Skip to content

Commit

Permalink
feat: support cpk for forms with hasMany relationship
Browse files Browse the repository at this point in the history
  • Loading branch information
Hein Jeong authored and hein-j committed Dec 1, 2022
1 parent c5d6abd commit ab9862f
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2286,6 +2286,7 @@ import {
CPKTeacher,
CPKStudent as CPKStudent0,
CPKClass,
CPKProject,
CPKTeacherCPKClass,
} from \\"../models\\";
import { fetchByPath, validateField } from \\"./utils\\";
Expand Down Expand Up @@ -2453,12 +2454,16 @@ export default function UpdateCPKTeacherForm(props) {
specialTeacherId: undefined,
CPKStudent: undefined,
CPKClasses: [],
CPKProjects: [],
};
const [specialTeacherId, setSpecialTeacherId] = React.useState(
initialValues.specialTeacherId
);
const [CPKStudent, setCPKStudent] = React.useState(initialValues.CPKStudent);
const [CPKClasses, setCPKClasses] = React.useState(initialValues.CPKClasses);
const [CPKProjects, setCPKProjects] = React.useState(
initialValues.CPKProjects
);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
const cleanValues = cPKTeacherRecord
Expand All @@ -2467,6 +2472,7 @@ export default function UpdateCPKTeacherForm(props) {
...cPKTeacherRecord,
CPKStudent,
CPKClasses: linkedCPKClasses,
CPKProjects: linkedCPKProjects,
}
: initialValues;
setSpecialTeacherId(cleanValues.specialTeacherId);
Expand All @@ -2476,10 +2482,14 @@ export default function UpdateCPKTeacherForm(props) {
setCPKClasses(cleanValues.CPKClasses ?? []);
setCurrentCPKClassesValue(undefined);
setCurrentCPKClassesDisplayValue(\\"\\");
setCPKProjects(cleanValues.CPKProjects ?? []);
setCurrentCPKProjectsValue(undefined);
setCurrentCPKProjectsDisplayValue(\\"\\");
setErrors({});
};
const [cPKTeacherRecord, setCPKTeacherRecord] = React.useState(cPKTeacher);
const [linkedCPKClasses, setLinkedCPKClasses] = React.useState([]);
const [linkedCPKProjects, setLinkedCPKProjects] = React.useState([]);
React.useEffect(() => {
const queryData = async () => {
const record = specialTeacherIdProp
Expand All @@ -2498,13 +2508,18 @@ export default function UpdateCPKTeacherForm(props) {
)
: [];
setLinkedCPKClasses(linkedCPKClasses);
const linkedCPKProjects = record
? await record.CPKProjects.toArray()
: [];
setLinkedCPKProjects(linkedCPKProjects);
};
queryData();
}, [specialTeacherIdProp, cPKTeacher]);
React.useEffect(resetStateValues, [
cPKTeacherRecord,
CPKStudent,
linkedCPKClasses,
linkedCPKProjects,
]);
const [currentCPKStudentDisplayValue, setCurrentCPKStudentDisplayValue] =
React.useState(\\"\\");
Expand All @@ -2516,6 +2531,11 @@ export default function UpdateCPKTeacherForm(props) {
const [currentCPKClassesValue, setCurrentCPKClassesValue] =
React.useState(undefined);
const CPKClassesRef = React.createRef();
const [currentCPKProjectsDisplayValue, setCurrentCPKProjectsDisplayValue] =
React.useState(\\"\\");
const [currentCPKProjectsValue, setCurrentCPKProjectsValue] =
React.useState(undefined);
const CPKProjectsRef = React.createRef();
const cPKStudentRecords = useDataStoreBinding({
type: \\"collection\\",
model: CPKStudent0,
Expand All @@ -2524,14 +2544,20 @@ export default function UpdateCPKTeacherForm(props) {
type: \\"collection\\",
model: CPKClass,
}).items;
const cPKProjectRecords = useDataStoreBinding({
type: \\"collection\\",
model: CPKProject,
}).items;
const getDisplayValue = {
CPKStudent: (record) => record?.specialStudentId,
CPKClasses: (record) => record?.specialClassId,
CPKProjects: (record) => record?.specialProjectId,
};
const validations = {
specialTeacherId: [{ type: \\"Required\\" }],
CPKStudent: [],
CPKClasses: [],
CPKProjects: [],
};
const runValidationTasks = async (
fieldName,
Expand Down Expand Up @@ -2561,6 +2587,7 @@ export default function UpdateCPKTeacherForm(props) {
specialTeacherId,
CPKStudent,
CPKClasses,
CPKProjects,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
Expand Down Expand Up @@ -2655,6 +2682,42 @@ export default function UpdateCPKTeacherForm(props) {
);
}
});
const cPKProjectsToLink = [];
const cPKProjectsToUnLink = [];
const cPKProjectsSet = new Set();
const linkedCPKProjectsSet = new Set();
CPKProjects.forEach((r) => cPKProjectsSet.add(r.specialProjectId));
linkedCPKProjects.forEach((r) =>
linkedCPKProjectsSet.add(r.specialProjectId)
);
linkedCPKProjects.forEach((r) => {
if (!cPKProjectsSet.has(r.id)) {
cPKProjectsToUnLink.push(r);
}
});
CPKProjects.forEach((r) => {
if (!linkedCPKProjectsSet.has(r.id)) {
cPKProjectsToLink.push(r);
}
});
cPKProjectsToUnLink.forEach((original) => {
promises.push(
DataStore.save(
CPKProject.copyOf(original, (updated) => {
updated.cPKTeacherID = null;
})
)
);
});
cPKProjectsToLink.forEach((original) => {
promises.push(
DataStore.save(
CPKProject.copyOf(original, (updated) => {
updated.cPKTeacherID = cPKTeacherRecord.specialTeacherId;
})
)
);
});
promises.push(
DataStore.save(
CPKTeacher.copyOf(cPKTeacherRecord, (updated) => {
Expand Down Expand Up @@ -2687,6 +2750,7 @@ export default function UpdateCPKTeacherForm(props) {
specialTeacherId: value,
CPKStudent,
CPKClasses,
CPKProjects,
};
const result = onChange(modelFields);
value = result?.specialTeacherId ?? value;
Expand All @@ -2710,6 +2774,7 @@ export default function UpdateCPKTeacherForm(props) {
specialTeacherId,
CPKStudent: value,
CPKClasses,
CPKProjects,
};
const result = onChange(modelFields);
value = result?.CPKStudent ?? value;
Expand Down Expand Up @@ -2773,6 +2838,7 @@ export default function UpdateCPKTeacherForm(props) {
specialTeacherId,
CPKStudent,
CPKClasses: values,
CPKProjects,
};
const result = onChange(modelFields);
values = result?.CPKClasses ?? values;
Expand Down Expand Up @@ -2829,6 +2895,71 @@ export default function UpdateCPKTeacherForm(props) {
{...getOverrideProps(overrides, \\"CPKClasses\\")}
></Autocomplete>
</ArrayField>
<ArrayField
onChange={async (items) => {
let values = items;
if (onChange) {
const modelFields = {
specialTeacherId,
CPKStudent,
CPKClasses,
CPKProjects: values,
};
const result = onChange(modelFields);
values = result?.CPKProjects ?? values;
}
setCPKProjects(values);
setCurrentCPKProjectsValue(undefined);
setCurrentCPKProjectsDisplayValue(\\"\\");
}}
currentFieldValue={currentCPKProjectsValue}
label={\\"Cpk projects\\"}
items={CPKProjects}
hasError={errors.CPKProjects?.hasError}
getBadgeText={getDisplayValue.CPKProjects}
setFieldValue={(model) => {
setCurrentCPKProjectsDisplayValue(getDisplayValue.CPKProjects(model));
setCurrentCPKProjectsValue(model);
}}
inputFieldRef={CPKProjectsRef}
defaultFieldValue={\\"\\"}
>
<Autocomplete
label=\\"Cpk projects\\"
isRequired={false}
isReadOnly={false}
value={currentCPKProjectsDisplayValue}
options={cPKProjectRecords.map((r) => ({
id: r.specialProjectId,
label: getDisplayValue.CPKProjects?.(r),
}))}
onSelect={({ id, label }) => {
setCurrentCPKProjectsValue(
cPKProjectRecords.find((r) => r.specialProjectId === id)
);
setCurrentCPKProjectsDisplayValue(label);
}}
onClear={() => {
setCurrentCPKProjectsDisplayValue(\\"\\");
}}
onChange={(e) => {
let { value } = e.target;
if (errors.CPKProjects?.hasError) {
runValidationTasks(\\"CPKProjects\\", value);
}
setCurrentCPKProjectsDisplayValue(value);
setCurrentCPKProjectsValue(undefined);
}}
onBlur={() =>
runValidationTasks(\\"CPKProjects\\", currentCPKProjectsValue)
}
errorMessage={errors.CPKProjects?.errorMessage}
hasError={errors.CPKProjects?.hasError}
ref={CPKProjectsRef}
labelHidden={true}
{...getOverrideProps(overrides, \\"CPKProjects\\")}
></Autocomplete>
</ArrayField>
<Flex
justifyContent=\\"space-between\\"
{...getOverrideProps(overrides, \\"CTAFlex\\")}
Expand Down Expand Up @@ -2862,7 +2993,7 @@ exports[`amplify form renderer tests datastore form tests custom form tests shou
"import * as React from \\"react\\";
import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
import { CPKTeacher, CPKStudent as CPKStudent0, CPKClass } from \\"../models\\";
import { CPKTeacher, CPKStudent as CPKStudent0, CPKClass, CPKProject } from \\"../models\\";
export declare type ValidationResponse = {
hasError: boolean;
errorMessage?: string;
Expand All @@ -2872,18 +3003,21 @@ export declare type UpdateCPKTeacherFormInputValues = {
specialTeacherId?: string;
CPKStudent?: CPKStudent0;
CPKClasses?: CPKClass[];
CPKProjects?: CPKProject[];
};
export declare type UpdateCPKTeacherFormValidationValues = {
specialTeacherId?: ValidationFunction<string>;
CPKStudent?: ValidationFunction<CPKStudent0>;
CPKClasses?: ValidationFunction<CPKClass>;
CPKProjects?: ValidationFunction<CPKProject>;
};
export declare type PrimitiveOverrideProps<T> = Partial<T> & React.DOMAttributes<HTMLDivElement>;
export declare type UpdateCPKTeacherFormOverridesProps = {
UpdateCPKTeacherFormGrid?: PrimitiveOverrideProps<GridProps>;
specialTeacherId?: PrimitiveOverrideProps<TextFieldProps>;
CPKStudent?: PrimitiveOverrideProps<AutocompleteProps>;
CPKClasses?: PrimitiveOverrideProps<AutocompleteProps>;
CPKProjects?: PrimitiveOverrideProps<AutocompleteProps>;
} & EscapeHatchProps;
export declare type UpdateCPKTeacherFormProps = React.PropsWithChildren<{
overrides?: UpdateCPKTeacherFormOverridesProps | undefined | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,11 @@ describe('amplify form renderer tests', () => {
expect(componentText).toContain('r.cpkTeacherID.eq(cPKTeacherRecord.specialTeacherId)');
expect(componentText).toContain('cpkTeacherID: cPKTeacherRecord.specialTeacherId');

// hasMany
expect(componentText).toContain('CPKProjects.forEach((r) => cPKProjectsSet.add(r.specialProjectId))');
expect(componentText).toContain('linkedCPKProjectsSet.add(r.specialProjectId)');
expect(componentText).toContain('updated.cPKTeacherID = cPKTeacherRecord.specialTeacherId');

expect(componentText).toMatchSnapshot();
expect(declaration).toMatchSnapshot();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ export const buildDataStoreExpression = (
);
} else {
hasManyDataStoreStatements.push(
...buildHasManyRelationshipDataStoreStatements(dataStoreActionType, importedModelName, fieldConfig),
...buildHasManyRelationshipDataStoreStatements(
dataStoreActionType,
importedModelName,
fieldConfig,
thisModelPrimaryKey,
),
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,7 @@ export const buildHasManyRelationshipDataStoreStatements = (
dataStoreActionType: 'update' | 'create',
modelName: string,
hasManyFieldConfig: [string, FieldConfigMetadata],
thisModelPrimaryKey: string,
) => {
let [fieldName] = hasManyFieldConfig;
const [, fieldConfigMetaData] = hasManyFieldConfig;
Expand All @@ -1162,6 +1163,11 @@ export const buildHasManyRelationshipDataStoreStatements = (
const dataToUnLink = `${lowerCaseFirst(fieldName)}ToUnLink`;
const dataToLinkSet = `${lowerCaseFirst(fieldName)}Set`;
const linkedDataSet = `${linkedDataName}Set`;
const { key } = extractModelAndKey(fieldConfigMetaData.valueMappings);
if (!key) {
throw new InternalError(`Could not identify primary key for ${relatedModelName}`);
}
const relatedModelPrimaryKey = key;
if (dataStoreActionType === 'update') {
return [
factory.createVariableStatement(
Expand Down Expand Up @@ -1222,6 +1228,7 @@ export const buildHasManyRelationshipDataStoreStatements = (
),
factory.createExpressionStatement(
factory.createCallExpression(
// CPKProjects.forEach((r) => cPKProjectsSet.add(r.specialProjectId));
factory.createPropertyAccessExpression(
factory.createIdentifier(fieldName),
factory.createIdentifier('forEach'),
Expand Down Expand Up @@ -1250,12 +1257,18 @@ export const buildHasManyRelationshipDataStoreStatements = (
factory.createIdentifier('add'),
),
undefined,
[factory.createPropertyAccessExpression(factory.createIdentifier('r'), factory.createIdentifier('id'))],
[
factory.createPropertyAccessExpression(
factory.createIdentifier('r'),
factory.createIdentifier(relatedModelPrimaryKey),
),
],
),
),
],
),
),
// linkedCPKProjects.forEach((r) => linkedCPKProjectsSet.add(r.specialProjectId));
factory.createExpressionStatement(
factory.createCallExpression(
factory.createPropertyAccessExpression(
Expand Down Expand Up @@ -1286,7 +1299,12 @@ export const buildHasManyRelationshipDataStoreStatements = (
factory.createIdentifier('add'),
),
undefined,
[factory.createPropertyAccessExpression(factory.createIdentifier('r'), factory.createIdentifier('id'))],
[
factory.createPropertyAccessExpression(
factory.createIdentifier('r'),
factory.createIdentifier(relatedModelPrimaryKey),
),
],
),
),
],
Expand Down Expand Up @@ -1588,6 +1606,7 @@ export const buildHasManyRelationshipDataStoreStatements = (
factory.createToken(SyntaxKind.EqualsGreaterThanToken),
factory.createBlock(
[
// updated.cPKTeacherID = cPKTeacherRecord.specialTeacherId;
factory.createExpressionStatement(
factory.createBinaryExpression(
factory.createPropertyAccessExpression(
Expand All @@ -1597,7 +1616,7 @@ export const buildHasManyRelationshipDataStoreStatements = (
factory.createToken(SyntaxKind.EqualsToken),
factory.createPropertyAccessExpression(
factory.createIdentifier(`${lowerCaseFirst(modelName)}Record`),
factory.createIdentifier('id'),
factory.createIdentifier(thisModelPrimaryKey),
),
),
),
Expand Down
Loading

0 comments on commit ab9862f

Please sign in to comment.