From 363472827654e7a08801f4d2209feaf2cba50e11 Mon Sep 17 00:00:00 2001 From: Hein Jeong <73264629+hein-j@users.noreply.github.com> Date: Fri, 22 Jul 2022 10:40:14 -0700 Subject: [PATCH] chore: add valueMappings to forms (#537) Co-authored-by: Hein Jeong --- .../helpers/form-field.test.ts | 103 +++++++++++--- .../helpers/model-fields-configs.test.ts | 129 ++++++++++++++---- .../helpers/defaults.ts | 2 +- .../helpers/field-type-map.ts | 8 +- .../helpers/form-field.ts | 49 +++++-- .../helpers/mapper-utils.ts | 17 +++ .../helpers/model-fields-configs.ts | 55 ++++++-- .../lib/generate-form-definition/index.ts | 7 +- .../lib/types/form/form-definition-element.ts | 9 +- .../lib/types/form/form-definition.ts | 19 +++ packages/codegen-ui/lib/types/form/index.ts | 6 +- .../codegen-ui/lib/types/form/input-config.ts | 22 ++- 12 files changed, 353 insertions(+), 73 deletions(-) diff --git a/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/form-field.test.ts b/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/form-field.test.ts index 6f213b8a6..5931a5eb3 100644 --- a/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/form-field.test.ts +++ b/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/form-field.test.ts @@ -15,6 +15,7 @@ */ import { mapFormFieldConfig, getFormDefinitionInputElement } from '../../../generate-form-definition/helpers'; +import { mergeValueMappings } from '../../../generate-form-definition/helpers/form-field'; import { FormDefinition, ModelFieldsConfigs, StudioFormFieldConfig, StudioGenericFieldConfig } from '../../../types'; describe('mapFormFieldConfig', () => { @@ -147,10 +148,7 @@ describe('getFormDefinitionInputElement', () => { inputType: { type: 'SelectField', readOnly: true, - valueMappings: [ - { displayValue: 'value1Display', value: 'value1' }, - { displayValue: 'value2Display', value: 'value2' }, - ], + valueMappings: { values: [{ value: { value: 'value1' }, displayvalue: { value: 'displayValue1' } }] }, defaultValue: 'value1', }, }; @@ -158,10 +156,10 @@ describe('getFormDefinitionInputElement', () => { expect(getFormDefinitionInputElement(config)).toStrictEqual({ componentType: 'SelectField', props: { label: 'Label', isDisabled: true }, - options: [ - { value: 'value1', children: 'value1Display' }, - { value: 'value2', children: 'value2Display' }, - ], + valueMappings: { + values: [{ value: { value: 'value1' }, displayvalue: { value: 'displayValue1' } }], + bindingProperties: {}, + }, defaultValue: 'value1', }); }); @@ -289,20 +287,35 @@ describe('getFormDefinitionInputElement', () => { inputType: { type: 'RadioGroupField', name: 'MyFieldName', - valueMappings: [ - { displayValue: 'value1Display', value: 'value1' }, - { displayValue: 'value2Display', value: 'value2' }, - ], + valueMappings: { values: [{ value: { value: 'value1' }, displayvalue: { value: 'displayValue1' } }] }, + }, + }; + + expect(getFormDefinitionInputElement(config)).toStrictEqual({ + componentType: 'RadioGroupField', + props: { label: 'Label', name: 'MyFieldName' }, + valueMappings: { + values: [{ value: { value: 'value1' }, displayvalue: { value: 'displayValue1' } }], + bindingProperties: {}, + }, + }); + }); + + it('should return default valueMappings for RadioGroupField if no values available', () => { + const config = { + inputType: { + type: 'RadioGroupField', + name: 'MyFieldName', + valueMappings: { values: [] }, }, }; expect(getFormDefinitionInputElement(config)).toStrictEqual({ componentType: 'RadioGroupField', props: { label: 'Label', name: 'MyFieldName' }, - radios: [ - { value: 'value1', children: 'value1Display' }, - { value: 'value2', children: 'value2Display' }, - ], + valueMappings: { + values: [{ value: { value: 'value' }, displayValue: { value: 'Label' } }], + }, }); }); @@ -322,3 +335,61 @@ describe('getFormDefinitionInputElement', () => { expect(() => getFormDefinitionInputElement(config)).toThrow(); }); }); + +describe('mergeValueMappings', () => { + it('should return override values if no base values', () => { + expect(mergeValueMappings(undefined, { values: [{ value: { value: 'value1' } }] }).values).toStrictEqual([ + { value: { value: 'value1' } }, + ]); + }); + + it('should return base values if no override values', () => { + expect(mergeValueMappings({ values: [{ value: { value: 'value1' } }] }, undefined).values).toStrictEqual([ + { value: { value: 'value1' } }, + ]); + }); + + it('should only return base values with overrides applied if both base and overrides present', () => { + const mergedMappings = mergeValueMappings( + { + values: [ + { value: { value: 'NEW_YORK' }, displayValue: { value: 'New york' } }, + { value: { value: 'HOUSTON' }, displayValue: { value: 'Houston' } }, + { value: { value: 'LOS_ANGELES' }, displayValue: { value: 'Los angeles' } }, + ], + }, + { + values: [ + { value: { value: 'LOS_ANGELES' }, displayValue: { value: 'LA' } }, + { value: { value: 'AUSTIN' }, displayValue: { value: 'Austin' } }, + ], + }, + ); + + expect(mergedMappings.values).toStrictEqual([ + { value: { value: 'NEW_YORK' }, displayValue: { value: 'New york' } }, + { value: { value: 'HOUSTON' }, displayValue: { value: 'Houston' } }, + { value: { value: 'LOS_ANGELES' }, displayValue: { value: 'LA' } }, + ]); + + expect(mergedMappings.values.find((v) => 'value' in v.value && v.value.value === 'AUSTIN')).toBeUndefined(); + }); + + it('should merge base and override bindingProperties', () => { + expect( + mergeValueMappings( + { + values: [{ value: { value: 'sdjoiflj' }, displayValue: { bindingProperties: { property: 'Dog' } } }], + bindingProperties: { + Dog: { type: 'Data', bindingProperties: { model: 'Dog' } }, + Person: { type: 'Data', bindingProperties: { model: 'Person' } }, + }, + }, + { values: [], bindingProperties: { Dog: { type: 'Data', bindingProperties: { model: 'MyDog' } } } }, + ).bindingProperties, + ).toStrictEqual({ + Person: { type: 'Data', bindingProperties: { model: 'Person' } }, + Dog: { type: 'Data', bindingProperties: { model: 'MyDog' } }, + }); + }); +}); diff --git a/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/model-fields-configs.test.ts b/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/model-fields-configs.test.ts index 7a15842af..3cd9f1915 100644 --- a/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/model-fields-configs.test.ts +++ b/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/model-fields-configs.test.ts @@ -14,7 +14,7 @@ limitations under the License. */ -import { mapModelFieldsConfigs } from '../../../generate-form-definition/helpers'; +import { mapModelFieldsConfigs, getFieldTypeMapKey } from '../../../generate-form-definition/helpers'; import { FormDefinition, ModelFieldsConfigs, GenericDataSchema } from '../../../types'; describe('mapModelFieldsConfigs', () => { @@ -106,7 +106,7 @@ describe('mapModelFieldsConfigs', () => { ).toThrow(); }); - it('should throw if there is no default component', () => { + it('should generate config from id field but not add it to matrix', () => { const formDefinition: FormDefinition = { form: { layoutStyle: {} }, elements: {}, @@ -116,25 +116,37 @@ describe('mapModelFieldsConfigs', () => { const modelFieldsConfigs: ModelFieldsConfigs = {}; - const dataSchema: any = { + const dataSchema: GenericDataSchema = { dataSourceType: 'DataStore', enums: {}, nonModels: {}, models: { Dog: { fields: { - names: { dataType: 'ErrantType', readOnly: false, required: false, isArray: true }, + id: { dataType: 'ID', readOnly: false, required: true, isArray: false }, }, }, }, }; - expect(() => - mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, modelFieldsConfigs, dataSchema }), - ).toThrow(); + mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, modelFieldsConfigs, dataSchema }); + + expect(formDefinition.elementMatrix).toStrictEqual([]); + expect(modelFieldsConfigs).toStrictEqual({ + id: { + inputType: { + name: 'id', + readOnly: false, + required: true, + type: 'TextField', + value: 'true', + }, + label: 'id', + }, + }); }); - it('should generate config from id field but not add it to matrix', () => { + it('should add read-only fields to configs but not to matrix', () => { const formDefinition: FormDefinition = { form: { layoutStyle: {} }, elements: {}, @@ -151,7 +163,7 @@ describe('mapModelFieldsConfigs', () => { models: { Dog: { fields: { - id: { dataType: 'ID', readOnly: false, required: true, isArray: false }, + name: { dataType: 'String', readOnly: true, required: false, isArray: false }, }, }, }, @@ -161,20 +173,20 @@ describe('mapModelFieldsConfigs', () => { expect(formDefinition.elementMatrix).toStrictEqual([]); expect(modelFieldsConfigs).toStrictEqual({ - id: { + name: { inputType: { - name: 'id', - readOnly: false, - required: true, + name: 'name', + readOnly: true, + required: false, type: 'TextField', value: 'true', }, - label: 'id', + label: 'name', }, }); }); - it('should add read-only fields to configs but not to matrix', () => { + it('should add value mappings from enums', () => { const formDefinition: FormDefinition = { form: { layoutStyle: {} }, elements: {}, @@ -184,14 +196,16 @@ describe('mapModelFieldsConfigs', () => { const modelFieldsConfigs: ModelFieldsConfigs = {}; + const nonEnglishAlphabetTest = 'ㅎ🌱يَّة'; + const dataSchema: GenericDataSchema = { dataSourceType: 'DataStore', - enums: {}, + enums: { City: { values: ['NEW_YORK', 'HOUSTON', 'LOS_ANGELES', nonEnglishAlphabetTest] } }, nonModels: {}, models: { Dog: { fields: { - name: { dataType: 'String', readOnly: true, required: false, isArray: false }, + city: { dataType: { enum: 'City' }, readOnly: false, required: false, isArray: false }, }, }, }, @@ -199,18 +213,87 @@ describe('mapModelFieldsConfigs', () => { mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, modelFieldsConfigs, dataSchema }); - expect(formDefinition.elementMatrix).toStrictEqual([]); expect(modelFieldsConfigs).toStrictEqual({ - name: { + city: { inputType: { - name: 'name', - readOnly: true, + name: 'city', + readOnly: false, required: false, - type: 'TextField', + type: 'SelectField', value: 'true', + valueMappings: { + values: [ + { value: { value: 'NEW_YORK' }, displayValue: { value: 'New york' } }, + { value: { value: 'HOUSTON' }, displayValue: { value: 'Houston' } }, + { value: { value: 'LOS_ANGELES' }, displayValue: { value: 'Los angeles' } }, + { value: { value: nonEnglishAlphabetTest }, displayValue: { value: nonEnglishAlphabetTest } }, + ], + }, }, - label: 'name', + label: 'city', }, }); }); + + it('should throw if type is enum but no matching enum provided', () => { + const formDefinition: FormDefinition = { + form: { layoutStyle: {} }, + elements: {}, + buttons: {}, + elementMatrix: [], + }; + + const modelFieldsConfigs: ModelFieldsConfigs = {}; + + const dataSchema: GenericDataSchema = { + dataSourceType: 'DataStore', + enums: {}, + nonModels: {}, + models: { + Dog: { + fields: { + city: { dataType: { enum: 'City' }, readOnly: false, required: false, isArray: false }, + }, + }, + }, + }; + + expect(() => + mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, modelFieldsConfigs, dataSchema }), + ).toThrow(); + }); +}); + +describe('getFieldTypeMapKey', () => { + it('should return `Relationship` if field is of type model or has a related model', () => { + expect( + getFieldTypeMapKey({ + dataType: { model: 'Dog' }, + readOnly: false, + required: false, + isArray: false, + }), + ).toBe('Relationship'); + + expect( + getFieldTypeMapKey({ + dataType: 'ID', + readOnly: false, + required: false, + isArray: false, + relationship: { relatedModelName: 'Dog', type: 'HAS_ONE' }, + }), + ).toBe('Relationship'); + }); + + it('should return `NonModel` if dataType is nonModel', () => { + expect( + getFieldTypeMapKey({ + dataType: { nonModel: 'Misc' }, + readOnly: false, + required: false, + isArray: false, + }), + ).toBe('NonModel'); + }); }); diff --git a/packages/codegen-ui/lib/generate-form-definition/helpers/defaults.ts b/packages/codegen-ui/lib/generate-form-definition/helpers/defaults.ts index 66242858c..36682693b 100644 --- a/packages/codegen-ui/lib/generate-form-definition/helpers/defaults.ts +++ b/packages/codegen-ui/lib/generate-form-definition/helpers/defaults.ts @@ -33,7 +33,7 @@ export const FORM_DEFINITION_DEFAULTS = { defaultCountryCode: '+1', value: 'true', name: 'fieldName', - valueMappings: [{ value: 'value', displayValue: 'Label' }], + valueMappings: { values: [{ value: { value: 'value' }, displayValue: { value: 'Label' } }] }, }, }, diff --git a/packages/codegen-ui/lib/generate-form-definition/helpers/field-type-map.ts b/packages/codegen-ui/lib/generate-form-definition/helpers/field-type-map.ts index 147318fef..3f64ac80c 100644 --- a/packages/codegen-ui/lib/generate-form-definition/helpers/field-type-map.ts +++ b/packages/codegen-ui/lib/generate-form-definition/helpers/field-type-map.ts @@ -14,13 +14,13 @@ limitations under the License. */ -import { FormDefinitionInputElement } from '../../types'; +import { FormDefinitionInputElement, FieldTypeMapKeys } from '../../types'; /** * Maps data types to UI Components */ export const FIELD_TYPE_MAP: { - [key: string]: { + [key in FieldTypeMapKeys]: { defaultComponent: FormDefinitionInputElement['componentType']; supportedComponents: Set; }; @@ -89,4 +89,8 @@ export const FIELD_TYPE_MAP: { defaultComponent: 'SelectField', supportedComponents: new Set(['SelectField']), }, + NonModel: { + defaultComponent: 'TextAreaField', + supportedComponents: new Set(['TextAreaField']), + }, }; diff --git a/packages/codegen-ui/lib/generate-form-definition/helpers/form-field.ts b/packages/codegen-ui/lib/generate-form-definition/helpers/form-field.ts index 980715e59..904da50c8 100644 --- a/packages/codegen-ui/lib/generate-form-definition/helpers/form-field.ts +++ b/packages/codegen-ui/lib/generate-form-definition/helpers/form-field.ts @@ -19,17 +19,40 @@ import { StudioGenericFieldConfig, ModelFieldsConfigs, StudioFormFieldConfig, + StudioFormValueMappings, } from '../../types'; import { InternalError, InvalidInputError } from '../../errors'; import { FORM_DEFINITION_DEFAULTS } from './defaults'; import { deleteUndefined, getFirstDefinedValue, getFirstNumber, getFirstString } from './mapper-utils'; -function getOptionsFromValueMappings( - valueMappings: { displayValue: string; value: string }[], -): { value: string; children: string }[] { - return valueMappings.map(({ displayValue, value }) => { - return { value, children: displayValue }; - }); +export function mergeValueMappings( + base?: StudioFormValueMappings, + override?: StudioFormValueMappings, +): StudioFormValueMappings { + let values: StudioFormValueMappings['values'] = []; + + if (!base && override) { + values = override.values; + } else if (base && !override) { + values = base.values; + } else if (base && override) { + const overrideMap = new Map( + override.values.map(({ displayValue, value }) => [JSON.stringify(value), displayValue]), + ); + values = base.values.map(({ displayValue, value }) => { + const stringifiedBaseValue = JSON.stringify(value); + const overrideDisplayValue = overrideMap.get(stringifiedBaseValue); + if (overrideDisplayValue) { + return { displayValue: overrideDisplayValue, value }; + } + return { displayValue, value }; + }); + } + + return { + values, + bindingProperties: { ...base?.bindingProperties, ...override?.bindingProperties }, + }; } /** @@ -104,10 +127,9 @@ export function getFormDefinitionInputElement( placeholder: config.inputType?.placeholder || baseConfig?.inputType?.placeholder, isDisabled: getFirstDefinedValue([config.inputType?.readOnly, baseConfig?.inputType?.readOnly]), }, - options: getOptionsFromValueMappings( - config.inputType?.valueMappings || baseConfig?.inputType?.valueMappings || [], - ), + defaultValue: getFirstString([config.inputType?.defaultValue, baseConfig?.inputType?.defaultValue]), + valueMappings: mergeValueMappings(baseConfig?.inputType?.valueMappings, config.inputType?.valueMappings), }; break; @@ -200,11 +222,10 @@ export function getFormDefinitionInputElement( descriptiveText: config.inputType?.descriptiveText ?? baseConfig?.inputType?.descriptiveText, isRequired: getFirstDefinedValue([config.inputType?.required, baseConfig?.inputType?.required]), }, - radios: getOptionsFromValueMappings( - config.inputType?.valueMappings || - baseConfig?.inputType?.valueMappings || - FORM_DEFINITION_DEFAULTS.field.inputType.valueMappings, - ), + valueMappings: + baseConfig?.inputType?.valueMappings?.values.length || config?.inputType?.valueMappings?.values.length + ? mergeValueMappings(baseConfig?.inputType?.valueMappings, config.inputType?.valueMappings) + : FORM_DEFINITION_DEFAULTS.field.inputType.valueMappings, }; break; diff --git a/packages/codegen-ui/lib/generate-form-definition/helpers/mapper-utils.ts b/packages/codegen-ui/lib/generate-form-definition/helpers/mapper-utils.ts index d7ef709f5..9ef26f5c9 100644 --- a/packages/codegen-ui/lib/generate-form-definition/helpers/mapper-utils.ts +++ b/packages/codegen-ui/lib/generate-form-definition/helpers/mapper-utils.ts @@ -25,6 +25,23 @@ export function getFirstNumber(values: (string | number | undefined)[]): number return values.find((value) => typeof value === 'number') as number | undefined; } +export function convertToTitleCase(value: string): string { + const ReplaceMap: Record = { '-': ' ', _: ' ' }; + + return value + .split('') + .map((char, i) => { + if (ReplaceMap[char]) { + return ReplaceMap[char]; + } + if (i === 0) { + return char.toUpperCase(); + } + return char.toLowerCase(); + }) + .join(''); +} + /* eslint-disable no-param-reassign */ export function deleteUndefined(obj: { [key: string]: unknown }) { Object.entries(obj).forEach(([key, value]) => { diff --git a/packages/codegen-ui/lib/generate-form-definition/helpers/model-fields-configs.ts b/packages/codegen-ui/lib/generate-form-definition/helpers/model-fields-configs.ts index 2d6652595..0dcc2aa9f 100644 --- a/packages/codegen-ui/lib/generate-form-definition/helpers/model-fields-configs.ts +++ b/packages/codegen-ui/lib/generate-form-definition/helpers/model-fields-configs.ts @@ -14,9 +14,33 @@ limitations under the License. */ -import { FormDefinition, ModelFieldsConfigs, GenericDataSchema } from '../../types'; +import { + FormDefinition, + ModelFieldsConfigs, + StudioGenericFieldConfig, + StudioFieldInputConfig, + GenericDataSchema, + FieldTypeMapKeys, + GenericDataField, +} from '../../types'; import { FIELD_TYPE_MAP } from './field-type-map'; import { InvalidInputError } from '../../errors'; +import { convertToTitleCase } from './mapper-utils'; + +export function getFieldTypeMapKey(field: GenericDataField): FieldTypeMapKeys { + if (typeof field.dataType === 'object' && 'enum' in field.dataType) { + return 'Enum'; + } + + if ((typeof field.dataType === 'object' && 'model' in field.dataType) || field.relationship?.relatedModelName) { + return 'Relationship'; + } + + if (typeof field.dataType === 'object' && 'nonModel' in field.dataType) { + return 'NonModel'; + } + return field.dataType; +} /** * Impure function that adds fields from DataStore to temporary util object, modelFieldsConfigs @@ -45,21 +69,17 @@ export function mapModelFieldsConfigs({ throw new InvalidInputError('Array types are not yet supported'); } - const dataType = typeof field.dataType === 'string' ? field.dataType : Object.keys(field.dataType)[0]; - const defaultComponent = FIELD_TYPE_MAP[dataType]?.defaultComponent; - - if (!defaultComponent) { - throw new InvalidInputError('Field type could not be mapped to a component'); - } - const isAutoExcludedField = field.readOnly || (fieldName === 'id' && field.dataType === 'ID' && field.required); if (!isAutoExcludedField) { formDefinition.elementMatrix.push([fieldName]); } - // TODO: map Enums to valueMappings - modelFieldsConfigs[fieldName] = { + const fieldTypeMapKey = getFieldTypeMapKey(field); + + const { defaultComponent } = FIELD_TYPE_MAP[fieldTypeMapKey]; + + const config: StudioGenericFieldConfig & { inputType: StudioFieldInputConfig } = { label: fieldName, inputType: { type: defaultComponent, @@ -69,6 +89,21 @@ export function mapModelFieldsConfigs({ value: 'true', }, }; + + if (typeof field.dataType === 'object' && 'enum' in field.dataType) { + const fieldEnums = dataSchema.enums[field.dataType.enum]; + if (!fieldEnums) { + throw new InvalidInputError(`Values could not be found for enum ${field.dataType.enum}`); + } + config.inputType.valueMappings = { + values: fieldEnums.values.map((value) => ({ + displayValue: { value: convertToTitleCase(value) }, + value: { value }, + })), + }; + } + + modelFieldsConfigs[fieldName] = config; }); } /* eslint-enable no-param-reassign */ diff --git a/packages/codegen-ui/lib/generate-form-definition/index.ts b/packages/codegen-ui/lib/generate-form-definition/index.ts index 64f8fdb94..58b129a71 100644 --- a/packages/codegen-ui/lib/generate-form-definition/index.ts +++ b/packages/codegen-ui/lib/generate-form-definition/index.ts @@ -13,6 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -export { FIELD_TYPE_MAP, getFormDefinitionInputElement, getFormDefinitionSectionalElement } from './helpers'; +export { + FIELD_TYPE_MAP, + getFormDefinitionInputElement, + getFormDefinitionSectionalElement, + getFieldTypeMapKey, +} from './helpers'; export { generateFormDefinition } from './generate-form-definition'; export { mapFormDefinitionToComponent } from './form-to-component'; diff --git a/packages/codegen-ui/lib/types/form/form-definition-element.ts b/packages/codegen-ui/lib/types/form/form-definition-element.ts index 9526964ab..dea82a3e6 100644 --- a/packages/codegen-ui/lib/types/form/form-definition-element.ts +++ b/packages/codegen-ui/lib/types/form/form-definition-element.ts @@ -13,6 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. */ + +import { StudioFormValueMappings } from './input-config'; + export type FormDefinitionTextFieldElement = { componentType: 'TextField'; props: { @@ -47,7 +50,7 @@ export type FormDefinitionSelectFieldElement = { componentType: 'SelectField'; props: { label: string; descriptiveText?: string; placeholder?: string; isDisabled?: boolean }; // needs to be mapped as children of 'option' JSX elements - options: { value: string; children: string }[]; + valueMappings: StudioFormValueMappings; // 'selected' attr needs to be mapped onto the 'option' itself, not the SelectField defaultValue?: string; }; @@ -117,8 +120,8 @@ export type FormDefinitionRadioGroupFieldElement = { descriptiveText?: string; isRequired?: boolean; }; - // needs to be mapped as children of 'Radio' components - radios: { value: string; children: string }[]; + // needs to be mapped as children of 'Radio' JSX elements + valueMappings: StudioFormValueMappings; }; export type FormDefinitionPasswordFieldElement = { diff --git a/packages/codegen-ui/lib/types/form/form-definition.ts b/packages/codegen-ui/lib/types/form/form-definition.ts index 21fa08a4f..3d9d6be4e 100644 --- a/packages/codegen-ui/lib/types/form/form-definition.ts +++ b/packages/codegen-ui/lib/types/form/form-definition.ts @@ -28,3 +28,22 @@ export type FormDefinition = { elementMatrix: string[][]; inputFields?: string[]; }; + +export type FieldTypeMapKeys = + | 'ID' + | 'String' + | 'Int' + | 'Float' + | 'AWSDate' + | 'AWSTime' + | 'AWSDateTime' + | 'AWSTimestamp' + | 'AWSEmail' + | 'AWSURL' + | 'AWSIPAddress' + | 'Boolean' + | 'AWSJSON' + | 'AWSPhone' + | 'Enum' + | 'Relationship' + | 'NonModel'; diff --git a/packages/codegen-ui/lib/types/form/index.ts b/packages/codegen-ui/lib/types/form/index.ts index b592c1329..bca13746e 100644 --- a/packages/codegen-ui/lib/types/form/index.ts +++ b/packages/codegen-ui/lib/types/form/index.ts @@ -17,8 +17,8 @@ import { StudioFormStyle } from './style'; import { StudioFormFields, StudioFormFieldConfig, StudioGenericFieldConfig } from './fields'; import { SectionalElement } from './sectional-element'; -import { FormDefinition, ModelFieldsConfigs } from './form-definition'; -import { StudioFieldInputConfig } from './input-config'; +import { FormDefinition, ModelFieldsConfigs, FieldTypeMapKeys } from './form-definition'; +import { StudioFieldInputConfig, StudioFormValueMappings } from './input-config'; import { StudioFieldPosition } from './position'; import { FormMetadata } from './form-metadata'; @@ -66,4 +66,6 @@ export type { StudioFormFields, ModelFieldsConfigs, StudioFieldPosition, + FieldTypeMapKeys, + StudioFormValueMappings, }; diff --git a/packages/codegen-ui/lib/types/form/input-config.ts b/packages/codegen-ui/lib/types/form/input-config.ts index 7236817a3..584ac9328 100644 --- a/packages/codegen-ui/lib/types/form/input-config.ts +++ b/packages/codegen-ui/lib/types/form/input-config.ts @@ -14,6 +14,26 @@ limitations under the License. */ +import { + FixedStudioComponentProperty, + ConcatenatedStudioComponentProperty, + ConditionalStudioComponentProperty, + BoundStudioComponentProperty, +} from '../properties'; +import { StudioComponentPropertyBinding } from '../bindings'; + +export type StudioFormInputFieldProperty = + | FixedStudioComponentProperty + | ConcatenatedStudioComponentProperty + | ConditionalStudioComponentProperty + | BoundStudioComponentProperty; + +export type StudioFormValueMappings = { + values: { displayValue?: StudioFormInputFieldProperty; value: StudioFormInputFieldProperty }[]; + + bindingProperties?: { [propertyName: string]: StudioComponentPropertyBinding }; +}; + // represents API shape after type casting export type StudioFieldInputConfig = { type: string; @@ -32,7 +52,7 @@ export type StudioFieldInputConfig = { defaultCountryCode?: string; - valueMappings?: { value: string; displayValue: string }[]; + valueMappings?: StudioFormValueMappings; name?: string;