Skip to content

Commit

Permalink
fix: use related fields for has_one and belongs_to properties when bu…
Browse files Browse the repository at this point in the history
…ilding GraphQL API payloads
  • Loading branch information
awinberg-aws committed Aug 8, 2023
1 parent af94de2 commit e12116a
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 85 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1001,9 +1001,9 @@ describe('amplify form renderer tests', () => {
);

expect(componentText).toContain('postCommentsId');
expect(componentText).not.toContain('postID');
expect(componentText).not.toContain('userCommentsId');
expect(componentText).not.toContain('orgCommentsId');
expect(componentText).toContain('postID');
expect(componentText).toContain('userCommentsId');
expect(componentText).toContain('orgCommentsId');
expect(componentText).toMatchSnapshot();
expect(declaration).toMatchSnapshot();
});
Expand Down
8 changes: 7 additions & 1 deletion packages/codegen-ui-react/lib/amplify-ui-renderers/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,13 @@ export default class FormRenderer extends ReactComponentRenderer<BaseComponentPr
[],
),
),
buildModelFieldObject(dataSourceType !== 'DataStore', formMetadata?.fieldConfigs),
buildModelFieldObject(
dataSourceType !== 'DataStore',
formMetadata?.fieldConfigs,
this.componentMetadata.dataSchemaMetadata?.models,
undefined,
this.isRenderingGraphQL(),
),
...onSubmitValidationRun(hasModelField),
...this.getOnSubmitDSCall(),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ export const addFormAttributes = (
if (formMetadata.formActionType === 'update' && !fieldConfig.isArray && !isControlledComponent(componentType)) {
attributes.push(renderDefaultValueAttribute(renderedVariableName, fieldConfig, componentType));
}
attributes.push(buildOnChangeStatement(component, formMetadata.fieldConfigs, dataApi));
attributes.push(
buildOnChangeStatement(component, formMetadata.fieldConfigs, dataApi, dataSchema?.models, dataApi === 'GraphQL'),
);
attributes.push(buildOnBlurStatement(componentName, fieldConfig));
attributes.push(
factory.createJsxAttribute(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
isValidVariableName,
shouldIncludeCancel,
InvalidInputError,
GenericDataModel,
} from '@aws-amplify/codegen-ui';
import {
BindingElement,
Expand Down Expand Up @@ -211,6 +212,8 @@ export const buildOverrideOnChangeStatement = (
fieldName: string,
fieldConfigs: Record<string, FieldConfigMetadata>,
valueNameOverride?: Identifier,
models?: Record<string, GenericDataModel>,
isRenderingGraphQL = false,
): IfStatement => {
const keyPath = fieldName.split('.');
const keyName = keyPath[0];
Expand All @@ -229,9 +232,15 @@ export const buildOverrideOnChangeStatement = (
factory.createIdentifier('onChange'),
factory.createBlock(
[
buildModelFieldObject(true, fieldConfigs, {
[keyName]: keyValueExpression,
}),
buildModelFieldObject(
true,
fieldConfigs,
models || {},
{
[keyName]: keyValueExpression,
},
isRenderingGraphQL,
),
factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
Expand Down Expand Up @@ -286,7 +295,9 @@ function getCallbackVarName(fieldType: string): string {
export const buildOnChangeStatement = (
component: StudioComponent | StudioComponentChild,
fieldConfigs: Record<string, FieldConfigMetadata>,
dataApi?: DataApiKind,
dataApi: DataApiKind | undefined,
models: Record<string, GenericDataModel> = {},
isRenderingGraphQL = false,
) => {
const { name: fieldName, componentType: fieldType } = component;
const fieldConfig = fieldConfigs[fieldName];
Expand All @@ -309,7 +320,9 @@ export const buildOnChangeStatement = (
}

if (!shouldWrapInArrayField(fieldConfig)) {
handleChangeStatements.push(buildOverrideOnChangeStatement(fieldName, fieldConfigs));
handleChangeStatements.push(
buildOverrideOnChangeStatement(fieldName, fieldConfigs, undefined, models, isRenderingGraphQL),
);
}

handleChangeStatements.push(getOnChangeValidationBlock(fieldName));
Expand Down Expand Up @@ -515,6 +528,7 @@ export const buildStorageManagerOnChangeStatement = (
component: StudioComponent | StudioComponentChild,
fieldConfigs: Record<string, FieldConfigMetadata>,
handlerName: 'onUploadSuccess' | 'onFileRemove',
isRenderingGraphQL: boolean,
) => {
const { name: fieldName } = component;
const fieldConfig = fieldConfigs[fieldName];
Expand Down Expand Up @@ -581,7 +595,7 @@ export const buildStorageManagerOnChangeStatement = (
NodeFlags.Let,
),
),
buildOverrideOnChangeStatement(fieldName, fieldConfigs),
buildOverrideOnChangeStatement(fieldName, fieldConfigs, undefined, undefined, isRenderingGraphQL),
factory.createReturnStatement(factory.createIdentifier('value')),
],
true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
limitations under the License.
*/
import { factory, NodeFlags, ObjectLiteralElementLike } from 'typescript';
import { FieldConfigMetadata } from '@aws-amplify/codegen-ui';
import { FieldConfigMetadata, GenericDataModel } from '@aws-amplify/codegen-ui';

/**
* builds modelFields object which is used to validate, onSubmit, onSuccess/onError
Expand All @@ -33,30 +33,49 @@ import { FieldConfigMetadata } from '@aws-amplify/codegen-ui';
export const buildModelFieldObject = (
shouldBeConst: boolean,
fieldConfigs: Record<string, FieldConfigMetadata> = {},
models: Record<string, GenericDataModel> = {},
nameOverrides: Record<string, ObjectLiteralElementLike> = {},
isRenderingGraphQL = false,
) => {
const fieldSet = new Set<string>();
const fields = Object.keys(fieldConfigs).reduce<ObjectLiteralElementLike[]>((acc, value) => {
const fieldName = value.split('.')[0];
const { sanitizedFieldName } = fieldConfigs[value];
const { sanitizedFieldName, relationship } = fieldConfigs[value];
const renderedFieldName = sanitizedFieldName || fieldName;
if (!fieldSet.has(renderedFieldName)) {
let assignment: ObjectLiteralElementLike = factory.createShorthandPropertyAssignment(
factory.createIdentifier(fieldName),
undefined,
);

let assignments: ObjectLiteralElementLike[] = [
factory.createShorthandPropertyAssignment(factory.createIdentifier(fieldName), undefined),
];
if (nameOverrides[fieldName]) {
assignment = nameOverrides[fieldName];
assignments = [nameOverrides[fieldName]];
} else if (
isRenderingGraphQL &&
typeof fieldConfigs[value].dataType === 'object' &&
relationship &&
(relationship.type === 'BELONGS_TO' || relationship.type === 'HAS_ONE')
) {
assignments =
relationship.associatedFields?.map((associatedField, index) => {
return factory.createPropertyAssignment(
factory.createStringLiteral(associatedField),
factory.createPropertyAccessChain(
factory.createIdentifier(fieldName),
undefined,
models[relationship.relatedModelName].primaryKeys[index],
),
);
}) || [];
} else if (sanitizedFieldName) {
// if overrides present, ignore sanitizedFieldName
assignment = factory.createPropertyAssignment(
factory.createStringLiteral(fieldName),
factory.createIdentifier(sanitizedFieldName),
);
assignments = [
factory.createPropertyAssignment(
factory.createStringLiteral(fieldName),
factory.createIdentifier(sanitizedFieldName),
),
];
}

acc.push(assignment);
acc.push(...assignments);
fieldSet.add(renderedFieldName);
}
return acc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
import { FieldConfigMetadata, LabelDecorator } from '@aws-amplify/codegen-ui';
import { FieldConfigMetadata, GenericDataModel, LabelDecorator } from '@aws-amplify/codegen-ui';
import { Expression, factory, Identifier, JsxAttribute, JsxChild, NodeFlags, SyntaxKind } from 'typescript';
import {
buildAccessChain,
Expand All @@ -38,12 +38,16 @@ function getOnChangeAttribute({
renderedFieldName,
fieldConfigs,
isLimitedToOneValue,
models,
isRenderingGraphQL,
}: {
setStateName: Identifier;
fieldName: string;
renderedFieldName: string;
fieldConfigs: Record<string, FieldConfigMetadata>;
isLimitedToOneValue?: boolean;
models: Record<string, GenericDataModel> | undefined;
isRenderingGraphQL: boolean;
}): JsxAttribute {
const fieldConfig = fieldConfigs[fieldName];
const { dataType, componentType } = fieldConfig;
Expand Down Expand Up @@ -97,7 +101,7 @@ function getOnChangeAttribute({
NodeFlags.Let,
),
),
buildOverrideOnChangeStatement(fieldName, fieldConfigs, valueName),
buildOverrideOnChangeStatement(fieldName, fieldConfigs, valueName, models, isRenderingGraphQL),
...setStateStatements,
],
true,
Expand Down Expand Up @@ -132,6 +136,7 @@ export const renderArrayFieldComponent = (
labelDecorator?: LabelDecorator,
isRequired?: boolean,
dataApi: DataApiKind = 'DataStore',
models: Record<string, GenericDataModel> = {},
) => {
const fieldConfig = fieldConfigs[fieldName];
const { sanitizedFieldName, dataType, componentType } = fieldConfig;
Expand Down Expand Up @@ -172,7 +177,17 @@ export const renderArrayFieldComponent = (
);
}

props.push(getOnChangeAttribute({ fieldName, isLimitedToOneValue, fieldConfigs, renderedFieldName, setStateName }));
props.push(
getOnChangeAttribute({
fieldName,
isLimitedToOneValue,
fieldConfigs,
renderedFieldName,
setStateName,
models,
isRenderingGraphQL: dataApi === 'GraphQL',
}),
);
let labelAttribute = factory.createJsxAttribute(
factory.createIdentifier('label'),
factory.createJsxExpression(undefined, factory.createStringLiteral(fieldLabel)),
Expand Down
2 changes: 2 additions & 0 deletions packages/codegen-ui-react/lib/react-component-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class ReactComponentRenderer<TPropIn> extends ComponentRendererBase<
fieldConfigs,
labelDecorator,
isRequired,
this.importCollection.rendererConfig?.apiConfiguration?.dataApi === 'GraphQL',
);
}

Expand All @@ -118,6 +119,7 @@ export class ReactComponentRenderer<TPropIn> extends ComponentRendererBase<
labelDecorator,
isRequired,
this.importCollection.rendererConfig?.apiConfiguration?.dataApi,
this.componentMetadata.dataSchemaMetadata?.models,
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ export const renderStorageFieldComponent = (
fieldConfigs: Record<string, FieldConfigMetadata>,
labelDecorator?: LabelDecorator,
isRequired?: boolean,
isRenderingGraphQL = false,
) => {
const { name: componentName } = component;
const dataTypeName = componentMetadata.formMetadata?.dataType.dataTypeName || '';
Expand Down Expand Up @@ -418,8 +419,12 @@ export const renderStorageFieldComponent = (
);
}

storageManagerAttributes.push(buildStorageManagerOnChangeStatement(component, fieldConfigs, 'onUploadSuccess'));
storageManagerAttributes.push(buildStorageManagerOnChangeStatement(component, fieldConfigs, 'onFileRemove'));
storageManagerAttributes.push(
buildStorageManagerOnChangeStatement(component, fieldConfigs, 'onUploadSuccess', isRenderingGraphQL),
);
storageManagerAttributes.push(
buildStorageManagerOnChangeStatement(component, fieldConfigs, 'onFileRemove', isRenderingGraphQL),
);
storageManagerAttributes.push(
factory.createJsxAttribute(
factory.createIdentifier('processFile'),
Expand Down

0 comments on commit e12116a

Please sign in to comment.