diff --git a/packages/codegen-ui-react/lib/__tests__/__utils__/amplify-renderer-generator.ts b/packages/codegen-ui-react/lib/__tests__/__utils__/amplify-renderer-generator.ts index bdf85ec75..1459ba050 100644 --- a/packages/codegen-ui-react/lib/__tests__/__utils__/amplify-renderer-generator.ts +++ b/packages/codegen-ui-react/lib/__tests__/__utils__/amplify-renderer-generator.ts @@ -20,6 +20,7 @@ import { getGenericFromDataStore, StudioForm, StudioView, + FormFeatureFlags, } from '@aws-amplify/codegen-ui'; import { Schema } from '@aws-amplify/datastore'; import { createPrinter, createSourceFile, EmitHint, NewLineKind, Node } from 'typescript'; @@ -56,6 +57,7 @@ export const generateWithAmplifyFormRenderer = ( formJsonFile: string, dataSchemaJsonFile: string | undefined, renderConfig: ReactRenderConfig = defaultCLIRenderConfig, + featureFlags?: FormFeatureFlags, ): { componentText: string; declaration?: string } => { let dataSchema: GenericDataSchema | undefined; if (dataSchemaJsonFile) { @@ -63,7 +65,7 @@ export const generateWithAmplifyFormRenderer = ( dataSchema = getGenericFromDataStore(dataStoreSchema); } const rendererFactory = new StudioTemplateRendererFactory( - (component: StudioForm) => new AmplifyFormRenderer(component, dataSchema, renderConfig), + (component: StudioForm) => new AmplifyFormRenderer(component, dataSchema, renderConfig, featureFlags), ); const renderer = rendererFactory.buildRenderer(loadSchemaFromJSONFile(formJsonFile)); diff --git a/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts b/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts index d3362f864..a29af49fd 100644 --- a/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts +++ b/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts @@ -22,6 +22,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/post-datastore-create', 'datastore/post', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('DataStore.save'); expect(componentText).toContain('resetStateValues();'); @@ -33,6 +35,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/book-datastore-relationship', 'datastore/relationship', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // check nested model is imported expect(componentText).toContain('import { Book, Author } from "../models";'); @@ -48,6 +52,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/book-datastore-relationship-multiple', 'datastore/relationship-multiple', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // check nested model is imported expect(componentText).toContain('import { Book, Author, Title } from "../models";'); @@ -64,6 +70,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/member-datastore-create', 'datastore/project-team-model', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // check nested model is imported expect(componentText).toContain('import { Member, Team as Team0 } from "../models";'); @@ -79,6 +87,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/member-datastore-update-belongs-to', 'datastore/project-team-model', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // check nested model is imported expect(componentText).toContain('import { Member, Team as Team0 } from "../models";'); @@ -94,6 +104,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/member-datastore-create', 'datastore/project-team-model', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // Check that custom field label is working as expected expect(componentText).toContain('Team Label'); @@ -108,6 +120,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/tag-datastore-create', 'datastore/tag-post', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // check nested model is imported expect(componentText).toContain('import { Tag, Post, TagPost } from "../models";'); @@ -126,6 +140,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/tag-datastore-update', 'datastore/tag-post', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // check nested model is imported expect(componentText).toContain('import { Tag, Post, TagPost } from "../models";'); @@ -153,6 +169,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/tag-datastore-create', 'datastore/tag-post', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // get displayValue function expect(componentText).toContain('statuses: (r) => {'); @@ -171,6 +189,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/school-datastore-create', 'datastore/school-student', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // check nested model is imported expect(componentText).toContain('import { School, Student } from "../models";'); @@ -189,6 +209,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/school-datastore-update', 'datastore/school-student', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // check nested model is imported expect(componentText).toContain('import { School, Student } from "../models";'); @@ -216,6 +238,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/post-datastore-create-row', 'datastore/post', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('DataStore.save'); expect(componentText).toMatchSnapshot(); @@ -226,6 +250,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/post-datastore-update', 'datastore/post', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('DataStore.save'); expect(componentText).toMatchSnapshot(); @@ -236,6 +262,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/blog-datastore-create', 'datastore/blog', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('DataStore.save'); expect(componentText).toMatchSnapshot(); @@ -246,6 +274,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/input-gallery-create', 'datastore/input-gallery', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('DataStore.save'); expect(componentText).toContain('const convertToLocal'); @@ -257,6 +287,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/input-gallery-update', 'datastore/input-gallery', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('DataStore.save'); expect(componentText).toContain('const convertToLocal'); @@ -272,6 +304,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/flex-datastore-create', 'datastore/flex', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('DataStore.save'); expect(componentText).toContain('Flex0'); @@ -282,6 +316,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/flex-datastore-update', 'datastore/flex', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('DataStore.save'); expect(componentText).toContain('Flex0'); @@ -368,15 +404,29 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/post-datastore-create-with-custom-array', 'datastore/post', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toMatchSnapshot(); expect(declaration).toMatchSnapshot(); }); + it('should not render non-model fields if non-model support off', () => { + const { componentText } = generateWithAmplifyFormRenderer( + 'forms/post-datastore-create-with-custom-array', + 'datastore/post', + undefined, + ); + + expect(componentText).not.toContain('nonModelField'); + }); + it('should use matching case for ref when array field is capitalized', () => { const { componentText } = generateWithAmplifyFormRenderer( 'forms/post-datastore-create-with-custom-array', 'datastore/post', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toContain('const CustomtagsRef'); @@ -388,6 +438,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/cpk-teacher-datastore-update', 'datastore/cpk-relationships', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); // hasOne expect(componentText).toContain('specialTeacherId: specialTeacherIdProp'); @@ -416,6 +468,8 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/composite-dog-datastore-update', 'datastore/composite-relationships', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toMatchSnapshot(); @@ -426,11 +480,25 @@ describe('amplify form renderer tests', () => { const { componentText, declaration } = generateWithAmplifyFormRenderer( 'forms/composite-dog-datastore-create', 'datastore/composite-relationships', + undefined, + { isNonModelSupported: true, isRelationshipSupported: true }, ); expect(componentText).toMatchSnapshot(); expect(declaration).toMatchSnapshot(); }); + + it('should not render relationships if relationship support off', () => { + const { componentText } = generateWithAmplifyFormRenderer( + 'forms/composite-dog-datastore-create', + 'datastore/composite-relationships', + undefined, + ); + expect(componentText).not.toContain('CompositeBowl'); + expect(componentText).not.toContain('CompositeOwner'); + expect(componentText).not.toContain('CompositeToys'); + expect(componentText).not.toContain('CompositeVets'); + }); }); }); }); diff --git a/packages/codegen-ui-react/lib/forms/react-form-renderer.ts b/packages/codegen-ui-react/lib/forms/react-form-renderer.ts index 90741bc1d..89e2793e5 100644 --- a/packages/codegen-ui-react/lib/forms/react-form-renderer.ts +++ b/packages/codegen-ui-react/lib/forms/react-form-renderer.ts @@ -29,6 +29,7 @@ import { StudioNode, StudioTemplateRenderer, validateFormSchema, + FormFeatureFlags, } from '@aws-amplify/codegen-ui'; import { EOL } from 'os'; import { @@ -131,7 +132,12 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer< protected primaryKeys: string[] | undefined; - constructor(component: StudioForm, dataSchema: GenericDataSchema | undefined, renderConfig: ReactRenderConfig) { + constructor( + component: StudioForm, + dataSchema: GenericDataSchema | undefined, + renderConfig: ReactRenderConfig, + featureFlags?: FormFeatureFlags, + ) { super(component, new ReactOutputManager(), renderConfig); this.renderConfig = { ...defaultRenderConfig, @@ -140,7 +146,7 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer< // the super class creates a component aka form which is what we pass in this extended implmentation this.fileName = `${this.component.name}.${scriptKindToFileExtension(this.renderConfig.script)}`; - this.formDefinition = generateFormDefinition({ form: component, dataSchema }); + this.formDefinition = generateFormDefinition({ form: component, dataSchema, featureFlags }); // create a studio component which will represent the structure of the form this.formComponent = mapFormDefinitionToComponent(this.component.name, this.formDefinition); diff --git a/packages/codegen-ui/lib/__tests__/check-support.test.ts b/packages/codegen-ui/lib/__tests__/check-support.test.ts index 1acd25977..5c0496468 100644 --- a/packages/codegen-ui/lib/__tests__/check-support.test.ts +++ b/packages/codegen-ui/lib/__tests__/check-support.test.ts @@ -61,7 +61,7 @@ describe('checkIsSupportedAsForm', () => { expect(checkIsSupportedAsForm(model)).toBe(false); }); - it('should support relationships', () => { + it('should support relationships if relationship is enabled', () => { const model: GenericDataModel = { primaryKeys: ['id'], fields: { @@ -75,6 +75,23 @@ describe('checkIsSupportedAsForm', () => { }, }; - expect(checkIsSupportedAsForm(model)).toBe(true); + expect(checkIsSupportedAsForm(model, { isRelationshipSupported: true })).toBe(true); + }); + + it('should not support relationships if relationship is not enabled', () => { + const model: GenericDataModel = { + primaryKeys: ['id'], + fields: { + relationship: { + dataType: 'ID', + required: true, + readOnly: false, + isArray: false, + relationship: { type: 'HAS_ONE', relatedModelName: 'RelatedModel' }, + }, + }, + }; + + expect(checkIsSupportedAsForm(model)).toBe(false); }); }); 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 f0ec032c2..08e68ce8a 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 @@ -168,7 +168,7 @@ describe('mapModelFieldsConfigs', () => { }); }); - it('should add model-type relationship fields to configs and matrix', () => { + it('should add model-type relationship fields to matrix if relationship enabled', () => { const formDefinition: FormDefinition = getBasicFormDefinition(); const dataSchema: GenericDataSchema = { @@ -195,7 +195,12 @@ describe('mapModelFieldsConfigs', () => { }, }; - const modelFieldsConfigs = mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, dataSchema }); + const modelFieldsConfigs = mapModelFieldsConfigs({ + dataTypeName: 'Dog', + formDefinition, + dataSchema, + featureFlags: { isRelationshipSupported: true }, + }); expect(formDefinition.elementMatrix).toStrictEqual([['Owner']]); expect(modelFieldsConfigs).toStrictEqual({ @@ -219,6 +224,57 @@ describe('mapModelFieldsConfigs', () => { }); }); + it('should not add model-type relationship fields matrix if relationship not enabled', () => { + const formDefinition: FormDefinition = getBasicFormDefinition(); + + const dataSchema: GenericDataSchema = { + dataSourceType: 'DataStore', + enums: {}, + nonModels: {}, + models: { + Owner: { + primaryKeys: ['id'], + fields: {}, + }, + Dog: { + primaryKeys: ['id'], + fields: { + Owner: { + dataType: { model: 'Owner' }, + readOnly: false, + required: false, + isArray: false, + relationship: { type: 'HAS_ONE', relatedModelName: 'Owner' }, + }, + }, + }, + }, + }; + + const modelFieldsConfigs = mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, dataSchema }); + + expect(formDefinition.elementMatrix).toStrictEqual([]); + expect(modelFieldsConfigs).toStrictEqual({ + Owner: { + dataType: { model: 'Owner' }, + inputType: { + name: 'Owner', + readOnly: false, + required: false, + type: 'Autocomplete', + value: 'Owner', + isArray: false, + valueMappings: { + values: [{ value: { bindingProperties: { property: 'Owner', field: 'id' } } }], + bindingProperties: { Owner: { type: 'Data', bindingProperties: { model: 'Owner' } } }, + }, + }, + label: 'Owner', + relationship: { relatedModelName: 'Owner', type: 'HAS_ONE' }, + }, + }); + }); + it('should add not-model type relationship fields to configs but not to matrix', () => { const formDefinition: FormDefinition = getBasicFormDefinition(); @@ -270,7 +326,7 @@ describe('mapModelFieldsConfigs', () => { }); }); - it('should add nonModel field to matrix', () => { + it('should add nonModel field to matrix if nonModel enabled', () => { const formDefinition: FormDefinition = getBasicFormDefinition(); const dataSchema: GenericDataSchema = { @@ -292,7 +348,12 @@ describe('mapModelFieldsConfigs', () => { }, }; - const modelFieldsConfigs = mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, dataSchema }); + const modelFieldsConfigs = mapModelFieldsConfigs({ + dataTypeName: 'Dog', + formDefinition, + dataSchema, + featureFlags: { isNonModelSupported: true }, + }); expect(modelFieldsConfigs).toStrictEqual({ ownerId: { @@ -313,6 +374,49 @@ describe('mapModelFieldsConfigs', () => { expect(formDefinition.elementMatrix).toStrictEqual([['ownerId']]); }); + it('should not add nonModel field to matrix if nonModel not supported', () => { + const formDefinition: FormDefinition = getBasicFormDefinition(); + + const dataSchema: GenericDataSchema = { + dataSourceType: 'DataStore', + enums: {}, + nonModels: { Interaction: { fields: {} } }, + models: { + Dog: { + primaryKeys: ['id'], + fields: { + ownerId: { + dataType: { nonModel: 'Interaction' }, + readOnly: false, + required: false, + isArray: false, + }, + }, + }, + }, + }; + + const modelFieldsConfigs = mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, dataSchema }); + + expect(modelFieldsConfigs).toStrictEqual({ + ownerId: { + dataType: { + nonModel: 'Interaction', + }, + inputType: { + isArray: false, + name: 'ownerId', + readOnly: false, + required: false, + type: 'TextAreaField', + value: 'ownerId', + }, + label: 'Owner id', + }, + }); + expect(formDefinition.elementMatrix).toStrictEqual([]); + }); + it('should add value mappings from enums', () => { const formDefinition: FormDefinition = getBasicFormDefinition(); diff --git a/packages/codegen-ui/lib/__tests__/utils/form-component-metadata.test.ts b/packages/codegen-ui/lib/__tests__/utils/form-component-metadata.test.ts index 9dda3e20b..03553bc00 100644 --- a/packages/codegen-ui/lib/__tests__/utils/form-component-metadata.test.ts +++ b/packages/codegen-ui/lib/__tests__/utils/form-component-metadata.test.ts @@ -95,7 +95,10 @@ describe('mapFormMetaData', () => { cta: {}, }; - const { fieldConfigs } = mapFormMetadata(form, generateFormDefinition({ form, dataSchema })); + const { fieldConfigs } = mapFormMetadata( + form, + generateFormDefinition({ form, dataSchema, featureFlags: { isRelationshipSupported: true } }), + ); expect('Teachers' in fieldConfigs).toBe(true); expect(fieldConfigs.Teachers.isArray).toBe(true); @@ -117,7 +120,10 @@ describe('mapFormMetaData', () => { cta: {}, }; - const { fieldConfigs } = mapFormMetadata(form, generateFormDefinition({ form, dataSchema })); + const { fieldConfigs } = mapFormMetadata( + form, + generateFormDefinition({ form, dataSchema, featureFlags: { isRelationshipSupported: true } }), + ); expect('CPKStudent' in fieldConfigs).toBe(true); expect(fieldConfigs.CPKStudent.relationship).toStrictEqual({ diff --git a/packages/codegen-ui/lib/check-support.ts b/packages/codegen-ui/lib/check-support.ts index 4fcc3c8d2..17be674f2 100644 --- a/packages/codegen-ui/lib/check-support.ts +++ b/packages/codegen-ui/lib/check-support.ts @@ -13,19 +13,26 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { DataFieldDataType, GenericDataField, GenericDataModel } from './types'; +import { DataFieldDataType, GenericDataField, GenericDataModel, FormFeatureFlags } from './types'; export const isNonModelDataType = (dataType?: DataFieldDataType): boolean => { return typeof dataType === 'object' && 'nonModel' in dataType; }; +// TODO: change so that default is supported once GA release +const isRelationshipSupported = (featureFlags: FormFeatureFlags | undefined) => featureFlags?.isRelationshipSupported; + +// TODO: change so that default is supported once GA release +const isNonModelSupported = (featureFlags: FormFeatureFlags | undefined) => featureFlags?.isNonModelSupported; + /** * Checks whether a field is supported as a form input */ -export const checkIsSupportedAsFormField = (field: GenericDataField): boolean => { +export const checkIsSupportedAsFormField = (field: GenericDataField, featureFlags?: FormFeatureFlags): boolean => { const unsupportedFieldMap: { [key: string]: (f: GenericDataField) => boolean } = { - nonModel: (f) => typeof f.dataType === 'object' && 'nonModel' in f.dataType, + nonModel: (f) => !isNonModelSupported(featureFlags) && typeof f.dataType === 'object' && 'nonModel' in f.dataType, + relationship: (f) => !isRelationshipSupported(featureFlags) && !!f.relationship, }; const unsupportedArray = Object.values(unsupportedFieldMap); @@ -34,7 +41,7 @@ export const checkIsSupportedAsFormField = (field: GenericDataField): boolean => /** * Checks whether a form should be autogen'd from the given model */ -export const checkIsSupportedAsForm = (model: GenericDataModel): boolean => { +export const checkIsSupportedAsForm = (model: GenericDataModel, featureFlags?: FormFeatureFlags): boolean => { const fieldsArray = Object.values(model.fields); // no empty forms @@ -45,7 +52,7 @@ export const checkIsSupportedAsForm = (model: GenericDataModel): boolean => { let unsupportedFieldsCount = 0; const hasRequiredUnsupportedField = fieldsArray.some((field) => { - const isUnsupported = !checkIsSupportedAsFormField(field); + const isUnsupported = !checkIsSupportedAsFormField(field, featureFlags); if (isUnsupported) { unsupportedFieldsCount += 1; diff --git a/packages/codegen-ui/lib/generate-form-definition/generate-form-definition.ts b/packages/codegen-ui/lib/generate-form-definition/generate-form-definition.ts index 3bcab5007..0f0495995 100644 --- a/packages/codegen-ui/lib/generate-form-definition/generate-form-definition.ts +++ b/packages/codegen-ui/lib/generate-form-definition/generate-form-definition.ts @@ -15,7 +15,14 @@ */ import { mapModelFieldsConfigs, mapElementMatrix, mapStyles, mapElements, mapButtons } from './helpers'; -import { StudioForm, FormDefinition, ModelFieldsConfigs, StudioFieldPosition, GenericDataSchema } from '../types'; +import { + StudioForm, + FormDefinition, + ModelFieldsConfigs, + StudioFieldPosition, + GenericDataSchema, + FormFeatureFlags, +} from '../types'; import { InvalidInputError } from '../errors'; /** @@ -28,9 +35,11 @@ import { InvalidInputError } from '../errors'; export function generateFormDefinition({ form, dataSchema, + featureFlags, }: { form: StudioForm; dataSchema?: GenericDataSchema; + featureFlags?: FormFeatureFlags; }): FormDefinition { const formDefinition: FormDefinition = { form: { layoutStyle: mapStyles(form.style) }, @@ -56,6 +65,7 @@ export function generateFormDefinition({ formDefinition, dataTypeName: form.dataType.dataTypeName, formActionType: form.formActionType, + featureFlags, }); } 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 a7af42c2d..cd91ae603 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 @@ -15,11 +15,13 @@ */ import { sentenceCase } from 'change-case'; +import { checkIsSupportedAsFormField } from '../../check-support'; import { InvalidInputError } from '../../errors'; import { FieldTypeMapKeys, FormDefinition, + FormFeatureFlags, GenericDataField, GenericDataModel, GenericDataSchema, @@ -159,11 +161,13 @@ export function mapModelFieldsConfigs({ formDefinition, dataSchema, formActionType, + featureFlags, }: { dataTypeName: string; dataSchema: GenericDataSchema; formDefinition: FormDefinition; formActionType?: StudioForm['formActionType']; + featureFlags?: FormFeatureFlags; }) { const modelFieldsConfigs: ModelFieldsConfigs = {}; const model = dataSchema.models[dataTypeName]; @@ -176,6 +180,7 @@ export function mapModelFieldsConfigs({ const isAutoExcludedField = field.readOnly || (fieldName === 'id' && field.dataType === 'ID' && field.required) || + !checkIsSupportedAsFormField(field, featureFlags) || (field.relationship && !(typeof field.dataType === 'object' && 'model' in field.dataType)); if (!isAutoExcludedField) { diff --git a/packages/codegen-ui/lib/types/featureFlags.ts b/packages/codegen-ui/lib/types/featureFlags.ts new file mode 100644 index 000000000..561a4f502 --- /dev/null +++ b/packages/codegen-ui/lib/types/featureFlags.ts @@ -0,0 +1,19 @@ +/* + Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"). + You may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +export type FormFeatureFlags = { + isRelationshipSupported?: boolean; + isNonModelSupported?: boolean; +}; diff --git a/packages/codegen-ui/lib/types/index.ts b/packages/codegen-ui/lib/types/index.ts index f152ef4f2..14390a023 100644 --- a/packages/codegen-ui/lib/types/index.ts +++ b/packages/codegen-ui/lib/types/index.ts @@ -31,5 +31,6 @@ export * from './form'; export * from './view'; export * from './data'; export * from './string-format'; +export * from './featureFlags'; export type StudioSchema = StudioComponent | StudioForm | StudioView | StudioTheme; diff --git a/packages/test-generator/lib/generators/NodeTestGenerator.ts b/packages/test-generator/lib/generators/NodeTestGenerator.ts index 390872da0..2e79e886f 100644 --- a/packages/test-generator/lib/generators/NodeTestGenerator.ts +++ b/packages/test-generator/lib/generators/NodeTestGenerator.ts @@ -74,7 +74,11 @@ export class NodeTestGenerator extends TestGenerator { ); this.formRendererFactory = new StudioTemplateRendererFactory( - (form: StudioForm) => new AmplifyFormRenderer(form, getGenericFromDataStore(schema), this.renderConfig), + (form: StudioForm) => + new AmplifyFormRenderer(form, getGenericFromDataStore(schema), this.renderConfig, { + isNonModelSupported: true, + isRelationshipSupported: true, + }), ); this.viewRendererFactory = new StudioTemplateRendererFactory( (view: StudioView) => new AmplifyViewRenderer(view, getGenericFromDataStore(schema), this.renderConfig),