diff --git a/airbyte-webapp/src/core/form/types.ts b/airbyte-webapp/src/core/form/types.ts index 658d5e267884..f72e5630f087 100644 --- a/airbyte-webapp/src/core/form/types.ts +++ b/airbyte-webapp/src/core/form/types.ts @@ -1,31 +1,33 @@ -import { JSONSchema7Type, JSONSchema7TypeName } from "json-schema"; +import { JSONSchema7TypeName } from "json-schema"; import { AirbyteJSONSchema } from "core/jsonSchema"; -interface FormItem { +/** + * When turning the JSON schema into `FormBlock`s, + * some often used props are copied over for easy access. + */ +type FormRelevantJSONSchema = Pick< + AirbyteJSONSchema, + "default" | "examples" | "description" | "pattern" | "order" | "const" | "title" | "airbyte_hidden" | "enum" +>; + +interface FormItem extends FormRelevantJSONSchema { fieldKey: string; path: string; isRequired: boolean; - order?: number; - title?: string; - description?: string; - airbyte_hidden?: boolean; } -export interface FormBaseItem extends FormItem, AirbyteJSONSchema { +export interface FormBaseItem extends FormItem { _type: "formItem"; type: JSONSchema7TypeName; isSecret?: boolean; multiline?: boolean; - default?: JSONSchema7Type; } export interface FormGroupItem extends FormItem { _type: "formGroup"; jsonSchema: AirbyteJSONSchema; properties: FormBlock[]; - isLoading?: boolean; - examples?: JSONSchema7Type; } export interface FormConditionItem extends FormItem { diff --git a/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.test.ts b/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.test.ts index 2677b69e5025..a53dc531cb32 100644 --- a/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.test.ts +++ b/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.test.ts @@ -1,3 +1,5 @@ +import { FormGroupItem } from "core/form/types"; + import { jsonSchemaToUiWidget } from "./schemaToUiWidget"; import { AirbyteJSONSchemaDefinition } from "./types"; @@ -115,6 +117,55 @@ it("should reformat jsonSchema to internal widget representation", () => { expect(builtSchema).toEqual(expected); }); +it("should turn single enum into const but keep multi value enum", () => { + const schema: AirbyteJSONSchemaDefinition = { + type: "object", + required: ["a", "b", "c"], + properties: { + a: { type: "string", enum: ["val1", "val2"] }, + b: { type: "string", enum: ["val1"], default: "val1" }, + c: { type: "string", const: "val3" }, + }, + }; + + const builtSchema = jsonSchemaToUiWidget(schema, "key"); + + const expectedProperties = [ + { + _type: "formItem", + enum: ["val1", "val2"], + fieldKey: "a", + isRequired: true, + isSecret: false, + multiline: false, + path: "key.a", + type: "string", + }, + { + _type: "formItem", + const: "val1", + default: "val1", + fieldKey: "b", + isRequired: true, + isSecret: false, + multiline: false, + path: "key.b", + type: "string", + }, + { + _type: "formItem", + const: "val3", + fieldKey: "c", + isRequired: true, + isSecret: false, + multiline: false, + path: "key.c", + type: "string", + }, + ]; + expect((builtSchema as FormGroupItem).properties).toEqual(expectedProperties); +}); + it("should reformat jsonSchema to internal widget representation with parent schema", () => { const schema: AirbyteJSONSchemaDefinition = { type: "object", diff --git a/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.ts b/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.ts index 84807806940e..360105af13b0 100644 --- a/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.ts +++ b/airbyte-webapp/src/core/jsonSchema/schemaToUiWidget.ts @@ -1,3 +1,5 @@ +import pick from "lodash/pick"; + import { FormBlock } from "core/form/types"; import { isDefined } from "utils/common"; @@ -109,7 +111,7 @@ function isKeyRequired(key: string, parentSchema?: AirbyteJSONSchemaDefinition): return isRequired; } -const defaultFields: Array = [ +const defaultFields = [ "default", "examples", "description", @@ -117,24 +119,21 @@ const defaultFields: Array = [ "order", "const", "title", + "enum", // airbyte specific fields "airbyte_hidden", -]; +] as const; -const pickDefaultFields = (schema: AirbyteJSONSchema): Partial => { - const partialSchema: Partial = { - ...Object.fromEntries(Object.entries(schema).filter(([k]) => defaultFields.includes(k as keyof AirbyteJSONSchema))), - }; +const pickDefaultFields = (schema: AirbyteJSONSchema) => { + const partialSchema = pick(schema, defaultFields); if (typeof schema.items === "object" && !Array.isArray(schema.items) && schema.items.enum) { partialSchema.enum = schema.items.enum; - } else if (schema.enum) { - if (schema.enum?.length === 1 && isDefined(schema.default)) { - partialSchema.const = schema.default; - } else { - partialSchema.enum = schema.enum; - } + } else if (schema.enum && schema.enum?.length === 1 && isDefined(schema.default)) { + partialSchema.const = schema.default; + // remove enum key as it has been "picked" already above + delete partialSchema.enum; } return partialSchema;