Skip to content

Commit

Permalink
feat: add support for manyToMany update form
Browse files Browse the repository at this point in the history
  • Loading branch information
zchenwei committed Nov 19, 2022
1 parent e78eeb7 commit 264c92b
Show file tree
Hide file tree
Showing 8 changed files with 830 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,9 @@ export default function CustomDataForm(props) {
const [pages, setPages] = React.useState(initialValues.pages);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
const cleanValues = { ...initialValues, ...initialData };
const cleanValues = initialData
? { ...initialValues, ...initialData }
: initialValues;
setName(cleanValues.name);
setEmail(cleanValues.email);
setMetadataField(cleanValues[\\"metadata-field\\"]);
Expand Down Expand Up @@ -2607,7 +2609,9 @@ export default function NestedJson(props) {
const [bio, setBio] = React.useState(initialValues.bio);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
const cleanValues = { ...initialValues, ...initialData };
const cleanValues = initialData
? { ...initialValues, ...initialData }
: initialValues;
setFirstName(cleanValues.firstName);
setLastName(cleanValues[\\"last-Name\\"]);
setLastName1(cleanValues.lastName ?? []);
Expand Down Expand Up @@ -5341,7 +5345,9 @@ export default function MyPostForm(props) {
);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
const cleanValues = { ...initialValues, ...postRecord };
const cleanValues = postRecord
? { ...initialValues, ...postRecord }
: initialValues;
setTextAreaFieldbbd63464(cleanValues.TextAreaFieldbbd63464);
setCaption(cleanValues.caption);
setUsername(cleanValues.username);
Expand Down Expand Up @@ -5924,7 +5930,9 @@ export default function MyFlexUpdateForm(props) {
);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
const cleanValues = { ...initialValues, ...flexRecord };
const cleanValues = flexRecord
? { ...initialValues, ...flexRecord }
: initialValues;
setUsername(cleanValues.username);
setCaption(cleanValues.caption);
setCustomtags(cleanValues.Customtags ?? []);
Expand Down Expand Up @@ -7913,7 +7921,9 @@ export default function InputGalleryUpdateForm(props) {
const [timeisnow, setTimeisnow] = React.useState(initialValues.timeisnow);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
const cleanValues = { ...initialValues, ...inputGalleryRecord };
const cleanValues = inputGalleryRecord
? { ...initialValues, ...inputGalleryRecord }
: initialValues;
setNum(cleanValues.num);
setRootbeer(cleanValues.rootbeer);
setAttend(cleanValues.attend);
Expand Down
6 changes: 2 additions & 4 deletions packages/codegen-ui-react/lib/amplify-ui-renderers/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { ReactComponentRenderer } from '../react-component-renderer';
import { buildLayoutProperties, buildOpeningElementProperties } from '../react-component-render-helper';
import { ImportCollection, ImportSource } from '../imports';
import { buildDataStoreExpression } from '../forms';
import { onSubmitValidationRun, buildModelFieldObject } from '../forms/form-renderer-helper';
import { onSubmitValidationRun, buildModelFieldObject, getHasManyFieldConfigs } from '../forms/form-renderer-helper';
import { hasTokenReference } from '../utils/forms/layout-helpers';
import { resetFunctionCheck } from '../forms/form-renderer-helper/value-props';
import { isModelDataType } from '../forms/form-renderer-helper/render-checkers';
Expand Down Expand Up @@ -98,9 +98,7 @@ export default class FormRenderer extends ReactComponentRenderer<BaseComponentPr
if (!formMetadata) {
throw new Error(`Form Metadata is missing from form: ${this.component.name}`);
}
const hasManyFieldConfigs = Object.entries(formMetadata.fieldConfigs).filter(
([, fieldConfigMetaData]) => fieldConfigMetaData.relationship?.type === 'HAS_MANY',
);
const hasManyFieldConfigs = getHasManyFieldConfigs(formMetadata.fieldConfigs);

const onSubmitIdentifier = factory.createIdentifier('onSubmit');

Expand Down
233 changes: 212 additions & 21 deletions packages/codegen-ui-react/lib/forms/form-renderer-helper/cta-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,37 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
import { FieldConfigMetadata } from '@aws-amplify/codegen-ui/lib/types';
import { factory, NodeFlags, SyntaxKind, Expression } from 'typescript';
import { FieldConfigMetadata, HasManyRelationshipType } from '@aws-amplify/codegen-ui/lib/types';
import { factory, NodeFlags, SyntaxKind, Expression, VariableStatement, ExpressionStatement } from 'typescript';
import { lowerCaseFirst } from '../../helpers';
import { getDisplayValueObjectName } from './display-value';
import { getSetNameIdentifier } from './form-state';
import { getSetNameIdentifier, getLinkedRecordsName } from './form-state';
import { buildManyToManyRelationshipCreateStatements } from './relationship';
import { isManyToManyRelationship } from './map-from-fieldConfigs';

export const buildDataStoreExpression = (
dataStoreActionType: 'update' | 'create',
importedModelName: string,
hasManyFieldConfigs: [string, FieldConfigMetadata][],
) => {
if (hasManyFieldConfigs.length > 0) {
return hasManyFieldConfigs
.map((hasManyFieldConfig) => {
const [, fieldConfigMetaData] = hasManyFieldConfig;
if (isManyToManyRelationship(fieldConfigMetaData)) {
return buildManyToManyRelationshipCreateStatements(
dataStoreActionType,
importedModelName,
hasManyFieldConfig,
);
}
return [];
})
.reduce((statements, statement) => {
return [...statements, ...statement];
}, []);
}

if (dataStoreActionType === 'update') {
return [
factory.createVariableStatement(
Expand Down Expand Up @@ -108,24 +127,6 @@ export const buildDataStoreExpression = (
];
}

// TODO: Many to Many update action, this condition dataStoreActionType === 'create' can be moved inside the functon
if (hasManyFieldConfigs.length > 0 && dataStoreActionType === 'create') {
return hasManyFieldConfigs
.map((hasManyFieldConfig) => {
const [, fieldConfigMetaData] = hasManyFieldConfig;
if (
fieldConfigMetaData.relationship?.type === 'HAS_MANY' &&
fieldConfigMetaData.relationship.relatedJoinTableName
) {
return buildManyToManyRelationshipCreateStatements(importedModelName, hasManyFieldConfig);
}
return [];
})
.reduce((statements, statement) => {
return [...statements, ...statement];
}, []);
}

return [
factory.createExpressionStatement(
factory.createAwaitExpression(
Expand Down Expand Up @@ -451,3 +452,193 @@ export const buildUpdateDatastoreQuery = (dataTypeName: string, recordName: stri
),
];
};

/**
* const queryData = async () => {
* const record = id ? await DataStore.query(Tag, id) : tag;
* const linkedPosts = record
* ? await Promise.all(
* (
* await record.Posts.toArray()
* ).map((r) => {
* return r.post;
* }),
* )
* : [];
* setLinkedPosts(linkedPosts);
* setTagRecord(record);
* };
* queryData();
*/
export const buildUpdateDatastoreQueryForHasMany = (
dataTypeName: string,
recordName: string,
hasManyFieldConfigs: [string, FieldConfigMetadata][],
) => {
const lazyLoadLinkedDataStatements: VariableStatement[] = [];
const setLinkedDataStateStatements: ExpressionStatement[] = [];

hasManyFieldConfigs.forEach(([fieldName, fieldConfig]) => {
const linkedRecordsName = getLinkedRecordsName(fieldName);
const { relatedJoinFieldName } = fieldConfig.relationship as HasManyRelationshipType;
const lazyLoadLinkedDataStatement = factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
[
factory.createVariableDeclaration(
factory.createIdentifier(linkedRecordsName),
undefined,
undefined,
factory.createConditionalExpression(
factory.createIdentifier('record'),
factory.createToken(SyntaxKind.QuestionToken),
factory.createAwaitExpression(
factory.createCallExpression(
factory.createPropertyAccessExpression(
factory.createIdentifier('Promise'),
factory.createIdentifier('all'),
),
undefined,
[
factory.createCallExpression(
factory.createPropertyAccessExpression(
factory.createParenthesizedExpression(
factory.createAwaitExpression(
factory.createCallExpression(
factory.createPropertyAccessExpression(
factory.createPropertyAccessExpression(
factory.createIdentifier('record'),
factory.createIdentifier(fieldName),
),
factory.createIdentifier('toArray'),
),
undefined,
[],
),
),
),
factory.createIdentifier('map'),
),
undefined,
[
factory.createArrowFunction(
undefined,
undefined,
[
factory.createParameterDeclaration(
undefined,
undefined,
undefined,
factory.createIdentifier('r'),
undefined,
undefined,
undefined,
),
],
undefined,
factory.createToken(SyntaxKind.EqualsGreaterThanToken),
factory.createBlock(
[
factory.createReturnStatement(
factory.createPropertyAccessExpression(
factory.createIdentifier('r'),
factory.createIdentifier(relatedJoinFieldName as string),
),
),
],
true,
),
),
],
),
],
),
),
factory.createToken(SyntaxKind.ColonToken),
factory.createArrayLiteralExpression([], false),
),
),
],
// eslint-disable-next-line no-bitwise
NodeFlags.Const | NodeFlags.AwaitContext | NodeFlags.ContextFlags | NodeFlags.TypeExcludesFlags,
),
);

const setLinkedDataStateStatement = factory.createExpressionStatement(
factory.createCallExpression(getSetNameIdentifier(linkedRecordsName), undefined, [
factory.createIdentifier(linkedRecordsName),
]),
);

lazyLoadLinkedDataStatements.push(lazyLoadLinkedDataStatement);
setLinkedDataStateStatements.push(setLinkedDataStateStatement);
});

return [
factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
[
factory.createVariableDeclaration(
factory.createIdentifier('queryData'),
undefined,
undefined,
factory.createArrowFunction(
[factory.createModifier(SyntaxKind.AsyncKeyword)],
undefined,
[],
undefined,
factory.createToken(SyntaxKind.EqualsGreaterThanToken),
factory.createBlock(
[
factory.createVariableStatement(
undefined,
factory.createVariableDeclarationList(
[
factory.createVariableDeclaration(
factory.createIdentifier('record'),
undefined,
undefined,
factory.createConditionalExpression(
factory.createIdentifier('id'),
factory.createToken(SyntaxKind.QuestionToken),
factory.createAwaitExpression(
factory.createCallExpression(
factory.createPropertyAccessExpression(
factory.createIdentifier('DataStore'),
factory.createIdentifier('query'),
),
undefined,
[factory.createIdentifier(dataTypeName), factory.createIdentifier('id')],
),
),
factory.createToken(SyntaxKind.ColonToken),
factory.createIdentifier('tag'),
),
),
],
// eslint-disable-next-line no-bitwise
NodeFlags.Const | NodeFlags.AwaitContext | NodeFlags.ContextFlags | NodeFlags.TypeExcludesFlags,
),
),
...lazyLoadLinkedDataStatements,
...setLinkedDataStateStatements,
factory.createExpressionStatement(
factory.createCallExpression(getSetNameIdentifier(recordName), undefined, [
factory.createIdentifier('record'),
]),
),
],
true,
),
),
),
],
NodeFlags.Const,
),
),
factory.createExpressionStatement(
factory.createCallExpression(factory.createIdentifier('queryData'), undefined, []),
),
];
};

0 comments on commit 264c92b

Please sign in to comment.