diff --git a/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap b/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap
index 812400b1..bc9b7ca8 100644
--- a/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap
+++ b/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap
@@ -10345,7 +10345,7 @@ export default function MyPostForm(props: MyPostFormProps): React.ReactElement;
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with composite primary key 1`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with composite primary key - amplify js v6 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import {
@@ -10369,12 +10369,13 @@ import {
listTags,
movieTagsByMovieMovieKeyAndMovietitleAndMoviegenre,
} from \\"../graphql/queries\\";
-import { API } from \\"aws-amplify\\";
+import { generateClient } from \\"aws-amplify/api\\";
import {
createMovieTags,
deleteMovieTags,
updateMovie,
} from \\"../graphql/mutations\\";
+const client = generateClient();
function ArrayField({
items = [],
onChange,
@@ -10578,7 +10579,7 @@ export default function MovieUpdateForm(props) {
const queryData = async () => {
const record = idProp
? (
- await API.graphql({
+ await client.graphql({
query: getMovie.replaceAll(\\"__typename\\", \\"\\"),
variables: { ...idProp },
})
@@ -10586,7 +10587,7 @@ export default function MovieUpdateForm(props) {
: movieModelProp;
const linkedTags = record
? (
- await API.graphql({
+ await client.graphql({
query:
movieTagsByMovieMovieKeyAndMovietitleAndMoviegenre.replaceAll(
\\"__typename\\",
@@ -10662,7 +10663,7 @@ export default function MovieUpdateForm(props) {
variables[\\"nextToken\\"] = newNext;
}
const result = (
- await API.graphql({
+ await client.graphql({
query: listTags.replaceAll(\\"__typename\\", \\"\\"),
variables,
})
@@ -10770,7 +10771,7 @@ export default function MovieUpdateForm(props) {
tagsToUnLinkMap.forEach(async (count, id) => {
const recordKeys = JSON.parse(id);
const movieTagsRecords = (
- await API.graphql({
+ await client.graphql({
query: listMovieTags.replaceAll(\\"__typename\\", \\"\\"),
variables: {
filter: {
@@ -10786,7 +10787,7 @@ export default function MovieUpdateForm(props) {
)?.data?.listMovieTags?.items;
for (let i = 0; i < count; i++) {
promises.push(
- API.graphql({
+ client.graphql({
query: deleteMovieTags.replaceAll(\\"__typename\\", \\"\\"),
variables: {
input: {
@@ -10805,7 +10806,7 @@ export default function MovieUpdateForm(props) {
);
for (let i = count; i > 0; i--) {
promises.push(
- API.graphql({
+ client.graphql({
query: createMovieTags.replaceAll(\\"__typename\\", \\"\\"),
variables: {
input: {
@@ -10826,7 +10827,7 @@ export default function MovieUpdateForm(props) {
rating: modelFields.rating ?? null,
};
promises.push(
- API.graphql({
+ client.graphql({
query: updateMovie.replaceAll(\\"__typename\\", \\"\\"),
variables: {
input: {
@@ -11076,7 +11077,7 @@ export default function MovieUpdateForm(props) {
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with composite primary key 2`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with composite primary key - amplify js v6 2`] = `
"import * as React from \\"react\\";
import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
@@ -11128,7 +11129,7 @@ export default function MovieUpdateForm(props: MovieUpdateFormProps): React.Reac
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship 1`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with composite primary key 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import {
@@ -11146,9 +11147,18 @@ import {
} from \\"@aws-amplify/ui-react\\";
import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
import { fetchByPath, validateField } from \\"./utils\\";
+import {
+ getMovie,
+ listMovieTags,
+ listTags,
+ movieTagsByMovieMovieKeyAndMovietitleAndMoviegenre,
+} from \\"../graphql/queries\\";
import { API } from \\"aws-amplify\\";
-import { getComment, getPost, listPosts } from \\"../graphql/queries\\";
-import { updateComment } from \\"../graphql/mutations\\";
+import {
+ createMovieTags,
+ deleteMovieTags,
+ updateMovie,
+} from \\"../graphql/mutations\\";
function ArrayField({
items = [],
onChange,
@@ -11304,10 +11314,10 @@ function ArrayField({
);
}
-export default function CommentUpdateForm(props) {
+export default function MovieUpdateForm(props) {
const {
id: idProp,
- comment: commentModelProp,
+ movie: movieModelProp,
onSuccess,
onError,
onSubmit,
@@ -11317,90 +11327,92 @@ export default function CommentUpdateForm(props) {
...rest
} = props;
const initialValues = {
- content: \\"\\",
- postID: undefined,
- Post: undefined,
- post: \\"\\",
+ movieKey: \\"\\",
+ title: \\"\\",
+ genre: \\"\\",
+ rating: \\"\\",
+ tags: [],
};
- const [content, setContent] = React.useState(initialValues.content);
- const [postID, setPostID] = React.useState(initialValues.postID);
- const [postIDLoading, setPostIDLoading] = React.useState(false);
- const [postIDRecords, setPostIDRecords] = React.useState([]);
- const [selectedPostIDRecords, setSelectedPostIDRecords] = React.useState([]);
- const [Post, setPost] = React.useState(initialValues.Post);
- const [PostLoading, setPostLoading] = React.useState(false);
- const [PostRecords, setPostRecords] = React.useState([]);
- const [post1, setPost1] = React.useState(initialValues.post);
+ const [movieKey, setMovieKey] = React.useState(initialValues.movieKey);
+ const [title, setTitle] = React.useState(initialValues.title);
+ const [genre, setGenre] = React.useState(initialValues.genre);
+ const [rating, setRating] = React.useState(initialValues.rating);
+ const [tags, setTags] = React.useState(initialValues.tags);
+ const [tagsLoading, setTagsLoading] = React.useState(false);
+ const [tagsRecords, setTagsRecords] = React.useState([]);
const autocompleteLength = 10;
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
- const cleanValues = commentRecord
- ? { ...initialValues, ...commentRecord, postID, Post }
+ const cleanValues = movieRecord
+ ? { ...initialValues, ...movieRecord, tags: linkedTags }
: initialValues;
- setContent(cleanValues.content);
- setPostID(cleanValues.postID);
- setCurrentPostIDValue(undefined);
- setCurrentPostIDDisplayValue(\\"\\");
- setPost(cleanValues.Post);
- setCurrentPostValue(undefined);
- setCurrentPostDisplayValue(\\"\\");
- setPost1(cleanValues.post);
+ setMovieKey(cleanValues.movieKey);
+ setTitle(cleanValues.title);
+ setGenre(cleanValues.genre);
+ setRating(cleanValues.rating);
+ setTags(cleanValues.tags ?? []);
+ setCurrentTagsValue(undefined);
+ setCurrentTagsDisplayValue(\\"\\");
setErrors({});
};
- const [commentRecord, setCommentRecord] = React.useState(commentModelProp);
+ const [movieRecord, setMovieRecord] = React.useState(movieModelProp);
+ const [linkedTags, setLinkedTags] = React.useState([]);
+ const canUnlinkTags = false;
React.useEffect(() => {
const queryData = async () => {
const record = idProp
? (
await API.graphql({
- query: getComment.replaceAll(\\"__typename\\", \\"\\"),
- variables: { id: idProp },
+ query: getMovie.replaceAll(\\"__typename\\", \\"\\"),
+ variables: { ...idProp },
})
- )?.data?.getComment
- : commentModelProp;
- const postIDRecord = record ? record.postID : undefined;
- const postRecord = postIDRecord
+ )?.data?.getMovie
+ : movieModelProp;
+ const linkedTags = record
? (
await API.graphql({
- query: getPost.replaceAll(\\"__typename\\", \\"\\"),
- variables: { id: postIDRecord },
+ query:
+ movieTagsByMovieMovieKeyAndMovietitleAndMoviegenre.replaceAll(
+ \\"__typename\\",
+ \\"\\"
+ ),
+ variables: {
+ movieMovieKey: record.movieKey,
+ movietitle: record.title,
+ moviegenre: record.genre,
+ },
})
- )?.data?.getPost
- : undefined;
- setPostID(postIDRecord);
- setSelectedPostIDRecords([postRecord]);
- const PostRecord = record ? await record.Post : undefined;
- setPost(PostRecord);
- setCommentRecord(record);
+ ).data.movieTagsByMovieMovieKeyAndMovietitleAndMoviegenre.items.map(
+ (t) => t.tag
+ )
+ : [];
+ setLinkedTags(linkedTags);
+ setMovieRecord(record);
};
queryData();
- }, [idProp, commentModelProp]);
- React.useEffect(resetStateValues, [commentRecord, postID, Post]);
- const [currentPostIDDisplayValue, setCurrentPostIDDisplayValue] =
- React.useState(\\"\\");
- const [currentPostIDValue, setCurrentPostIDValue] = React.useState(undefined);
- const postIDRef = React.createRef();
- const [currentPostDisplayValue, setCurrentPostDisplayValue] =
+ }, [idProp, movieModelProp]);
+ React.useEffect(resetStateValues, [movieRecord, linkedTags]);
+ const [currentTagsDisplayValue, setCurrentTagsDisplayValue] =
React.useState(\\"\\");
- const [currentPostValue, setCurrentPostValue] = React.useState(undefined);
- const PostRef = React.createRef();
+ const [currentTagsValue, setCurrentTagsValue] = React.useState(undefined);
+ const tagsRef = React.createRef();
const getIDValue = {
- Post: (r) => JSON.stringify({ id: r?.id }),
+ tags: (r) => JSON.stringify({ id: r?.id }),
};
- const PostIdSet = new Set(
- Array.isArray(Post)
- ? Post.map((r) => getIDValue.Post?.(r))
- : getIDValue.Post?.(Post)
+ const tagsIdSet = new Set(
+ Array.isArray(tags)
+ ? tags.map((r) => getIDValue.tags?.(r))
+ : getIDValue.tags?.(tags)
);
const getDisplayValue = {
- postID: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
- Post: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ tags: (r) => \`\${r?.label ? r?.label + \\" - \\" : \\"\\"}\${r?.id}\`,
};
const validations = {
- content: [],
- postID: [{ type: \\"Required\\" }],
- Post: [],
- post: [],
+ movieKey: [{ type: \\"Required\\" }],
+ title: [{ type: \\"Required\\" }],
+ genre: [{ type: \\"Required\\" }],
+ rating: [],
+ tags: [],
};
const runValidationTasks = async (
fieldName,
@@ -11419,42 +11431,15 @@ export default function CommentUpdateForm(props) {
setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
return validationResponse;
};
- const fetchPostIDRecords = async (value) => {
- setPostIDLoading(true);
- const newOptions = [];
- let newNext = \\"\\";
- while (newOptions.length < autocompleteLength && newNext != null) {
- const variables = {
- limit: autocompleteLength * 5,
- filter: {
- or: [{ title: { contains: value } }, { id: { contains: value } }],
- },
- };
- if (newNext) {
- variables[\\"nextToken\\"] = newNext;
- }
- const result = (
- await API.graphql({
- query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
- variables,
- })
- )?.data?.listPosts?.items;
- var loaded = result.filter((item) => postID !== item.id);
- newOptions.push(...loaded);
- newNext = result.nextToken;
- }
- setPostIDRecords(newOptions.slice(0, autocompleteLength));
- setPostIDLoading(false);
- };
- const fetchPostRecords = async (value) => {
- setPostLoading(true);
+ const fetchTagsRecords = async (value) => {
+ setTagsLoading(true);
const newOptions = [];
let newNext = \\"\\";
while (newOptions.length < autocompleteLength && newNext != null) {
const variables = {
limit: autocompleteLength * 5,
filter: {
- or: [{ title: { contains: value } }, { id: { contains: value } }],
+ or: [{ label: { contains: value } }, { id: { contains: value } }],
},
};
if (newNext) {
@@ -11462,22 +11447,21 @@ export default function CommentUpdateForm(props) {
}
const result = (
await API.graphql({
- query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ query: listTags.replaceAll(\\"__typename\\", \\"\\"),
variables,
})
- )?.data?.listPosts?.items;
+ )?.data?.listTags?.items;
var loaded = result.filter(
- (item) => !PostIdSet.has(getIDValue.Post?.(item))
+ (item) => !tagsIdSet.has(getIDValue.tags?.(item))
);
newOptions.push(...loaded);
newNext = result.nextToken;
}
- setPostRecords(newOptions.slice(0, autocompleteLength));
- setPostLoading(false);
+ setTagsRecords(newOptions.slice(0, autocompleteLength));
+ setTagsLoading(false);
};
React.useEffect(() => {
- fetchPostIDRecords(\\"\\");
- fetchPostRecords(\\"\\");
+ fetchTagsRecords(\\"\\");
}, []);
return (
{
event.preventDefault();
let modelFields = {
- content: content ?? null,
- postID,
- Post: Post ?? null,
- post: post ?? null,
+ movieKey,
+ title,
+ genre,
+ rating: rating ?? null,
+ tags: tags ?? null,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
@@ -11529,43 +11514,2308 @@ export default function CommentUpdateForm(props) {
modelFields[key] = null;
}
});
- const modelFieldsToSave = {
- content: modelFields.content ?? null,
- postID: modelFields.postID,
- postCommentsId: modelFields?.Post?.id ?? null,
- };
- await API.graphql({
- query: updateComment.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- input: {
- id: commentRecord.id,
- ...modelFieldsToSave,
- },
- },
+ const promises = [];
+ const tagsToLinkMap = new Map();
+ const tagsToUnLinkMap = new Map();
+ const tagsMap = new Map();
+ const linkedTagsMap = new Map();
+ tags.forEach((r) => {
+ const count = tagsMap.get(getIDValue.tags?.(r));
+ const newCount = count ? count + 1 : 1;
+ tagsMap.set(getIDValue.tags?.(r), newCount);
});
- if (onSuccess) {
- onSuccess(modelFields);
- }
- } catch (err) {
- if (onError) {
- const messages = err.errors.map((e) => e.message).join(\\"\\\\n\\");
- onError(modelFields, messages);
- }
- }
- }}
- {...getOverrideProps(overrides, \\"CommentUpdateForm\\")}
- {...rest}
- >
- {
- let { value } = e.target;
- if (onChange) {
- const modelFields = {
- content: value,
+ linkedTags.forEach((r) => {
+ const count = linkedTagsMap.get(getIDValue.tags?.(r));
+ const newCount = count ? count + 1 : 1;
+ linkedTagsMap.set(getIDValue.tags?.(r), newCount);
+ });
+ linkedTagsMap.forEach((count, id) => {
+ const newCount = tagsMap.get(id);
+ if (newCount) {
+ const diffCount = count - newCount;
+ if (diffCount > 0) {
+ tagsToUnLinkMap.set(id, diffCount);
+ }
+ } else {
+ tagsToUnLinkMap.set(id, count);
+ }
+ });
+ tagsMap.forEach((count, id) => {
+ const originalCount = linkedTagsMap.get(id);
+ if (originalCount) {
+ const diffCount = count - originalCount;
+ if (diffCount > 0) {
+ tagsToLinkMap.set(id, diffCount);
+ }
+ } else {
+ tagsToLinkMap.set(id, count);
+ }
+ });
+ tagsToUnLinkMap.forEach(async (count, id) => {
+ const recordKeys = JSON.parse(id);
+ const movieTagsRecords = (
+ await API.graphql({
+ query: listMovieTags.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ filter: {
+ and: [
+ { tagId: { eq: recordKeys.id } },
+ { movieMovieKey: { eq: movieRecord.movieKey } },
+ { movietitle: { eq: movieRecord.title } },
+ { moviegenre: { eq: movieRecord.genre } },
+ ],
+ },
+ },
+ })
+ )?.data?.listMovieTags?.items;
+ for (let i = 0; i < count; i++) {
+ promises.push(
+ API.graphql({
+ query: deleteMovieTags.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: movieTagsRecords[i].id,
+ },
+ },
+ })
+ );
+ }
+ });
+ tagsToLinkMap.forEach((count, id) => {
+ const tagToLink = tagRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
+ );
+ for (let i = count; i > 0; i--) {
+ promises.push(
+ API.graphql({
+ query: createMovieTags.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ movieMovieKey: movieRecord.movieKey,
+ movietitle: movieRecord.title,
+ moviegenre: movieRecord.genre,
+ tagId: tagToLink.id,
+ },
+ },
+ })
+ );
+ }
+ });
+ const modelFieldsToSave = {
+ movieKey: modelFields.movieKey,
+ title: modelFields.title,
+ genre: modelFields.genre,
+ rating: modelFields.rating ?? null,
+ };
+ promises.push(
+ API.graphql({
+ query: updateMovie.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ movieKey: movieRecord.movieKey,
+ title: movieRecord.title,
+ genre: movieRecord.genre,
+ ...modelFieldsToSave,
+ },
+ },
+ })
+ );
+ await Promise.all(promises);
+ if (onSuccess) {
+ onSuccess(modelFields);
+ }
+ } catch (err) {
+ if (onError) {
+ const messages = err.errors.map((e) => e.message).join(\\"\\\\n\\");
+ onError(modelFields, messages);
+ }
+ }
+ }}
+ {...getOverrideProps(overrides, \\"MovieUpdateForm\\")}
+ {...rest}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ movieKey: value,
+ title,
+ genre,
+ rating,
+ tags,
+ };
+ const result = onChange(modelFields);
+ value = result?.movieKey ?? value;
+ }
+ if (errors.movieKey?.hasError) {
+ runValidationTasks(\\"movieKey\\", value);
+ }
+ setMovieKey(value);
+ }}
+ onBlur={() => runValidationTasks(\\"movieKey\\", movieKey)}
+ errorMessage={errors.movieKey?.errorMessage}
+ hasError={errors.movieKey?.hasError}
+ {...getOverrideProps(overrides, \\"movieKey\\")}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ movieKey,
+ title: value,
+ genre,
+ rating,
+ tags,
+ };
+ const result = onChange(modelFields);
+ value = result?.title ?? value;
+ }
+ if (errors.title?.hasError) {
+ runValidationTasks(\\"title\\", value);
+ }
+ setTitle(value);
+ }}
+ onBlur={() => runValidationTasks(\\"title\\", title)}
+ errorMessage={errors.title?.errorMessage}
+ hasError={errors.title?.hasError}
+ {...getOverrideProps(overrides, \\"title\\")}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ movieKey,
+ title,
+ genre: value,
+ rating,
+ tags,
+ };
+ const result = onChange(modelFields);
+ value = result?.genre ?? value;
+ }
+ if (errors.genre?.hasError) {
+ runValidationTasks(\\"genre\\", value);
+ }
+ setGenre(value);
+ }}
+ onBlur={() => runValidationTasks(\\"genre\\", genre)}
+ errorMessage={errors.genre?.errorMessage}
+ hasError={errors.genre?.hasError}
+ {...getOverrideProps(overrides, \\"genre\\")}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ movieKey,
+ title,
+ genre,
+ rating: value,
+ tags,
+ };
+ const result = onChange(modelFields);
+ value = result?.rating ?? value;
+ }
+ if (errors.rating?.hasError) {
+ runValidationTasks(\\"rating\\", value);
+ }
+ setRating(value);
+ }}
+ onBlur={() => runValidationTasks(\\"rating\\", rating)}
+ errorMessage={errors.rating?.errorMessage}
+ hasError={errors.rating?.hasError}
+ {...getOverrideProps(overrides, \\"rating\\")}
+ >
+ {
+ let values = items;
+ if (onChange) {
+ const modelFields = {
+ movieKey,
+ title,
+ genre,
+ rating,
+ tags: values,
+ };
+ const result = onChange(modelFields);
+ values = result?.tags ?? values;
+ }
+ setTags(values);
+ setCurrentTagsValue(undefined);
+ setCurrentTagsDisplayValue(\\"\\");
+ }}
+ currentFieldValue={currentTagsValue}
+ label={\\"Tags\\"}
+ items={tags}
+ hasError={errors?.tags?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks(\\"tags\\", currentTagsValue)
+ }
+ errorMessage={errors?.tags?.errorMessage}
+ getBadgeText={getDisplayValue.tags}
+ setFieldValue={(model) => {
+ setCurrentTagsDisplayValue(model ? getDisplayValue.tags(model) : \\"\\");
+ setCurrentTagsValue(model);
+ }}
+ inputFieldRef={tagsRef}
+ defaultFieldValue={\\"\\"}
+ >
+ ({
+ id: getIDValue.tags?.(r),
+ label: getDisplayValue.tags?.(r),
+ }))}
+ isLoading={tagsLoading}
+ onSelect={({ id, label }) => {
+ setCurrentTagsValue(
+ tagsRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
+ )
+ );
+ setCurrentTagsDisplayValue(label);
+ runValidationTasks(\\"tags\\", label);
+ }}
+ onClear={() => {
+ setCurrentTagsDisplayValue(\\"\\");
+ }}
+ onChange={(e) => {
+ let { value } = e.target;
+ fetchTagsRecords(value);
+ if (errors.tags?.hasError) {
+ runValidationTasks(\\"tags\\", value);
+ }
+ setCurrentTagsDisplayValue(value);
+ setCurrentTagsValue(undefined);
+ }}
+ onBlur={() => runValidationTasks(\\"tags\\", currentTagsDisplayValue)}
+ errorMessage={errors.tags?.errorMessage}
+ hasError={errors.tags?.hasError}
+ ref={tagsRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"tags\\")}
+ >
+
+
+
+
+
+
+
+
+ );
+}
+"
+`;
+
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with composite primary key 2`] = `
+"import * as React from \\"react\\";
+import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
+import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
+import { Movie, Tag } from \\"../API\\";
+export declare type ValidationResponse = {
+ hasError: boolean;
+ errorMessage?: string;
+};
+export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
+export declare type MovieUpdateFormInputValues = {
+ movieKey?: string;
+ title?: string;
+ genre?: string;
+ rating?: string;
+ tags?: Tag[];
+};
+export declare type MovieUpdateFormValidationValues = {
+ movieKey?: ValidationFunction;
+ title?: ValidationFunction;
+ genre?: ValidationFunction;
+ rating?: ValidationFunction;
+ tags?: ValidationFunction;
+};
+export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
+export declare type MovieUpdateFormOverridesProps = {
+ MovieUpdateFormGrid?: PrimitiveOverrideProps;
+ movieKey?: PrimitiveOverrideProps;
+ title?: PrimitiveOverrideProps;
+ genre?: PrimitiveOverrideProps;
+ rating?: PrimitiveOverrideProps;
+ tags?: PrimitiveOverrideProps;
+} & EscapeHatchProps;
+export declare type MovieUpdateFormProps = React.PropsWithChildren<{
+ overrides?: MovieUpdateFormOverridesProps | undefined | null;
+} & {
+ id?: {
+ movieKey: string;
+ title: string;
+ genre: string;
+ };
+ movie?: Movie;
+ onSubmit?: (fields: MovieUpdateFormInputValues) => MovieUpdateFormInputValues;
+ onSuccess?: (fields: MovieUpdateFormInputValues) => void;
+ onError?: (fields: MovieUpdateFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: MovieUpdateFormInputValues) => MovieUpdateFormInputValues;
+ onValidate?: MovieUpdateFormValidationValues;
+} & React.CSSProperties>;
+export default function MovieUpdateForm(props: MovieUpdateFormProps): React.ReactElement;
+"
+`;
+
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship 1`] = `
+"/* eslint-disable */
+import * as React from \\"react\\";
+import {
+ Autocomplete,
+ Badge,
+ Button,
+ Divider,
+ Flex,
+ Grid,
+ Icon,
+ ScrollView,
+ Text,
+ TextField,
+ useTheme,
+} from \\"@aws-amplify/ui-react\\";
+import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
+import { fetchByPath, validateField } from \\"./utils\\";
+import { API } from \\"aws-amplify\\";
+import { getComment, getPost, listPosts } from \\"../graphql/queries\\";
+import { updateComment } from \\"../graphql/mutations\\";
+function ArrayField({
+ items = [],
+ onChange,
+ label,
+ inputFieldRef,
+ children,
+ hasError,
+ setFieldValue,
+ currentFieldValue,
+ defaultFieldValue,
+ lengthLimit,
+ getBadgeText,
+ runValidationTasks,
+ errorMessage,
+}) {
+ const labelElement = {label};
+ const {
+ tokens: {
+ components: {
+ fieldmessages: { error: errorStyles },
+ },
+ },
+ } = useTheme();
+ const [selectedBadgeIndex, setSelectedBadgeIndex] = React.useState();
+ const [isEditing, setIsEditing] = React.useState();
+ React.useEffect(() => {
+ if (isEditing) {
+ inputFieldRef?.current?.focus();
+ }
+ }, [isEditing]);
+ const removeItem = async (removeIndex) => {
+ const newItems = items.filter((value, index) => index !== removeIndex);
+ await onChange(newItems);
+ setSelectedBadgeIndex(undefined);
+ };
+ const addItem = async () => {
+ const { hasError } = runValidationTasks();
+ if (
+ currentFieldValue !== undefined &&
+ currentFieldValue !== null &&
+ currentFieldValue !== \\"\\" &&
+ !hasError
+ ) {
+ const newItems = [...items];
+ if (selectedBadgeIndex !== undefined) {
+ newItems[selectedBadgeIndex] = currentFieldValue;
+ setSelectedBadgeIndex(undefined);
+ } else {
+ newItems.push(currentFieldValue);
+ }
+ await onChange(newItems);
+ setIsEditing(false);
+ }
+ };
+ const arraySection = (
+
+ {!!items?.length && (
+
+ {items.map((value, index) => {
+ return (
+ {
+ setSelectedBadgeIndex(index);
+ setFieldValue(items[index]);
+ setIsEditing(true);
+ }}
+ >
+ {getBadgeText ? getBadgeText(value) : value.toString()}
+ {
+ event.stopPropagation();
+ removeItem(index);
+ }}
+ />
+
+ );
+ })}
+
+ )}
+
+
+ );
+ if (lengthLimit !== undefined && items.length >= lengthLimit && !isEditing) {
+ return (
+
+ {labelElement}
+ {arraySection}
+
+ );
+ }
+ return (
+
+ {labelElement}
+ {isEditing && children}
+ {!isEditing ? (
+ <>
+
+ {errorMessage && hasError && (
+
+ {errorMessage}
+
+ )}
+ >
+ ) : (
+
+ {(currentFieldValue || isEditing) && (
+
+ )}
+
+
+ )}
+ {arraySection}
+
+ );
+}
+export default function CommentUpdateForm(props) {
+ const {
+ id: idProp,
+ comment: commentModelProp,
+ onSuccess,
+ onError,
+ onSubmit,
+ onValidate,
+ onChange,
+ overrides,
+ ...rest
+ } = props;
+ const initialValues = {
+ content: \\"\\",
+ postID: undefined,
+ Post: undefined,
+ post: \\"\\",
+ };
+ const [content, setContent] = React.useState(initialValues.content);
+ const [postID, setPostID] = React.useState(initialValues.postID);
+ const [postIDLoading, setPostIDLoading] = React.useState(false);
+ const [postIDRecords, setPostIDRecords] = React.useState([]);
+ const [selectedPostIDRecords, setSelectedPostIDRecords] = React.useState([]);
+ const [Post, setPost] = React.useState(initialValues.Post);
+ const [PostLoading, setPostLoading] = React.useState(false);
+ const [PostRecords, setPostRecords] = React.useState([]);
+ const [post1, setPost1] = React.useState(initialValues.post);
+ const autocompleteLength = 10;
+ const [errors, setErrors] = React.useState({});
+ const resetStateValues = () => {
+ const cleanValues = commentRecord
+ ? { ...initialValues, ...commentRecord, postID, Post }
+ : initialValues;
+ setContent(cleanValues.content);
+ setPostID(cleanValues.postID);
+ setCurrentPostIDValue(undefined);
+ setCurrentPostIDDisplayValue(\\"\\");
+ setPost(cleanValues.Post);
+ setCurrentPostValue(undefined);
+ setCurrentPostDisplayValue(\\"\\");
+ setPost1(cleanValues.post);
+ setErrors({});
+ };
+ const [commentRecord, setCommentRecord] = React.useState(commentModelProp);
+ React.useEffect(() => {
+ const queryData = async () => {
+ const record = idProp
+ ? (
+ await API.graphql({
+ query: getComment.replaceAll(\\"__typename\\", \\"\\"),
+ variables: { id: idProp },
+ })
+ )?.data?.getComment
+ : commentModelProp;
+ const postIDRecord = record ? record.postID : undefined;
+ const postRecord = postIDRecord
+ ? (
+ await API.graphql({
+ query: getPost.replaceAll(\\"__typename\\", \\"\\"),
+ variables: { id: postIDRecord },
+ })
+ )?.data?.getPost
+ : undefined;
+ setPostID(postIDRecord);
+ setSelectedPostIDRecords([postRecord]);
+ const PostRecord = record ? await record.Post : undefined;
+ setPost(PostRecord);
+ setCommentRecord(record);
+ };
+ queryData();
+ }, [idProp, commentModelProp]);
+ React.useEffect(resetStateValues, [commentRecord, postID, Post]);
+ const [currentPostIDDisplayValue, setCurrentPostIDDisplayValue] =
+ React.useState(\\"\\");
+ const [currentPostIDValue, setCurrentPostIDValue] = React.useState(undefined);
+ const postIDRef = React.createRef();
+ const [currentPostDisplayValue, setCurrentPostDisplayValue] =
+ React.useState(\\"\\");
+ const [currentPostValue, setCurrentPostValue] = React.useState(undefined);
+ const PostRef = React.createRef();
+ const getIDValue = {
+ Post: (r) => JSON.stringify({ id: r?.id }),
+ };
+ const PostIdSet = new Set(
+ Array.isArray(Post)
+ ? Post.map((r) => getIDValue.Post?.(r))
+ : getIDValue.Post?.(Post)
+ );
+ const getDisplayValue = {
+ postID: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ Post: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ };
+ const validations = {
+ content: [],
+ postID: [{ type: \\"Required\\" }],
+ Post: [],
+ post: [],
+ };
+ const runValidationTasks = async (
+ fieldName,
+ currentValue,
+ getDisplayValue
+ ) => {
+ const value =
+ currentValue && getDisplayValue
+ ? getDisplayValue(currentValue)
+ : currentValue;
+ let validationResponse = validateField(value, validations[fieldName]);
+ const customValidator = fetchByPath(onValidate, fieldName);
+ if (customValidator) {
+ validationResponse = await customValidator(value, validationResponse);
+ }
+ setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
+ return validationResponse;
+ };
+ const fetchPostIDRecords = async (value) => {
+ setPostIDLoading(true);
+ const newOptions = [];
+ let newNext = \\"\\";
+ while (newOptions.length < autocompleteLength && newNext != null) {
+ const variables = {
+ limit: autocompleteLength * 5,
+ filter: {
+ or: [{ title: { contains: value } }, { id: { contains: value } }],
+ },
+ };
+ if (newNext) {
+ variables[\\"nextToken\\"] = newNext;
+ }
+ const result = (
+ await API.graphql({
+ query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ variables,
+ })
+ )?.data?.listPosts?.items;
+ var loaded = result.filter((item) => postID !== item.id);
+ newOptions.push(...loaded);
+ newNext = result.nextToken;
+ }
+ setPostIDRecords(newOptions.slice(0, autocompleteLength));
+ setPostIDLoading(false);
+ };
+ const fetchPostRecords = async (value) => {
+ setPostLoading(true);
+ const newOptions = [];
+ let newNext = \\"\\";
+ while (newOptions.length < autocompleteLength && newNext != null) {
+ const variables = {
+ limit: autocompleteLength * 5,
+ filter: {
+ or: [{ title: { contains: value } }, { id: { contains: value } }],
+ },
+ };
+ if (newNext) {
+ variables[\\"nextToken\\"] = newNext;
+ }
+ const result = (
+ await API.graphql({
+ query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ variables,
+ })
+ )?.data?.listPosts?.items;
+ var loaded = result.filter(
+ (item) => !PostIdSet.has(getIDValue.Post?.(item))
+ );
+ newOptions.push(...loaded);
+ newNext = result.nextToken;
+ }
+ setPostRecords(newOptions.slice(0, autocompleteLength));
+ setPostLoading(false);
+ };
+ React.useEffect(() => {
+ fetchPostIDRecords(\\"\\");
+ fetchPostRecords(\\"\\");
+ }, []);
+ return (
+ {
+ event.preventDefault();
+ let modelFields = {
+ content: content ?? null,
+ postID,
+ Post: Post ?? null,
+ post: post ?? null,
+ };
+ const validationResponses = await Promise.all(
+ Object.keys(validations).reduce((promises, fieldName) => {
+ if (Array.isArray(modelFields[fieldName])) {
+ promises.push(
+ ...modelFields[fieldName].map((item) =>
+ runValidationTasks(
+ fieldName,
+ item,
+ getDisplayValue[fieldName]
+ )
+ )
+ );
+ return promises;
+ }
+ promises.push(
+ runValidationTasks(
+ fieldName,
+ modelFields[fieldName],
+ getDisplayValue[fieldName]
+ )
+ );
+ return promises;
+ }, [])
+ );
+ if (validationResponses.some((r) => r.hasError)) {
+ return;
+ }
+ if (onSubmit) {
+ modelFields = onSubmit(modelFields);
+ }
+ try {
+ Object.entries(modelFields).forEach(([key, value]) => {
+ if (typeof value === \\"string\\" && value === \\"\\") {
+ modelFields[key] = null;
+ }
+ });
+ const modelFieldsToSave = {
+ content: modelFields.content ?? null,
+ postID: modelFields.postID,
+ postCommentsId: modelFields?.Post?.id ?? null,
+ };
+ await API.graphql({
+ query: updateComment.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: commentRecord.id,
+ ...modelFieldsToSave,
+ },
+ },
+ });
+ if (onSuccess) {
+ onSuccess(modelFields);
+ }
+ } catch (err) {
+ if (onError) {
+ const messages = err.errors.map((e) => e.message).join(\\"\\\\n\\");
+ onError(modelFields, messages);
+ }
+ }
+ }}
+ {...getOverrideProps(overrides, \\"CommentUpdateForm\\")}
+ {...rest}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ content: value,
+ postID,
+ Post,
+ post: post1,
+ };
+ const result = onChange(modelFields);
+ value = result?.content ?? value;
+ }
+ if (errors.content?.hasError) {
+ runValidationTasks(\\"content\\", value);
+ }
+ setContent(value);
+ }}
+ onBlur={() => runValidationTasks(\\"content\\", content)}
+ errorMessage={errors.content?.errorMessage}
+ hasError={errors.content?.hasError}
+ {...getOverrideProps(overrides, \\"content\\")}
+ >
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ content,
+ postID: value,
+ Post,
+ post: post1,
+ };
+ const result = onChange(modelFields);
+ value = result?.postID ?? value;
+ }
+ setPostID(value);
+ setCurrentPostIDValue(undefined);
+ }}
+ currentFieldValue={currentPostIDValue}
+ label={\\"Post id\\"}
+ items={postID ? [postID] : []}
+ hasError={errors?.postID?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks(\\"postID\\", currentPostIDValue)
+ }
+ errorMessage={errors?.postID?.errorMessage}
+ getBadgeText={(value) =>
+ value
+ ? getDisplayValue.postID(
+ postIDRecords.find((r) => r.id === value) ??
+ selectedPostIDRecords.find((r) => r.id === value)
+ )
+ : \\"\\"
+ }
+ setFieldValue={(value) => {
+ setCurrentPostIDDisplayValue(
+ value
+ ? getDisplayValue.postID(
+ postIDRecords.find((r) => r.id === value) ??
+ selectedPostIDRecords.find((r) => r.id === value)
+ )
+ : \\"\\"
+ );
+ setCurrentPostIDValue(value);
+ const selectedRecord = postIDRecords.find((r) => r.id === value);
+ if (selectedRecord) {
+ setSelectedPostIDRecords([selectedRecord]);
+ }
+ }}
+ inputFieldRef={postIDRef}
+ defaultFieldValue={\\"\\"}
+ >
+
+ arr.findIndex((member) => member?.id === r?.id) === i
+ )
+ .map((r) => ({
+ id: r?.id,
+ label: getDisplayValue.postID?.(r),
+ }))}
+ isLoading={postIDLoading}
+ onSelect={({ id, label }) => {
+ setCurrentPostIDValue(id);
+ setCurrentPostIDDisplayValue(label);
+ runValidationTasks(\\"postID\\", label);
+ }}
+ onClear={() => {
+ setCurrentPostIDDisplayValue(\\"\\");
+ }}
+ defaultValue={postID}
+ onChange={(e) => {
+ let { value } = e.target;
+ fetchPostIDRecords(value);
+ if (errors.postID?.hasError) {
+ runValidationTasks(\\"postID\\", value);
+ }
+ setCurrentPostIDDisplayValue(value);
+ setCurrentPostIDValue(undefined);
+ }}
+ onBlur={() => runValidationTasks(\\"postID\\", currentPostIDValue)}
+ errorMessage={errors.postID?.errorMessage}
+ hasError={errors.postID?.hasError}
+ ref={postIDRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"postID\\")}
+ >
+
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ content,
+ postID,
+ Post: value,
+ post: post1,
+ };
+ const result = onChange(modelFields);
+ value = result?.Post ?? value;
+ }
+ setPost(value);
+ setCurrentPostValue(undefined);
+ setCurrentPostDisplayValue(\\"\\");
+ }}
+ currentFieldValue={currentPostValue}
+ label={\\"Post\\"}
+ items={Post ? [Post] : []}
+ hasError={errors?.Post?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks(\\"Post\\", currentPostValue)
+ }
+ errorMessage={errors?.Post?.errorMessage}
+ getBadgeText={getDisplayValue.Post}
+ setFieldValue={(model) => {
+ setCurrentPostDisplayValue(model ? getDisplayValue.Post(model) : \\"\\");
+ setCurrentPostValue(model);
+ }}
+ inputFieldRef={PostRef}
+ defaultFieldValue={\\"\\"}
+ >
+ !PostIdSet.has(getIDValue.Post?.(r))
+ ).map((r) => ({
+ id: getIDValue.Post?.(r),
+ label: getDisplayValue.Post?.(r),
+ }))}
+ isLoading={PostLoading}
+ onSelect={({ id, label }) => {
+ setCurrentPostValue(
+ PostRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
+ )
+ );
+ setCurrentPostDisplayValue(label);
+ runValidationTasks(\\"Post\\", label);
+ }}
+ onClear={() => {
+ setCurrentPostDisplayValue(\\"\\");
+ }}
+ defaultValue={Post}
+ onChange={(e) => {
+ let { value } = e.target;
+ fetchPostRecords(value);
+ if (errors.Post?.hasError) {
+ runValidationTasks(\\"Post\\", value);
+ }
+ setCurrentPostDisplayValue(value);
+ setCurrentPostValue(undefined);
+ }}
+ onBlur={() => runValidationTasks(\\"Post\\", currentPostDisplayValue)}
+ errorMessage={errors.Post?.errorMessage}
+ hasError={errors.Post?.hasError}
+ ref={PostRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"Post\\")}
+ >
+
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ content,
+ postID,
+ Post,
+ post: value,
+ };
+ const result = onChange(modelFields);
+ value = result?.post ?? value;
+ }
+ if (errors.post?.hasError) {
+ runValidationTasks(\\"post\\", value);
+ }
+ setPost1(value);
+ }}
+ onBlur={() => runValidationTasks(\\"post\\", post1)}
+ errorMessage={errors.post?.errorMessage}
+ hasError={errors.post?.hasError}
+ {...getOverrideProps(overrides, \\"post\\")}
+ >
+
+
+
+
+
+
+
+ );
+}
+"
+`;
+
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship 2`] = `
+"import * as React from \\"react\\";
+import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
+import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
+import { Comment, Post } from \\"../API\\";
+export declare type ValidationResponse = {
+ hasError: boolean;
+ errorMessage?: string;
+};
+export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
+export declare type CommentUpdateFormInputValues = {
+ content?: string;
+ postID?: string;
+ Post?: Post;
+ post?: string;
+};
+export declare type CommentUpdateFormValidationValues = {
+ content?: ValidationFunction;
+ postID?: ValidationFunction;
+ Post?: ValidationFunction;
+ post?: ValidationFunction;
+};
+export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
+export declare type CommentUpdateFormOverridesProps = {
+ CommentUpdateFormGrid?: PrimitiveOverrideProps;
+ content?: PrimitiveOverrideProps;
+ postID?: PrimitiveOverrideProps;
+ Post?: PrimitiveOverrideProps;
+ post?: PrimitiveOverrideProps;
+} & EscapeHatchProps;
+export declare type CommentUpdateFormProps = React.PropsWithChildren<{
+ overrides?: CommentUpdateFormOverridesProps | undefined | null;
+} & {
+ id?: string;
+ comment?: Comment;
+ onSubmit?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
+ onSuccess?: (fields: CommentUpdateFormInputValues) => void;
+ onError?: (fields: CommentUpdateFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
+ onValidate?: CommentUpdateFormValidationValues;
+} & React.CSSProperties>;
+export default function CommentUpdateForm(props: CommentUpdateFormProps): React.ReactElement;
+"
+`;
+
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship without types file - amplify js v6 1`] = `
+"/* eslint-disable */
+import * as React from \\"react\\";
+import {
+ Autocomplete,
+ Badge,
+ Button,
+ Divider,
+ Flex,
+ Grid,
+ Icon,
+ ScrollView,
+ Text,
+ TextField,
+ useTheme,
+} from \\"@aws-amplify/ui-react\\";
+import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
+import { fetchByPath, validateField } from \\"./utils\\";
+import { generateClient } from \\"aws-amplify/api\\";
+import { getComment, getPost, listPosts } from \\"../graphql/queries\\";
+import { updateComment } from \\"../graphql/mutations\\";
+const client = generateClient();
+function ArrayField({
+ items = [],
+ onChange,
+ label,
+ inputFieldRef,
+ children,
+ hasError,
+ setFieldValue,
+ currentFieldValue,
+ defaultFieldValue,
+ lengthLimit,
+ getBadgeText,
+ runValidationTasks,
+ errorMessage,
+}) {
+ const labelElement = {label};
+ const {
+ tokens: {
+ components: {
+ fieldmessages: { error: errorStyles },
+ },
+ },
+ } = useTheme();
+ const [selectedBadgeIndex, setSelectedBadgeIndex] = React.useState();
+ const [isEditing, setIsEditing] = React.useState();
+ React.useEffect(() => {
+ if (isEditing) {
+ inputFieldRef?.current?.focus();
+ }
+ }, [isEditing]);
+ const removeItem = async (removeIndex) => {
+ const newItems = items.filter((value, index) => index !== removeIndex);
+ await onChange(newItems);
+ setSelectedBadgeIndex(undefined);
+ };
+ const addItem = async () => {
+ const { hasError } = runValidationTasks();
+ if (
+ currentFieldValue !== undefined &&
+ currentFieldValue !== null &&
+ currentFieldValue !== \\"\\" &&
+ !hasError
+ ) {
+ const newItems = [...items];
+ if (selectedBadgeIndex !== undefined) {
+ newItems[selectedBadgeIndex] = currentFieldValue;
+ setSelectedBadgeIndex(undefined);
+ } else {
+ newItems.push(currentFieldValue);
+ }
+ await onChange(newItems);
+ setIsEditing(false);
+ }
+ };
+ const arraySection = (
+
+ {!!items?.length && (
+
+ {items.map((value, index) => {
+ return (
+ {
+ setSelectedBadgeIndex(index);
+ setFieldValue(items[index]);
+ setIsEditing(true);
+ }}
+ >
+ {getBadgeText ? getBadgeText(value) : value.toString()}
+ {
+ event.stopPropagation();
+ removeItem(index);
+ }}
+ />
+
+ );
+ })}
+
+ )}
+
+
+ );
+ if (lengthLimit !== undefined && items.length >= lengthLimit && !isEditing) {
+ return (
+
+ {labelElement}
+ {arraySection}
+
+ );
+ }
+ return (
+
+ {labelElement}
+ {isEditing && children}
+ {!isEditing ? (
+ <>
+
+ {errorMessage && hasError && (
+
+ {errorMessage}
+
+ )}
+ >
+ ) : (
+
+ {(currentFieldValue || isEditing) && (
+
+ )}
+
+
+ )}
+ {arraySection}
+
+ );
+}
+export default function CommentUpdateForm(props) {
+ const {
+ id: idProp,
+ comment: commentModelProp,
+ onSuccess,
+ onError,
+ onSubmit,
+ onValidate,
+ onChange,
+ overrides,
+ ...rest
+ } = props;
+ const initialValues = {
+ content: \\"\\",
+ postID: undefined,
+ Post: undefined,
+ post: \\"\\",
+ };
+ const [content, setContent] = React.useState(initialValues.content);
+ const [postID, setPostID] = React.useState(initialValues.postID);
+ const [postIDLoading, setPostIDLoading] = React.useState(false);
+ const [postIDRecords, setPostIDRecords] = React.useState([]);
+ const [selectedPostIDRecords, setSelectedPostIDRecords] = React.useState([]);
+ const [Post, setPost] = React.useState(initialValues.Post);
+ const [PostLoading, setPostLoading] = React.useState(false);
+ const [PostRecords, setPostRecords] = React.useState([]);
+ const [post1, setPost1] = React.useState(initialValues.post);
+ const autocompleteLength = 10;
+ const [errors, setErrors] = React.useState({});
+ const resetStateValues = () => {
+ const cleanValues = commentRecord
+ ? { ...initialValues, ...commentRecord, postID, Post }
+ : initialValues;
+ setContent(cleanValues.content);
+ setPostID(cleanValues.postID);
+ setCurrentPostIDValue(undefined);
+ setCurrentPostIDDisplayValue(\\"\\");
+ setPost(cleanValues.Post);
+ setCurrentPostValue(undefined);
+ setCurrentPostDisplayValue(\\"\\");
+ setPost1(cleanValues.post);
+ setErrors({});
+ };
+ const [commentRecord, setCommentRecord] = React.useState(commentModelProp);
+ React.useEffect(() => {
+ const queryData = async () => {
+ const record = idProp
+ ? (
+ await client.graphql({
+ query: getComment.replaceAll(\\"__typename\\", \\"\\"),
+ variables: { id: idProp },
+ })
+ )?.data?.getComment
+ : commentModelProp;
+ const postIDRecord = record ? record.postID : undefined;
+ const postRecord = postIDRecord
+ ? (
+ await client.graphql({
+ query: getPost.replaceAll(\\"__typename\\", \\"\\"),
+ variables: { id: postIDRecord },
+ })
+ )?.data?.getPost
+ : undefined;
+ setPostID(postIDRecord);
+ setSelectedPostIDRecords([postRecord]);
+ const PostRecord = record ? await record.Post : undefined;
+ setPost(PostRecord);
+ setCommentRecord(record);
+ };
+ queryData();
+ }, [idProp, commentModelProp]);
+ React.useEffect(resetStateValues, [commentRecord, postID, Post]);
+ const [currentPostIDDisplayValue, setCurrentPostIDDisplayValue] =
+ React.useState(\\"\\");
+ const [currentPostIDValue, setCurrentPostIDValue] = React.useState(undefined);
+ const postIDRef = React.createRef();
+ const [currentPostDisplayValue, setCurrentPostDisplayValue] =
+ React.useState(\\"\\");
+ const [currentPostValue, setCurrentPostValue] = React.useState(undefined);
+ const PostRef = React.createRef();
+ const getIDValue = {
+ Post: (r) => JSON.stringify({ id: r?.id }),
+ };
+ const PostIdSet = new Set(
+ Array.isArray(Post)
+ ? Post.map((r) => getIDValue.Post?.(r))
+ : getIDValue.Post?.(Post)
+ );
+ const getDisplayValue = {
+ postID: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ Post: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ };
+ const validations = {
+ content: [],
+ postID: [{ type: \\"Required\\" }],
+ Post: [],
+ post: [],
+ };
+ const runValidationTasks = async (
+ fieldName,
+ currentValue,
+ getDisplayValue
+ ) => {
+ const value =
+ currentValue && getDisplayValue
+ ? getDisplayValue(currentValue)
+ : currentValue;
+ let validationResponse = validateField(value, validations[fieldName]);
+ const customValidator = fetchByPath(onValidate, fieldName);
+ if (customValidator) {
+ validationResponse = await customValidator(value, validationResponse);
+ }
+ setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
+ return validationResponse;
+ };
+ const fetchPostIDRecords = async (value) => {
+ setPostIDLoading(true);
+ const newOptions = [];
+ let newNext = \\"\\";
+ while (newOptions.length < autocompleteLength && newNext != null) {
+ const variables = {
+ limit: autocompleteLength * 5,
+ filter: {
+ or: [{ title: { contains: value } }, { id: { contains: value } }],
+ },
+ };
+ if (newNext) {
+ variables[\\"nextToken\\"] = newNext;
+ }
+ const result = (
+ await client.graphql({
+ query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ variables,
+ })
+ )?.data?.listPosts?.items;
+ var loaded = result.filter((item) => postID !== item.id);
+ newOptions.push(...loaded);
+ newNext = result.nextToken;
+ }
+ setPostIDRecords(newOptions.slice(0, autocompleteLength));
+ setPostIDLoading(false);
+ };
+ const fetchPostRecords = async (value) => {
+ setPostLoading(true);
+ const newOptions = [];
+ let newNext = \\"\\";
+ while (newOptions.length < autocompleteLength && newNext != null) {
+ const variables = {
+ limit: autocompleteLength * 5,
+ filter: {
+ or: [{ title: { contains: value } }, { id: { contains: value } }],
+ },
+ };
+ if (newNext) {
+ variables[\\"nextToken\\"] = newNext;
+ }
+ const result = (
+ await client.graphql({
+ query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ variables,
+ })
+ )?.data?.listPosts?.items;
+ var loaded = result.filter(
+ (item) => !PostIdSet.has(getIDValue.Post?.(item))
+ );
+ newOptions.push(...loaded);
+ newNext = result.nextToken;
+ }
+ setPostRecords(newOptions.slice(0, autocompleteLength));
+ setPostLoading(false);
+ };
+ React.useEffect(() => {
+ fetchPostIDRecords(\\"\\");
+ fetchPostRecords(\\"\\");
+ }, []);
+ return (
+ {
+ event.preventDefault();
+ let modelFields = {
+ content: content ?? null,
+ postID,
+ Post: Post ?? null,
+ post: post ?? null,
+ };
+ const validationResponses = await Promise.all(
+ Object.keys(validations).reduce((promises, fieldName) => {
+ if (Array.isArray(modelFields[fieldName])) {
+ promises.push(
+ ...modelFields[fieldName].map((item) =>
+ runValidationTasks(
+ fieldName,
+ item,
+ getDisplayValue[fieldName]
+ )
+ )
+ );
+ return promises;
+ }
+ promises.push(
+ runValidationTasks(
+ fieldName,
+ modelFields[fieldName],
+ getDisplayValue[fieldName]
+ )
+ );
+ return promises;
+ }, [])
+ );
+ if (validationResponses.some((r) => r.hasError)) {
+ return;
+ }
+ if (onSubmit) {
+ modelFields = onSubmit(modelFields);
+ }
+ try {
+ Object.entries(modelFields).forEach(([key, value]) => {
+ if (typeof value === \\"string\\" && value === \\"\\") {
+ modelFields[key] = null;
+ }
+ });
+ const modelFieldsToSave = {
+ content: modelFields.content ?? null,
+ postID: modelFields.postID,
+ postCommentsId: modelFields?.Post?.id ?? null,
+ };
+ await client.graphql({
+ query: updateComment.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: commentRecord.id,
+ ...modelFieldsToSave,
+ },
+ },
+ });
+ if (onSuccess) {
+ onSuccess(modelFields);
+ }
+ } catch (err) {
+ if (onError) {
+ const messages = err.errors.map((e) => e.message).join(\\"\\\\n\\");
+ onError(modelFields, messages);
+ }
+ }
+ }}
+ {...getOverrideProps(overrides, \\"CommentUpdateForm\\")}
+ {...rest}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ content: value,
+ postID,
+ Post,
+ post: post1,
+ };
+ const result = onChange(modelFields);
+ value = result?.content ?? value;
+ }
+ if (errors.content?.hasError) {
+ runValidationTasks(\\"content\\", value);
+ }
+ setContent(value);
+ }}
+ onBlur={() => runValidationTasks(\\"content\\", content)}
+ errorMessage={errors.content?.errorMessage}
+ hasError={errors.content?.hasError}
+ {...getOverrideProps(overrides, \\"content\\")}
+ >
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ content,
+ postID: value,
+ Post,
+ post: post1,
+ };
+ const result = onChange(modelFields);
+ value = result?.postID ?? value;
+ }
+ setPostID(value);
+ setCurrentPostIDValue(undefined);
+ }}
+ currentFieldValue={currentPostIDValue}
+ label={\\"Post id\\"}
+ items={postID ? [postID] : []}
+ hasError={errors?.postID?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks(\\"postID\\", currentPostIDValue)
+ }
+ errorMessage={errors?.postID?.errorMessage}
+ getBadgeText={(value) =>
+ value
+ ? getDisplayValue.postID(
+ postIDRecords.find((r) => r.id === value) ??
+ selectedPostIDRecords.find((r) => r.id === value)
+ )
+ : \\"\\"
+ }
+ setFieldValue={(value) => {
+ setCurrentPostIDDisplayValue(
+ value
+ ? getDisplayValue.postID(
+ postIDRecords.find((r) => r.id === value) ??
+ selectedPostIDRecords.find((r) => r.id === value)
+ )
+ : \\"\\"
+ );
+ setCurrentPostIDValue(value);
+ const selectedRecord = postIDRecords.find((r) => r.id === value);
+ if (selectedRecord) {
+ setSelectedPostIDRecords([selectedRecord]);
+ }
+ }}
+ inputFieldRef={postIDRef}
+ defaultFieldValue={\\"\\"}
+ >
+
+ arr.findIndex((member) => member?.id === r?.id) === i
+ )
+ .map((r) => ({
+ id: r?.id,
+ label: getDisplayValue.postID?.(r),
+ }))}
+ isLoading={postIDLoading}
+ onSelect={({ id, label }) => {
+ setCurrentPostIDValue(id);
+ setCurrentPostIDDisplayValue(label);
+ runValidationTasks(\\"postID\\", label);
+ }}
+ onClear={() => {
+ setCurrentPostIDDisplayValue(\\"\\");
+ }}
+ defaultValue={postID}
+ onChange={(e) => {
+ let { value } = e.target;
+ fetchPostIDRecords(value);
+ if (errors.postID?.hasError) {
+ runValidationTasks(\\"postID\\", value);
+ }
+ setCurrentPostIDDisplayValue(value);
+ setCurrentPostIDValue(undefined);
+ }}
+ onBlur={() => runValidationTasks(\\"postID\\", currentPostIDValue)}
+ errorMessage={errors.postID?.errorMessage}
+ hasError={errors.postID?.hasError}
+ ref={postIDRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"postID\\")}
+ >
+
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ content,
+ postID,
+ Post: value,
+ post: post1,
+ };
+ const result = onChange(modelFields);
+ value = result?.Post ?? value;
+ }
+ setPost(value);
+ setCurrentPostValue(undefined);
+ setCurrentPostDisplayValue(\\"\\");
+ }}
+ currentFieldValue={currentPostValue}
+ label={\\"Post\\"}
+ items={Post ? [Post] : []}
+ hasError={errors?.Post?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks(\\"Post\\", currentPostValue)
+ }
+ errorMessage={errors?.Post?.errorMessage}
+ getBadgeText={getDisplayValue.Post}
+ setFieldValue={(model) => {
+ setCurrentPostDisplayValue(model ? getDisplayValue.Post(model) : \\"\\");
+ setCurrentPostValue(model);
+ }}
+ inputFieldRef={PostRef}
+ defaultFieldValue={\\"\\"}
+ >
+ !PostIdSet.has(getIDValue.Post?.(r))
+ ).map((r) => ({
+ id: getIDValue.Post?.(r),
+ label: getDisplayValue.Post?.(r),
+ }))}
+ isLoading={PostLoading}
+ onSelect={({ id, label }) => {
+ setCurrentPostValue(
+ PostRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
+ )
+ );
+ setCurrentPostDisplayValue(label);
+ runValidationTasks(\\"Post\\", label);
+ }}
+ onClear={() => {
+ setCurrentPostDisplayValue(\\"\\");
+ }}
+ defaultValue={Post}
+ onChange={(e) => {
+ let { value } = e.target;
+ fetchPostRecords(value);
+ if (errors.Post?.hasError) {
+ runValidationTasks(\\"Post\\", value);
+ }
+ setCurrentPostDisplayValue(value);
+ setCurrentPostValue(undefined);
+ }}
+ onBlur={() => runValidationTasks(\\"Post\\", currentPostDisplayValue)}
+ errorMessage={errors.Post?.errorMessage}
+ hasError={errors.Post?.hasError}
+ ref={PostRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"Post\\")}
+ >
+
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ content,
+ postID,
+ Post,
+ post: value,
+ };
+ const result = onChange(modelFields);
+ value = result?.post ?? value;
+ }
+ if (errors.post?.hasError) {
+ runValidationTasks(\\"post\\", value);
+ }
+ setPost1(value);
+ }}
+ onBlur={() => runValidationTasks(\\"post\\", post1)}
+ errorMessage={errors.post?.errorMessage}
+ hasError={errors.post?.hasError}
+ {...getOverrideProps(overrides, \\"post\\")}
+ >
+
+
+
+
+
+
+
+ );
+}
+"
+`;
+
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship without types file - amplify js v6 2`] = `
+"import * as React from \\"react\\";
+import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
+import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
+export declare type ValidationResponse = {
+ hasError: boolean;
+ errorMessage?: string;
+};
+export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
+export declare type CommentUpdateFormInputValues = {
+ content?: string;
+ postID?: string;
+ Post?: any;
+ post?: string;
+};
+export declare type CommentUpdateFormValidationValues = {
+ content?: ValidationFunction;
+ postID?: ValidationFunction;
+ Post?: ValidationFunction;
+ post?: ValidationFunction;
+};
+export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
+export declare type CommentUpdateFormOverridesProps = {
+ CommentUpdateFormGrid?: PrimitiveOverrideProps;
+ content?: PrimitiveOverrideProps;
+ postID?: PrimitiveOverrideProps;
+ Post?: PrimitiveOverrideProps;
+ post?: PrimitiveOverrideProps;
+} & EscapeHatchProps;
+export declare type CommentUpdateFormProps = React.PropsWithChildren<{
+ overrides?: CommentUpdateFormOverridesProps | undefined | null;
+} & {
+ id?: string;
+ comment?: any;
+ onSubmit?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
+ onSuccess?: (fields: CommentUpdateFormInputValues) => void;
+ onError?: (fields: CommentUpdateFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
+ onValidate?: CommentUpdateFormValidationValues;
+} & React.CSSProperties>;
+export default function CommentUpdateForm(props: CommentUpdateFormProps): React.ReactElement;
+"
+`;
+
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship without types file 1`] = `
+"/* eslint-disable */
+import * as React from \\"react\\";
+import {
+ Autocomplete,
+ Badge,
+ Button,
+ Divider,
+ Flex,
+ Grid,
+ Icon,
+ ScrollView,
+ Text,
+ TextField,
+ useTheme,
+} from \\"@aws-amplify/ui-react\\";
+import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
+import { fetchByPath, validateField } from \\"./utils\\";
+import { API } from \\"aws-amplify\\";
+import { getComment, getPost, listPosts } from \\"../graphql/queries\\";
+import { updateComment } from \\"../graphql/mutations\\";
+function ArrayField({
+ items = [],
+ onChange,
+ label,
+ inputFieldRef,
+ children,
+ hasError,
+ setFieldValue,
+ currentFieldValue,
+ defaultFieldValue,
+ lengthLimit,
+ getBadgeText,
+ runValidationTasks,
+ errorMessage,
+}) {
+ const labelElement = {label};
+ const {
+ tokens: {
+ components: {
+ fieldmessages: { error: errorStyles },
+ },
+ },
+ } = useTheme();
+ const [selectedBadgeIndex, setSelectedBadgeIndex] = React.useState();
+ const [isEditing, setIsEditing] = React.useState();
+ React.useEffect(() => {
+ if (isEditing) {
+ inputFieldRef?.current?.focus();
+ }
+ }, [isEditing]);
+ const removeItem = async (removeIndex) => {
+ const newItems = items.filter((value, index) => index !== removeIndex);
+ await onChange(newItems);
+ setSelectedBadgeIndex(undefined);
+ };
+ const addItem = async () => {
+ const { hasError } = runValidationTasks();
+ if (
+ currentFieldValue !== undefined &&
+ currentFieldValue !== null &&
+ currentFieldValue !== \\"\\" &&
+ !hasError
+ ) {
+ const newItems = [...items];
+ if (selectedBadgeIndex !== undefined) {
+ newItems[selectedBadgeIndex] = currentFieldValue;
+ setSelectedBadgeIndex(undefined);
+ } else {
+ newItems.push(currentFieldValue);
+ }
+ await onChange(newItems);
+ setIsEditing(false);
+ }
+ };
+ const arraySection = (
+
+ {!!items?.length && (
+
+ {items.map((value, index) => {
+ return (
+ {
+ setSelectedBadgeIndex(index);
+ setFieldValue(items[index]);
+ setIsEditing(true);
+ }}
+ >
+ {getBadgeText ? getBadgeText(value) : value.toString()}
+ {
+ event.stopPropagation();
+ removeItem(index);
+ }}
+ />
+
+ );
+ })}
+
+ )}
+
+
+ );
+ if (lengthLimit !== undefined && items.length >= lengthLimit && !isEditing) {
+ return (
+
+ {labelElement}
+ {arraySection}
+
+ );
+ }
+ return (
+
+ {labelElement}
+ {isEditing && children}
+ {!isEditing ? (
+ <>
+
+ {errorMessage && hasError && (
+
+ {errorMessage}
+
+ )}
+ >
+ ) : (
+
+ {(currentFieldValue || isEditing) && (
+
+ )}
+
+
+ )}
+ {arraySection}
+
+ );
+}
+export default function CommentUpdateForm(props) {
+ const {
+ id: idProp,
+ comment: commentModelProp,
+ onSuccess,
+ onError,
+ onSubmit,
+ onValidate,
+ onChange,
+ overrides,
+ ...rest
+ } = props;
+ const initialValues = {
+ content: \\"\\",
+ postID: undefined,
+ Post: undefined,
+ post: \\"\\",
+ };
+ const [content, setContent] = React.useState(initialValues.content);
+ const [postID, setPostID] = React.useState(initialValues.postID);
+ const [postIDLoading, setPostIDLoading] = React.useState(false);
+ const [postIDRecords, setPostIDRecords] = React.useState([]);
+ const [selectedPostIDRecords, setSelectedPostIDRecords] = React.useState([]);
+ const [Post, setPost] = React.useState(initialValues.Post);
+ const [PostLoading, setPostLoading] = React.useState(false);
+ const [PostRecords, setPostRecords] = React.useState([]);
+ const [post1, setPost1] = React.useState(initialValues.post);
+ const autocompleteLength = 10;
+ const [errors, setErrors] = React.useState({});
+ const resetStateValues = () => {
+ const cleanValues = commentRecord
+ ? { ...initialValues, ...commentRecord, postID, Post }
+ : initialValues;
+ setContent(cleanValues.content);
+ setPostID(cleanValues.postID);
+ setCurrentPostIDValue(undefined);
+ setCurrentPostIDDisplayValue(\\"\\");
+ setPost(cleanValues.Post);
+ setCurrentPostValue(undefined);
+ setCurrentPostDisplayValue(\\"\\");
+ setPost1(cleanValues.post);
+ setErrors({});
+ };
+ const [commentRecord, setCommentRecord] = React.useState(commentModelProp);
+ React.useEffect(() => {
+ const queryData = async () => {
+ const record = idProp
+ ? (
+ await API.graphql({
+ query: getComment.replaceAll(\\"__typename\\", \\"\\"),
+ variables: { id: idProp },
+ })
+ )?.data?.getComment
+ : commentModelProp;
+ const postIDRecord = record ? record.postID : undefined;
+ const postRecord = postIDRecord
+ ? (
+ await API.graphql({
+ query: getPost.replaceAll(\\"__typename\\", \\"\\"),
+ variables: { id: postIDRecord },
+ })
+ )?.data?.getPost
+ : undefined;
+ setPostID(postIDRecord);
+ setSelectedPostIDRecords([postRecord]);
+ const PostRecord = record ? await record.Post : undefined;
+ setPost(PostRecord);
+ setCommentRecord(record);
+ };
+ queryData();
+ }, [idProp, commentModelProp]);
+ React.useEffect(resetStateValues, [commentRecord, postID, Post]);
+ const [currentPostIDDisplayValue, setCurrentPostIDDisplayValue] =
+ React.useState(\\"\\");
+ const [currentPostIDValue, setCurrentPostIDValue] = React.useState(undefined);
+ const postIDRef = React.createRef();
+ const [currentPostDisplayValue, setCurrentPostDisplayValue] =
+ React.useState(\\"\\");
+ const [currentPostValue, setCurrentPostValue] = React.useState(undefined);
+ const PostRef = React.createRef();
+ const getIDValue = {
+ Post: (r) => JSON.stringify({ id: r?.id }),
+ };
+ const PostIdSet = new Set(
+ Array.isArray(Post)
+ ? Post.map((r) => getIDValue.Post?.(r))
+ : getIDValue.Post?.(Post)
+ );
+ const getDisplayValue = {
+ postID: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ Post: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ };
+ const validations = {
+ content: [],
+ postID: [{ type: \\"Required\\" }],
+ Post: [],
+ post: [],
+ };
+ const runValidationTasks = async (
+ fieldName,
+ currentValue,
+ getDisplayValue
+ ) => {
+ const value =
+ currentValue && getDisplayValue
+ ? getDisplayValue(currentValue)
+ : currentValue;
+ let validationResponse = validateField(value, validations[fieldName]);
+ const customValidator = fetchByPath(onValidate, fieldName);
+ if (customValidator) {
+ validationResponse = await customValidator(value, validationResponse);
+ }
+ setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
+ return validationResponse;
+ };
+ const fetchPostIDRecords = async (value) => {
+ setPostIDLoading(true);
+ const newOptions = [];
+ let newNext = \\"\\";
+ while (newOptions.length < autocompleteLength && newNext != null) {
+ const variables = {
+ limit: autocompleteLength * 5,
+ filter: {
+ or: [{ title: { contains: value } }, { id: { contains: value } }],
+ },
+ };
+ if (newNext) {
+ variables[\\"nextToken\\"] = newNext;
+ }
+ const result = (
+ await API.graphql({
+ query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ variables,
+ })
+ )?.data?.listPosts?.items;
+ var loaded = result.filter((item) => postID !== item.id);
+ newOptions.push(...loaded);
+ newNext = result.nextToken;
+ }
+ setPostIDRecords(newOptions.slice(0, autocompleteLength));
+ setPostIDLoading(false);
+ };
+ const fetchPostRecords = async (value) => {
+ setPostLoading(true);
+ const newOptions = [];
+ let newNext = \\"\\";
+ while (newOptions.length < autocompleteLength && newNext != null) {
+ const variables = {
+ limit: autocompleteLength * 5,
+ filter: {
+ or: [{ title: { contains: value } }, { id: { contains: value } }],
+ },
+ };
+ if (newNext) {
+ variables[\\"nextToken\\"] = newNext;
+ }
+ const result = (
+ await API.graphql({
+ query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ variables,
+ })
+ )?.data?.listPosts?.items;
+ var loaded = result.filter(
+ (item) => !PostIdSet.has(getIDValue.Post?.(item))
+ );
+ newOptions.push(...loaded);
+ newNext = result.nextToken;
+ }
+ setPostRecords(newOptions.slice(0, autocompleteLength));
+ setPostLoading(false);
+ };
+ React.useEffect(() => {
+ fetchPostIDRecords(\\"\\");
+ fetchPostRecords(\\"\\");
+ }, []);
+ return (
+ {
+ event.preventDefault();
+ let modelFields = {
+ content: content ?? null,
+ postID,
+ Post: Post ?? null,
+ post: post ?? null,
+ };
+ const validationResponses = await Promise.all(
+ Object.keys(validations).reduce((promises, fieldName) => {
+ if (Array.isArray(modelFields[fieldName])) {
+ promises.push(
+ ...modelFields[fieldName].map((item) =>
+ runValidationTasks(
+ fieldName,
+ item,
+ getDisplayValue[fieldName]
+ )
+ )
+ );
+ return promises;
+ }
+ promises.push(
+ runValidationTasks(
+ fieldName,
+ modelFields[fieldName],
+ getDisplayValue[fieldName]
+ )
+ );
+ return promises;
+ }, [])
+ );
+ if (validationResponses.some((r) => r.hasError)) {
+ return;
+ }
+ if (onSubmit) {
+ modelFields = onSubmit(modelFields);
+ }
+ try {
+ Object.entries(modelFields).forEach(([key, value]) => {
+ if (typeof value === \\"string\\" && value === \\"\\") {
+ modelFields[key] = null;
+ }
+ });
+ const modelFieldsToSave = {
+ content: modelFields.content ?? null,
+ postID: modelFields.postID,
+ postCommentsId: modelFields?.Post?.id ?? null,
+ };
+ await API.graphql({
+ query: updateComment.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: commentRecord.id,
+ ...modelFieldsToSave,
+ },
+ },
+ });
+ if (onSuccess) {
+ onSuccess(modelFields);
+ }
+ } catch (err) {
+ if (onError) {
+ const messages = err.errors.map((e) => e.message).join(\\"\\\\n\\");
+ onError(modelFields, messages);
+ }
+ }
+ }}
+ {...getOverrideProps(overrides, \\"CommentUpdateForm\\")}
+ {...rest}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ content: value,
postID,
Post,
post: post1,
@@ -11816,11 +14066,10 @@ export default function CommentUpdateForm(props) {
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship 2`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship without types file 2`] = `
"import * as React from \\"react\\";
import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
-import { Comment, Post } from \\"../API\\";
export declare type ValidationResponse = {
hasError: boolean;
errorMessage?: string;
@@ -11829,13 +14078,13 @@ export declare type ValidationFunction = (value: T, validationResponse: Valid
export declare type CommentUpdateFormInputValues = {
content?: string;
postID?: string;
- Post?: Post;
+ Post?: any;
post?: string;
};
export declare type CommentUpdateFormValidationValues = {
content?: ValidationFunction;
postID?: ValidationFunction;
- Post?: ValidationFunction;
+ Post?: ValidationFunction;
post?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
@@ -11850,7 +14099,7 @@ export declare type CommentUpdateFormProps = React.PropsWithChildren<{
overrides?: CommentUpdateFormOverridesProps | undefined | null;
} & {
id?: string;
- comment?: Comment;
+ comment?: any;
onSubmit?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
onSuccess?: (fields: CommentUpdateFormInputValues) => void;
onError?: (fields: CommentUpdateFormInputValues, errorMessage: string) => void;
@@ -11861,7 +14110,7 @@ export default function CommentUpdateForm(props: CommentUpdateFormProps): React.
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship without types file - amplify js v6 1`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with id field instead of belongsTo 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import {
@@ -11879,10 +14128,9 @@ import {
} from \\"@aws-amplify/ui-react\\";
import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
import { fetchByPath, validateField } from \\"./utils\\";
-import { generateClient } from \\"aws-amplify/api\\";
+import { API } from \\"aws-amplify\\";
import { getComment, getPost, listPosts } from \\"../graphql/queries\\";
import { updateComment } from \\"../graphql/mutations\\";
-const client = generateClient();
function ArrayField({
items = [],
onChange,
@@ -12053,32 +14301,22 @@ export default function CommentUpdateForm(props) {
const initialValues = {
content: \\"\\",
postID: undefined,
- Post: undefined,
- post: \\"\\",
};
const [content, setContent] = React.useState(initialValues.content);
const [postID, setPostID] = React.useState(initialValues.postID);
const [postIDLoading, setPostIDLoading] = React.useState(false);
const [postIDRecords, setPostIDRecords] = React.useState([]);
const [selectedPostIDRecords, setSelectedPostIDRecords] = React.useState([]);
- const [Post, setPost] = React.useState(initialValues.Post);
- const [PostLoading, setPostLoading] = React.useState(false);
- const [PostRecords, setPostRecords] = React.useState([]);
- const [post1, setPost1] = React.useState(initialValues.post);
const autocompleteLength = 10;
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
const cleanValues = commentRecord
- ? { ...initialValues, ...commentRecord, postID, Post }
+ ? { ...initialValues, ...commentRecord, postID }
: initialValues;
setContent(cleanValues.content);
setPostID(cleanValues.postID);
setCurrentPostIDValue(undefined);
setCurrentPostIDDisplayValue(\\"\\");
- setPost(cleanValues.Post);
- setCurrentPostValue(undefined);
- setCurrentPostDisplayValue(\\"\\");
- setPost1(cleanValues.post);
setErrors({});
};
const [commentRecord, setCommentRecord] = React.useState(commentModelProp);
@@ -12086,7 +14324,7 @@ export default function CommentUpdateForm(props) {
const queryData = async () => {
const record = idProp
? (
- await client.graphql({
+ await API.graphql({
query: getComment.replaceAll(\\"__typename\\", \\"\\"),
variables: { id: idProp },
})
@@ -12095,7 +14333,7 @@ export default function CommentUpdateForm(props) {
const postIDRecord = record ? record.postID : undefined;
const postRecord = postIDRecord
? (
- await client.graphql({
+ await API.graphql({
query: getPost.replaceAll(\\"__typename\\", \\"\\"),
variables: { id: postIDRecord },
})
@@ -12103,38 +14341,21 @@ export default function CommentUpdateForm(props) {
: undefined;
setPostID(postIDRecord);
setSelectedPostIDRecords([postRecord]);
- const PostRecord = record ? await record.Post : undefined;
- setPost(PostRecord);
setCommentRecord(record);
};
queryData();
}, [idProp, commentModelProp]);
- React.useEffect(resetStateValues, [commentRecord, postID, Post]);
+ React.useEffect(resetStateValues, [commentRecord, postID]);
const [currentPostIDDisplayValue, setCurrentPostIDDisplayValue] =
React.useState(\\"\\");
const [currentPostIDValue, setCurrentPostIDValue] = React.useState(undefined);
const postIDRef = React.createRef();
- const [currentPostDisplayValue, setCurrentPostDisplayValue] =
- React.useState(\\"\\");
- const [currentPostValue, setCurrentPostValue] = React.useState(undefined);
- const PostRef = React.createRef();
- const getIDValue = {
- Post: (r) => JSON.stringify({ id: r?.id }),
- };
- const PostIdSet = new Set(
- Array.isArray(Post)
- ? Post.map((r) => getIDValue.Post?.(r))
- : getIDValue.Post?.(Post)
- );
const getDisplayValue = {
postID: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
- Post: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
};
const validations = {
- content: [],
- postID: [{ type: \\"Required\\" }],
- Post: [],
- post: [],
+ content: [{ type: \\"Required\\" }],
+ postID: [],
};
const runValidationTasks = async (
fieldName,
@@ -12168,7 +14389,7 @@ export default function CommentUpdateForm(props) {
variables[\\"nextToken\\"] = newNext;
}
const result = (
- await client.graphql({
+ await API.graphql({
query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
variables,
})
@@ -12180,38 +14401,8 @@ export default function CommentUpdateForm(props) {
setPostIDRecords(newOptions.slice(0, autocompleteLength));
setPostIDLoading(false);
};
- const fetchPostRecords = async (value) => {
- setPostLoading(true);
- const newOptions = [];
- let newNext = \\"\\";
- while (newOptions.length < autocompleteLength && newNext != null) {
- const variables = {
- limit: autocompleteLength * 5,
- filter: {
- or: [{ title: { contains: value } }, { id: { contains: value } }],
- },
- };
- if (newNext) {
- variables[\\"nextToken\\"] = newNext;
- }
- const result = (
- await client.graphql({
- query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
- variables,
- })
- )?.data?.listPosts?.items;
- var loaded = result.filter(
- (item) => !PostIdSet.has(getIDValue.Post?.(item))
- );
- newOptions.push(...loaded);
- newNext = result.nextToken;
- }
- setPostRecords(newOptions.slice(0, autocompleteLength));
- setPostLoading(false);
- };
React.useEffect(() => {
fetchPostIDRecords(\\"\\");
- fetchPostRecords(\\"\\");
}, []);
return (
{
event.preventDefault();
let modelFields = {
- content: content ?? null,
- postID,
- Post: Post ?? null,
- post: post ?? null,
+ content,
+ postID: postID ?? null,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
if (Array.isArray(modelFields[fieldName])) {
promises.push(
...modelFields[fieldName].map((item) =>
- runValidationTasks(
- fieldName,
- item,
- getDisplayValue[fieldName]
- )
+ runValidationTasks(fieldName, item)
)
);
return promises;
}
promises.push(
- runValidationTasks(
- fieldName,
- modelFields[fieldName],
- getDisplayValue[fieldName]
- )
+ runValidationTasks(fieldName, modelFields[fieldName])
);
return promises;
}, [])
@@ -12263,17 +14444,12 @@ export default function CommentUpdateForm(props) {
modelFields[key] = null;
}
});
- const modelFieldsToSave = {
- content: modelFields.content ?? null,
- postID: modelFields.postID,
- postCommentsId: modelFields?.Post?.id ?? null,
- };
- await client.graphql({
+ await API.graphql({
query: updateComment.replaceAll(\\"__typename\\", \\"\\"),
variables: {
input: {
id: commentRecord.id,
- ...modelFieldsToSave,
+ ...modelFields,
},
},
});
@@ -12292,7 +14468,7 @@ export default function CommentUpdateForm(props) {
>
{
@@ -12301,8 +14477,6 @@ export default function CommentUpdateForm(props) {
const modelFields = {
content: value,
postID,
- Post,
- post: post1,
};
const result = onChange(modelFields);
value = result?.content ?? value;
@@ -12325,8 +14499,6 @@ export default function CommentUpdateForm(props) {
const modelFields = {
content,
postID: value,
- Post,
- post: post1,
};
const result = onChange(modelFields);
value = result?.postID ?? value;
@@ -12370,7 +14542,7 @@ export default function CommentUpdateForm(props) {
>
- {
- let value = items[0];
- if (onChange) {
- const modelFields = {
- content,
- postID,
- Post: value,
- post: post1,
- };
- const result = onChange(modelFields);
- value = result?.Post ?? value;
- }
- setPost(value);
- setCurrentPostValue(undefined);
- setCurrentPostDisplayValue(\\"\\");
- }}
- currentFieldValue={currentPostValue}
- label={\\"Post\\"}
- items={Post ? [Post] : []}
- hasError={errors?.Post?.hasError}
- runValidationTasks={async () =>
- await runValidationTasks(\\"Post\\", currentPostValue)
- }
- errorMessage={errors?.Post?.errorMessage}
- getBadgeText={getDisplayValue.Post}
- setFieldValue={(model) => {
- setCurrentPostDisplayValue(model ? getDisplayValue.Post(model) : \\"\\");
- setCurrentPostValue(model);
- }}
- inputFieldRef={PostRef}
- defaultFieldValue={\\"\\"}
- >
- !PostIdSet.has(getIDValue.Post?.(r))
- ).map((r) => ({
- id: getIDValue.Post?.(r),
- label: getDisplayValue.Post?.(r),
- }))}
- isLoading={PostLoading}
- onSelect={({ id, label }) => {
- setCurrentPostValue(
- PostRecords.find((r) =>
- Object.entries(JSON.parse(id)).every(
- ([key, value]) => r[key] === value
- )
- )
- );
- setCurrentPostDisplayValue(label);
- runValidationTasks(\\"Post\\", label);
- }}
- onClear={() => {
- setCurrentPostDisplayValue(\\"\\");
- }}
- defaultValue={Post}
- onChange={(e) => {
- let { value } = e.target;
- fetchPostRecords(value);
- if (errors.Post?.hasError) {
- runValidationTasks(\\"Post\\", value);
- }
- setCurrentPostDisplayValue(value);
- setCurrentPostValue(undefined);
- }}
- onBlur={() => runValidationTasks(\\"Post\\", currentPostDisplayValue)}
- errorMessage={errors.Post?.errorMessage}
- hasError={errors.Post?.hasError}
- ref={PostRef}
- labelHidden={true}
- {...getOverrideProps(overrides, \\"Post\\")}
- >
-
- {
- let { value } = e.target;
- if (onChange) {
- const modelFields = {
- content,
- postID,
- Post,
- post: value,
- };
- const result = onChange(modelFields);
- value = result?.post ?? value;
- }
- if (errors.post?.hasError) {
- runValidationTasks(\\"post\\", value);
- }
- setPost1(value);
- }}
- onBlur={() => runValidationTasks(\\"post\\", post1)}
- errorMessage={errors.post?.errorMessage}
- hasError={errors.post?.hasError}
- {...getOverrideProps(overrides, \\"post\\")}
- >
= (value: T, validationResponse: Valid
export declare type CommentUpdateFormInputValues = {
content?: string;
postID?: string;
- Post?: any;
- post?: string;
};
export declare type CommentUpdateFormValidationValues = {
content?: ValidationFunction;
postID?: ValidationFunction;
- Post?: ValidationFunction;
- post?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
export declare type CommentUpdateFormOverridesProps = {
CommentUpdateFormGrid?: PrimitiveOverrideProps;
content?: PrimitiveOverrideProps;
postID?: PrimitiveOverrideProps;
- Post?: PrimitiveOverrideProps;
- post?: PrimitiveOverrideProps;
} & EscapeHatchProps;
export declare type CommentUpdateFormProps = React.PropsWithChildren<{
overrides?: CommentUpdateFormOverridesProps | undefined | null;
} & {
id?: string;
- comment?: any;
+ comment?: Comment;
onSubmit?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
onSuccess?: (fields: CommentUpdateFormInputValues) => void;
onError?: (fields: CommentUpdateFormInputValues, errorMessage: string) => void;
@@ -12594,7 +14657,7 @@ export default function CommentUpdateForm(props: CommentUpdateFormProps): React.
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship without types file 1`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with many to many relationship - amplify js v6 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import {
@@ -12607,14 +14670,23 @@ import {
Icon,
ScrollView,
Text,
- TextField,
useTheme,
} from \\"@aws-amplify/ui-react\\";
import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
import { fetchByPath, validateField } from \\"./utils\\";
-import { API } from \\"aws-amplify\\";
-import { getComment, getPost, listPosts } from \\"../graphql/queries\\";
-import { updateComment } from \\"../graphql/mutations\\";
+import {
+ getClass,
+ listStudentClasses,
+ listStudents,
+ studentClassesByClassId,
+} from \\"../graphql/queries\\";
+import { generateClient } from \\"aws-amplify/api\\";
+import {
+ createStudentClass,
+ deleteStudentClass,
+ updateClass,
+} from \\"../graphql/mutations\\";
+const client = generateClient();
function ArrayField({
items = [],
onChange,
@@ -12770,10 +14842,10 @@ function ArrayField({
);
}
-export default function CommentUpdateForm(props) {
+export default function ClassUpdateForm(props) {
const {
id: idProp,
- comment: commentModelProp,
+ class: classModelProp,
onSuccess,
onError,
onSubmit,
@@ -12783,90 +14855,69 @@ export default function CommentUpdateForm(props) {
...rest
} = props;
const initialValues = {
- content: \\"\\",
- postID: undefined,
- Post: undefined,
- post: \\"\\",
+ students: [],
};
- const [content, setContent] = React.useState(initialValues.content);
- const [postID, setPostID] = React.useState(initialValues.postID);
- const [postIDLoading, setPostIDLoading] = React.useState(false);
- const [postIDRecords, setPostIDRecords] = React.useState([]);
- const [selectedPostIDRecords, setSelectedPostIDRecords] = React.useState([]);
- const [Post, setPost] = React.useState(initialValues.Post);
- const [PostLoading, setPostLoading] = React.useState(false);
- const [PostRecords, setPostRecords] = React.useState([]);
- const [post1, setPost1] = React.useState(initialValues.post);
+ const [students, setStudents] = React.useState(initialValues.students);
+ const [studentsLoading, setStudentsLoading] = React.useState(false);
+ const [studentsRecords, setStudentsRecords] = React.useState([]);
const autocompleteLength = 10;
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
- const cleanValues = commentRecord
- ? { ...initialValues, ...commentRecord, postID, Post }
+ const cleanValues = classRecord
+ ? { ...initialValues, ...classRecord, students: linkedStudents }
: initialValues;
- setContent(cleanValues.content);
- setPostID(cleanValues.postID);
- setCurrentPostIDValue(undefined);
- setCurrentPostIDDisplayValue(\\"\\");
- setPost(cleanValues.Post);
- setCurrentPostValue(undefined);
- setCurrentPostDisplayValue(\\"\\");
- setPost1(cleanValues.post);
+ setStudents(cleanValues.students ?? []);
+ setCurrentStudentsValue(undefined);
+ setCurrentStudentsDisplayValue(\\"\\");
setErrors({});
};
- const [commentRecord, setCommentRecord] = React.useState(commentModelProp);
+ const [classRecord, setClassRecord] = React.useState(classModelProp);
+ const [linkedStudents, setLinkedStudents] = React.useState([]);
+ const canUnlinkStudents = false;
React.useEffect(() => {
const queryData = async () => {
const record = idProp
? (
- await API.graphql({
- query: getComment.replaceAll(\\"__typename\\", \\"\\"),
+ await client.graphql({
+ query: getClass.replaceAll(\\"__typename\\", \\"\\"),
variables: { id: idProp },
})
- )?.data?.getComment
- : commentModelProp;
- const postIDRecord = record ? record.postID : undefined;
- const postRecord = postIDRecord
+ )?.data?.getClass
+ : classModelProp;
+ const linkedStudents = record
? (
- await API.graphql({
- query: getPost.replaceAll(\\"__typename\\", \\"\\"),
- variables: { id: postIDRecord },
+ await client.graphql({
+ query: studentClassesByClassId.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ classId: record.id,
+ },
})
- )?.data?.getPost
- : undefined;
- setPostID(postIDRecord);
- setSelectedPostIDRecords([postRecord]);
- const PostRecord = record ? await record.Post : undefined;
- setPost(PostRecord);
- setCommentRecord(record);
+ ).data.studentClassesByClassId.items.map((t) => t.student)
+ : [];
+ setLinkedStudents(linkedStudents);
+ setClassRecord(record);
};
queryData();
- }, [idProp, commentModelProp]);
- React.useEffect(resetStateValues, [commentRecord, postID, Post]);
- const [currentPostIDDisplayValue, setCurrentPostIDDisplayValue] =
- React.useState(\\"\\");
- const [currentPostIDValue, setCurrentPostIDValue] = React.useState(undefined);
- const postIDRef = React.createRef();
- const [currentPostDisplayValue, setCurrentPostDisplayValue] =
+ }, [idProp, classModelProp]);
+ React.useEffect(resetStateValues, [classRecord, linkedStudents]);
+ const [currentStudentsDisplayValue, setCurrentStudentsDisplayValue] =
React.useState(\\"\\");
- const [currentPostValue, setCurrentPostValue] = React.useState(undefined);
- const PostRef = React.createRef();
+ const [currentStudentsValue, setCurrentStudentsValue] =
+ React.useState(undefined);
+ const studentsRef = React.createRef();
const getIDValue = {
- Post: (r) => JSON.stringify({ id: r?.id }),
+ students: (r) => JSON.stringify({ id: r?.id }),
};
- const PostIdSet = new Set(
- Array.isArray(Post)
- ? Post.map((r) => getIDValue.Post?.(r))
- : getIDValue.Post?.(Post)
+ const studentsIdSet = new Set(
+ Array.isArray(students)
+ ? students.map((r) => getIDValue.students?.(r))
+ : getIDValue.students?.(students)
);
const getDisplayValue = {
- postID: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
- Post: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ students: (r) => r?.id,
};
const validations = {
- content: [],
- postID: [{ type: \\"Required\\" }],
- Post: [],
- post: [],
+ students: [],
};
const runValidationTasks = async (
fieldName,
@@ -12885,65 +14936,35 @@ export default function CommentUpdateForm(props) {
setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
return validationResponse;
};
- const fetchPostIDRecords = async (value) => {
- setPostIDLoading(true);
- const newOptions = [];
- let newNext = \\"\\";
- while (newOptions.length < autocompleteLength && newNext != null) {
- const variables = {
- limit: autocompleteLength * 5,
- filter: {
- or: [{ title: { contains: value } }, { id: { contains: value } }],
- },
- };
- if (newNext) {
- variables[\\"nextToken\\"] = newNext;
- }
- const result = (
- await API.graphql({
- query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
- variables,
- })
- )?.data?.listPosts?.items;
- var loaded = result.filter((item) => postID !== item.id);
- newOptions.push(...loaded);
- newNext = result.nextToken;
- }
- setPostIDRecords(newOptions.slice(0, autocompleteLength));
- setPostIDLoading(false);
- };
- const fetchPostRecords = async (value) => {
- setPostLoading(true);
+ const fetchStudentsRecords = async (value) => {
+ setStudentsLoading(true);
const newOptions = [];
let newNext = \\"\\";
while (newOptions.length < autocompleteLength && newNext != null) {
const variables = {
limit: autocompleteLength * 5,
- filter: {
- or: [{ title: { contains: value } }, { id: { contains: value } }],
- },
+ filter: { or: [{ id: { contains: value } }] },
};
if (newNext) {
variables[\\"nextToken\\"] = newNext;
}
const result = (
- await API.graphql({
- query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ await client.graphql({
+ query: listStudents.replaceAll(\\"__typename\\", \\"\\"),
variables,
})
- )?.data?.listPosts?.items;
+ )?.data?.listStudents?.items;
var loaded = result.filter(
- (item) => !PostIdSet.has(getIDValue.Post?.(item))
+ (item) => !studentsIdSet.has(getIDValue.students?.(item))
);
newOptions.push(...loaded);
newNext = result.nextToken;
}
- setPostRecords(newOptions.slice(0, autocompleteLength));
- setPostLoading(false);
+ setStudentsRecords(newOptions.slice(0, autocompleteLength));
+ setStudentsLoading(false);
};
React.useEffect(() => {
- fetchPostIDRecords(\\"\\");
- fetchPostRecords(\\"\\");
+ fetchStudentsRecords(\\"\\");
}, []);
return (
{
event.preventDefault();
let modelFields = {
- content: content ?? null,
- postID,
- Post: Post ?? null,
- post: post ?? null,
+ students: students ?? null,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
@@ -12995,20 +15013,104 @@ export default function CommentUpdateForm(props) {
modelFields[key] = null;
}
});
- const modelFieldsToSave = {
- content: modelFields.content ?? null,
- postID: modelFields.postID,
- postCommentsId: modelFields?.Post?.id ?? null,
- };
- await API.graphql({
- query: updateComment.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- input: {
- id: commentRecord.id,
- ...modelFieldsToSave,
- },
- },
+ const promises = [];
+ const studentsToLinkMap = new Map();
+ const studentsToUnLinkMap = new Map();
+ const studentsMap = new Map();
+ const linkedStudentsMap = new Map();
+ students.forEach((r) => {
+ const count = studentsMap.get(getIDValue.students?.(r));
+ const newCount = count ? count + 1 : 1;
+ studentsMap.set(getIDValue.students?.(r), newCount);
+ });
+ linkedStudents.forEach((r) => {
+ const count = linkedStudentsMap.get(getIDValue.students?.(r));
+ const newCount = count ? count + 1 : 1;
+ linkedStudentsMap.set(getIDValue.students?.(r), newCount);
+ });
+ linkedStudentsMap.forEach((count, id) => {
+ const newCount = studentsMap.get(id);
+ if (newCount) {
+ const diffCount = count - newCount;
+ if (diffCount > 0) {
+ studentsToUnLinkMap.set(id, diffCount);
+ }
+ } else {
+ studentsToUnLinkMap.set(id, count);
+ }
+ });
+ studentsMap.forEach((count, id) => {
+ const originalCount = linkedStudentsMap.get(id);
+ if (originalCount) {
+ const diffCount = count - originalCount;
+ if (diffCount > 0) {
+ studentsToLinkMap.set(id, diffCount);
+ }
+ } else {
+ studentsToLinkMap.set(id, count);
+ }
+ });
+ studentsToUnLinkMap.forEach(async (count, id) => {
+ const recordKeys = JSON.parse(id);
+ const studentClassRecords = (
+ await client.graphql({
+ query: listStudentClasses.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ filter: {
+ and: [
+ { studentId: { eq: recordKeys.id } },
+ { classId: { eq: classRecord.id } },
+ ],
+ },
+ },
+ })
+ )?.data?.listStudentClasses?.items;
+ for (let i = 0; i < count; i++) {
+ promises.push(
+ client.graphql({
+ query: deleteStudentClass.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: studentClassRecords[i].id,
+ },
+ },
+ })
+ );
+ }
+ });
+ studentsToLinkMap.forEach((count, id) => {
+ const studentToLink = studentRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
+ );
+ for (let i = count; i > 0; i--) {
+ promises.push(
+ client.graphql({
+ query: createStudentClass.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ classId: classRecord.id,
+ studentId: studentToLink.id,
+ },
+ },
+ })
+ );
+ }
});
+ const modelFieldsToSave = {};
+ promises.push(
+ client.graphql({
+ query: updateClass.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: classRecord.id,
+ ...modelFieldsToSave,
+ },
+ },
+ })
+ );
+ await Promise.all(promises);
if (onSuccess) {
onSuccess(modelFields);
}
@@ -13019,233 +15121,85 @@ export default function CommentUpdateForm(props) {
}
}
}}
- {...getOverrideProps(overrides, \\"CommentUpdateForm\\")}
+ {...getOverrideProps(overrides, \\"ClassUpdateForm\\")}
{...rest}
>
- {
- let { value } = e.target;
- if (onChange) {
- const modelFields = {
- content: value,
- postID,
- Post,
- post: post1,
- };
- const result = onChange(modelFields);
- value = result?.content ?? value;
- }
- if (errors.content?.hasError) {
- runValidationTasks(\\"content\\", value);
- }
- setContent(value);
- }}
- onBlur={() => runValidationTasks(\\"content\\", content)}
- errorMessage={errors.content?.errorMessage}
- hasError={errors.content?.hasError}
- {...getOverrideProps(overrides, \\"content\\")}
- >
- {
- let value = items[0];
- if (onChange) {
- const modelFields = {
- content,
- postID: value,
- Post,
- post: post1,
- };
- const result = onChange(modelFields);
- value = result?.postID ?? value;
- }
- setPostID(value);
- setCurrentPostIDValue(undefined);
- }}
- currentFieldValue={currentPostIDValue}
- label={\\"Post id\\"}
- items={postID ? [postID] : []}
- hasError={errors?.postID?.hasError}
- runValidationTasks={async () =>
- await runValidationTasks(\\"postID\\", currentPostIDValue)
- }
- errorMessage={errors?.postID?.errorMessage}
- getBadgeText={(value) =>
- value
- ? getDisplayValue.postID(
- postIDRecords.find((r) => r.id === value) ??
- selectedPostIDRecords.find((r) => r.id === value)
- )
- : \\"\\"
- }
- setFieldValue={(value) => {
- setCurrentPostIDDisplayValue(
- value
- ? getDisplayValue.postID(
- postIDRecords.find((r) => r.id === value) ??
- selectedPostIDRecords.find((r) => r.id === value)
- )
- : \\"\\"
- );
- setCurrentPostIDValue(value);
- const selectedRecord = postIDRecords.find((r) => r.id === value);
- if (selectedRecord) {
- setSelectedPostIDRecords([selectedRecord]);
- }
- }}
- inputFieldRef={postIDRef}
- defaultFieldValue={\\"\\"}
- >
-
- arr.findIndex((member) => member?.id === r?.id) === i
- )
- .map((r) => ({
- id: r?.id,
- label: getDisplayValue.postID?.(r),
- }))}
- isLoading={postIDLoading}
- onSelect={({ id, label }) => {
- setCurrentPostIDValue(id);
- setCurrentPostIDDisplayValue(label);
- runValidationTasks(\\"postID\\", label);
- }}
- onClear={() => {
- setCurrentPostIDDisplayValue(\\"\\");
- }}
- defaultValue={postID}
- onChange={(e) => {
- let { value } = e.target;
- fetchPostIDRecords(value);
- if (errors.postID?.hasError) {
- runValidationTasks(\\"postID\\", value);
- }
- setCurrentPostIDDisplayValue(value);
- setCurrentPostIDValue(undefined);
- }}
- onBlur={() => runValidationTasks(\\"postID\\", currentPostIDValue)}
- errorMessage={errors.postID?.errorMessage}
- hasError={errors.postID?.hasError}
- ref={postIDRef}
- labelHidden={true}
- {...getOverrideProps(overrides, \\"postID\\")}
- >
-
{
- let value = items[0];
+ let values = items;
if (onChange) {
const modelFields = {
- content,
- postID,
- Post: value,
- post: post1,
+ students: values,
};
const result = onChange(modelFields);
- value = result?.Post ?? value;
+ values = result?.students ?? values;
}
- setPost(value);
- setCurrentPostValue(undefined);
- setCurrentPostDisplayValue(\\"\\");
+ setStudents(values);
+ setCurrentStudentsValue(undefined);
+ setCurrentStudentsDisplayValue(\\"\\");
}}
- currentFieldValue={currentPostValue}
- label={\\"Post\\"}
- items={Post ? [Post] : []}
- hasError={errors?.Post?.hasError}
+ currentFieldValue={currentStudentsValue}
+ label={\\"Students\\"}
+ items={students}
+ hasError={errors?.students?.hasError}
runValidationTasks={async () =>
- await runValidationTasks(\\"Post\\", currentPostValue)
+ await runValidationTasks(\\"students\\", currentStudentsValue)
}
- errorMessage={errors?.Post?.errorMessage}
- getBadgeText={getDisplayValue.Post}
+ errorMessage={errors?.students?.errorMessage}
+ getBadgeText={getDisplayValue.students}
setFieldValue={(model) => {
- setCurrentPostDisplayValue(model ? getDisplayValue.Post(model) : \\"\\");
- setCurrentPostValue(model);
+ setCurrentStudentsDisplayValue(
+ model ? getDisplayValue.students(model) : \\"\\"
+ );
+ setCurrentStudentsValue(model);
}}
- inputFieldRef={PostRef}
+ inputFieldRef={studentsRef}
defaultFieldValue={\\"\\"}
>
!PostIdSet.has(getIDValue.Post?.(r))
- ).map((r) => ({
- id: getIDValue.Post?.(r),
- label: getDisplayValue.Post?.(r),
+ placeholder=\\"Search Student\\"
+ value={currentStudentsDisplayValue}
+ options={studentsRecords.map((r) => ({
+ id: getIDValue.students?.(r),
+ label: getDisplayValue.students?.(r),
}))}
- isLoading={PostLoading}
+ isLoading={studentsLoading}
onSelect={({ id, label }) => {
- setCurrentPostValue(
- PostRecords.find((r) =>
+ setCurrentStudentsValue(
+ studentsRecords.find((r) =>
Object.entries(JSON.parse(id)).every(
([key, value]) => r[key] === value
)
)
);
- setCurrentPostDisplayValue(label);
- runValidationTasks(\\"Post\\", label);
+ setCurrentStudentsDisplayValue(label);
+ runValidationTasks(\\"students\\", label);
}}
onClear={() => {
- setCurrentPostDisplayValue(\\"\\");
+ setCurrentStudentsDisplayValue(\\"\\");
}}
- defaultValue={Post}
onChange={(e) => {
let { value } = e.target;
- fetchPostRecords(value);
- if (errors.Post?.hasError) {
- runValidationTasks(\\"Post\\", value);
+ fetchStudentsRecords(value);
+ if (errors.students?.hasError) {
+ runValidationTasks(\\"students\\", value);
}
- setCurrentPostDisplayValue(value);
- setCurrentPostValue(undefined);
+ setCurrentStudentsDisplayValue(value);
+ setCurrentStudentsValue(undefined);
}}
- onBlur={() => runValidationTasks(\\"Post\\", currentPostDisplayValue)}
- errorMessage={errors.Post?.errorMessage}
- hasError={errors.Post?.hasError}
- ref={PostRef}
+ onBlur={() =>
+ runValidationTasks(\\"students\\", currentStudentsDisplayValue)
+ }
+ errorMessage={errors.students?.errorMessage}
+ hasError={errors.students?.hasError}
+ ref={studentsRef}
labelHidden={true}
- {...getOverrideProps(overrides, \\"Post\\")}
+ {...getOverrideProps(overrides, \\"students\\")}
>
- {
- let { value } = e.target;
- if (onChange) {
- const modelFields = {
- content,
- postID,
- Post,
- post: value,
- };
- const result = onChange(modelFields);
- value = result?.post ?? value;
- }
- if (errors.post?.hasError) {
- runValidationTasks(\\"post\\", value);
- }
- setPost1(value);
- }}
- onBlur={() => runValidationTasks(\\"post\\", post1)}
- errorMessage={errors.post?.errorMessage}
- hasError={errors.post?.hasError}
- {...getOverrideProps(overrides, \\"post\\")}
- >
e?.hasError)
}
{...getOverrideProps(overrides, \\"SubmitButton\\")}
@@ -13282,51 +15236,43 @@ export default function CommentUpdateForm(props) {
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with hasMany relationship without types file 2`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with many to many relationship - amplify js v6 2`] = `
"import * as React from \\"react\\";
-import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
+import { AutocompleteProps, GridProps } from \\"@aws-amplify/ui-react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
+import { Class, Student } from \\"../API\\";
export declare type ValidationResponse = {
hasError: boolean;
errorMessage?: string;
};
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
-export declare type CommentUpdateFormInputValues = {
- content?: string;
- postID?: string;
- Post?: any;
- post?: string;
+export declare type ClassUpdateFormInputValues = {
+ students?: Student[];
};
-export declare type CommentUpdateFormValidationValues = {
- content?: ValidationFunction;
- postID?: ValidationFunction;
- Post?: ValidationFunction;
- post?: ValidationFunction;
+export declare type ClassUpdateFormValidationValues = {
+ students?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
-export declare type CommentUpdateFormOverridesProps = {
- CommentUpdateFormGrid?: PrimitiveOverrideProps;
- content?: PrimitiveOverrideProps;
- postID?: PrimitiveOverrideProps;
- Post?: PrimitiveOverrideProps;
- post?: PrimitiveOverrideProps;
+export declare type ClassUpdateFormOverridesProps = {
+ ClassUpdateFormGrid?: PrimitiveOverrideProps;
+ students?: PrimitiveOverrideProps;
} & EscapeHatchProps;
-export declare type CommentUpdateFormProps = React.PropsWithChildren<{
- overrides?: CommentUpdateFormOverridesProps | undefined | null;
+export declare type ClassUpdateFormProps = React.PropsWithChildren<{
+ overrides?: ClassUpdateFormOverridesProps | undefined | null;
} & {
id?: string;
- comment?: any;
- onSubmit?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
- onSuccess?: (fields: CommentUpdateFormInputValues) => void;
- onError?: (fields: CommentUpdateFormInputValues, errorMessage: string) => void;
- onChange?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
- onValidate?: CommentUpdateFormValidationValues;
+ class?: Class;
+ onSubmit?: (fields: ClassUpdateFormInputValues) => ClassUpdateFormInputValues;
+ onSuccess?: (fields: ClassUpdateFormInputValues) => void;
+ onError?: (fields: ClassUpdateFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: ClassUpdateFormInputValues) => ClassUpdateFormInputValues;
+ onValidate?: ClassUpdateFormValidationValues;
} & React.CSSProperties>;
-export default function CommentUpdateForm(props: CommentUpdateFormProps): React.ReactElement;
+export default function ClassUpdateForm(props: ClassUpdateFormProps): React.ReactElement;
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with id field instead of belongsTo 1`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with many to many relationship 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import {
@@ -13339,14 +15285,22 @@ import {
Icon,
ScrollView,
Text,
- TextField,
useTheme,
} from \\"@aws-amplify/ui-react\\";
import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
import { fetchByPath, validateField } from \\"./utils\\";
+import {
+ getClass,
+ listStudentClasses,
+ listStudents,
+ studentClassesByClassId,
+} from \\"../graphql/queries\\";
import { API } from \\"aws-amplify\\";
-import { getComment, getPost, listPosts } from \\"../graphql/queries\\";
-import { updateComment } from \\"../graphql/mutations\\";
+import {
+ createStudentClass,
+ deleteStudentClass,
+ updateClass,
+} from \\"../graphql/mutations\\";
function ArrayField({
items = [],
onChange,
@@ -13502,10 +15456,10 @@ function ArrayField({
);
}
-export default function CommentUpdateForm(props) {
+export default function ClassUpdateForm(props) {
const {
id: idProp,
- comment: commentModelProp,
+ class: classModelProp,
onSuccess,
onError,
onSubmit,
@@ -13515,63 +15469,69 @@ export default function CommentUpdateForm(props) {
...rest
} = props;
const initialValues = {
- content: \\"\\",
- postID: undefined,
+ students: [],
};
- const [content, setContent] = React.useState(initialValues.content);
- const [postID, setPostID] = React.useState(initialValues.postID);
- const [postIDLoading, setPostIDLoading] = React.useState(false);
- const [postIDRecords, setPostIDRecords] = React.useState([]);
- const [selectedPostIDRecords, setSelectedPostIDRecords] = React.useState([]);
+ const [students, setStudents] = React.useState(initialValues.students);
+ const [studentsLoading, setStudentsLoading] = React.useState(false);
+ const [studentsRecords, setStudentsRecords] = React.useState([]);
const autocompleteLength = 10;
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
- const cleanValues = commentRecord
- ? { ...initialValues, ...commentRecord, postID }
+ const cleanValues = classRecord
+ ? { ...initialValues, ...classRecord, students: linkedStudents }
: initialValues;
- setContent(cleanValues.content);
- setPostID(cleanValues.postID);
- setCurrentPostIDValue(undefined);
- setCurrentPostIDDisplayValue(\\"\\");
+ setStudents(cleanValues.students ?? []);
+ setCurrentStudentsValue(undefined);
+ setCurrentStudentsDisplayValue(\\"\\");
setErrors({});
};
- const [commentRecord, setCommentRecord] = React.useState(commentModelProp);
+ const [classRecord, setClassRecord] = React.useState(classModelProp);
+ const [linkedStudents, setLinkedStudents] = React.useState([]);
+ const canUnlinkStudents = false;
React.useEffect(() => {
const queryData = async () => {
const record = idProp
? (
await API.graphql({
- query: getComment.replaceAll(\\"__typename\\", \\"\\"),
+ query: getClass.replaceAll(\\"__typename\\", \\"\\"),
variables: { id: idProp },
})
- )?.data?.getComment
- : commentModelProp;
- const postIDRecord = record ? record.postID : undefined;
- const postRecord = postIDRecord
+ )?.data?.getClass
+ : classModelProp;
+ const linkedStudents = record
? (
await API.graphql({
- query: getPost.replaceAll(\\"__typename\\", \\"\\"),
- variables: { id: postIDRecord },
+ query: studentClassesByClassId.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ classId: record.id,
+ },
})
- )?.data?.getPost
- : undefined;
- setPostID(postIDRecord);
- setSelectedPostIDRecords([postRecord]);
- setCommentRecord(record);
+ ).data.studentClassesByClassId.items.map((t) => t.student)
+ : [];
+ setLinkedStudents(linkedStudents);
+ setClassRecord(record);
};
queryData();
- }, [idProp, commentModelProp]);
- React.useEffect(resetStateValues, [commentRecord, postID]);
- const [currentPostIDDisplayValue, setCurrentPostIDDisplayValue] =
+ }, [idProp, classModelProp]);
+ React.useEffect(resetStateValues, [classRecord, linkedStudents]);
+ const [currentStudentsDisplayValue, setCurrentStudentsDisplayValue] =
React.useState(\\"\\");
- const [currentPostIDValue, setCurrentPostIDValue] = React.useState(undefined);
- const postIDRef = React.createRef();
+ const [currentStudentsValue, setCurrentStudentsValue] =
+ React.useState(undefined);
+ const studentsRef = React.createRef();
+ const getIDValue = {
+ students: (r) => JSON.stringify({ id: r?.id }),
+ };
+ const studentsIdSet = new Set(
+ Array.isArray(students)
+ ? students.map((r) => getIDValue.students?.(r))
+ : getIDValue.students?.(students)
+ );
const getDisplayValue = {
- postID: (r) => \`\${r?.title ? r?.title + \\" - \\" : \\"\\"}\${r?.id}\`,
+ students: (r) => r?.id,
};
const validations = {
- content: [{ type: \\"Required\\" }],
- postID: [],
+ students: [],
};
const runValidationTasks = async (
fieldName,
@@ -13590,35 +15550,35 @@ export default function CommentUpdateForm(props) {
setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
return validationResponse;
};
- const fetchPostIDRecords = async (value) => {
- setPostIDLoading(true);
+ const fetchStudentsRecords = async (value) => {
+ setStudentsLoading(true);
const newOptions = [];
let newNext = \\"\\";
while (newOptions.length < autocompleteLength && newNext != null) {
const variables = {
limit: autocompleteLength * 5,
- filter: {
- or: [{ title: { contains: value } }, { id: { contains: value } }],
- },
+ filter: { or: [{ id: { contains: value } }] },
};
if (newNext) {
variables[\\"nextToken\\"] = newNext;
}
const result = (
await API.graphql({
- query: listPosts.replaceAll(\\"__typename\\", \\"\\"),
+ query: listStudents.replaceAll(\\"__typename\\", \\"\\"),
variables,
})
- )?.data?.listPosts?.items;
- var loaded = result.filter((item) => postID !== item.id);
+ )?.data?.listStudents?.items;
+ var loaded = result.filter(
+ (item) => !studentsIdSet.has(getIDValue.students?.(item))
+ );
newOptions.push(...loaded);
newNext = result.nextToken;
}
- setPostIDRecords(newOptions.slice(0, autocompleteLength));
- setPostIDLoading(false);
+ setStudentsRecords(newOptions.slice(0, autocompleteLength));
+ setStudentsLoading(false);
};
React.useEffect(() => {
- fetchPostIDRecords(\\"\\");
+ fetchStudentsRecords(\\"\\");
}, []);
return (
{
event.preventDefault();
let modelFields = {
- content,
- postID: postID ?? null,
+ students: students ?? null,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
if (Array.isArray(modelFields[fieldName])) {
promises.push(
...modelFields[fieldName].map((item) =>
- runValidationTasks(fieldName, item)
+ runValidationTasks(
+ fieldName,
+ item,
+ getDisplayValue[fieldName]
+ )
)
);
- return promises;
+ return promises;
+ }
+ promises.push(
+ runValidationTasks(
+ fieldName,
+ modelFields[fieldName],
+ getDisplayValue[fieldName]
+ )
+ );
+ return promises;
+ }, [])
+ );
+ if (validationResponses.some((r) => r.hasError)) {
+ return;
+ }
+ if (onSubmit) {
+ modelFields = onSubmit(modelFields);
+ }
+ try {
+ Object.entries(modelFields).forEach(([key, value]) => {
+ if (typeof value === \\"string\\" && value === \\"\\") {
+ modelFields[key] = null;
+ }
+ });
+ const promises = [];
+ const studentsToLinkMap = new Map();
+ const studentsToUnLinkMap = new Map();
+ const studentsMap = new Map();
+ const linkedStudentsMap = new Map();
+ students.forEach((r) => {
+ const count = studentsMap.get(getIDValue.students?.(r));
+ const newCount = count ? count + 1 : 1;
+ studentsMap.set(getIDValue.students?.(r), newCount);
+ });
+ linkedStudents.forEach((r) => {
+ const count = linkedStudentsMap.get(getIDValue.students?.(r));
+ const newCount = count ? count + 1 : 1;
+ linkedStudentsMap.set(getIDValue.students?.(r), newCount);
+ });
+ linkedStudentsMap.forEach((count, id) => {
+ const newCount = studentsMap.get(id);
+ if (newCount) {
+ const diffCount = count - newCount;
+ if (diffCount > 0) {
+ studentsToUnLinkMap.set(id, diffCount);
+ }
+ } else {
+ studentsToUnLinkMap.set(id, count);
+ }
+ });
+ studentsMap.forEach((count, id) => {
+ const originalCount = linkedStudentsMap.get(id);
+ if (originalCount) {
+ const diffCount = count - originalCount;
+ if (diffCount > 0) {
+ studentsToLinkMap.set(id, diffCount);
+ }
+ } else {
+ studentsToLinkMap.set(id, count);
+ }
+ });
+ studentsToUnLinkMap.forEach(async (count, id) => {
+ const recordKeys = JSON.parse(id);
+ const studentClassRecords = (
+ await API.graphql({
+ query: listStudentClasses.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ filter: {
+ and: [
+ { studentId: { eq: recordKeys.id } },
+ { classId: { eq: classRecord.id } },
+ ],
+ },
+ },
+ })
+ )?.data?.listStudentClasses?.items;
+ for (let i = 0; i < count; i++) {
+ promises.push(
+ API.graphql({
+ query: deleteStudentClass.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: studentClassRecords[i].id,
+ },
+ },
+ })
+ );
}
- promises.push(
- runValidationTasks(fieldName, modelFields[fieldName])
+ });
+ studentsToLinkMap.forEach((count, id) => {
+ const studentToLink = studentRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
);
- return promises;
- }, [])
- );
- if (validationResponses.some((r) => r.hasError)) {
- return;
- }
- if (onSubmit) {
- modelFields = onSubmit(modelFields);
- }
- try {
- Object.entries(modelFields).forEach(([key, value]) => {
- if (typeof value === \\"string\\" && value === \\"\\") {
- modelFields[key] = null;
+ for (let i = count; i > 0; i--) {
+ promises.push(
+ API.graphql({
+ query: createStudentClass.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ classId: classRecord.id,
+ studentId: studentToLink.id,
+ },
+ },
+ })
+ );
}
});
- await API.graphql({
- query: updateComment.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- input: {
- id: commentRecord.id,
- ...modelFields,
+ const modelFieldsToSave = {};
+ promises.push(
+ API.graphql({
+ query: updateClass.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: classRecord.id,
+ ...modelFieldsToSave,
+ },
},
- },
- });
+ })
+ );
+ await Promise.all(promises);
if (onSuccess) {
onSuccess(modelFields);
}
@@ -13679,123 +15735,83 @@ export default function CommentUpdateForm(props) {
}
}
}}
- {...getOverrideProps(overrides, \\"CommentUpdateForm\\")}
+ {...getOverrideProps(overrides, \\"ClassUpdateForm\\")}
{...rest}
>
- {
- let { value } = e.target;
- if (onChange) {
- const modelFields = {
- content: value,
- postID,
- };
- const result = onChange(modelFields);
- value = result?.content ?? value;
- }
- if (errors.content?.hasError) {
- runValidationTasks(\\"content\\", value);
- }
- setContent(value);
- }}
- onBlur={() => runValidationTasks(\\"content\\", content)}
- errorMessage={errors.content?.errorMessage}
- hasError={errors.content?.hasError}
- {...getOverrideProps(overrides, \\"content\\")}
- >
{
- let value = items[0];
+ let values = items;
if (onChange) {
const modelFields = {
- content,
- postID: value,
+ students: values,
};
const result = onChange(modelFields);
- value = result?.postID ?? value;
+ values = result?.students ?? values;
}
- setPostID(value);
- setCurrentPostIDValue(undefined);
+ setStudents(values);
+ setCurrentStudentsValue(undefined);
+ setCurrentStudentsDisplayValue(\\"\\");
}}
- currentFieldValue={currentPostIDValue}
- label={\\"Post id\\"}
- items={postID ? [postID] : []}
- hasError={errors?.postID?.hasError}
+ currentFieldValue={currentStudentsValue}
+ label={\\"Students\\"}
+ items={students}
+ hasError={errors?.students?.hasError}
runValidationTasks={async () =>
- await runValidationTasks(\\"postID\\", currentPostIDValue)
- }
- errorMessage={errors?.postID?.errorMessage}
- getBadgeText={(value) =>
- value
- ? getDisplayValue.postID(
- postIDRecords.find((r) => r.id === value) ??
- selectedPostIDRecords.find((r) => r.id === value)
- )
- : \\"\\"
+ await runValidationTasks(\\"students\\", currentStudentsValue)
}
- setFieldValue={(value) => {
- setCurrentPostIDDisplayValue(
- value
- ? getDisplayValue.postID(
- postIDRecords.find((r) => r.id === value) ??
- selectedPostIDRecords.find((r) => r.id === value)
- )
- : \\"\\"
+ errorMessage={errors?.students?.errorMessage}
+ getBadgeText={getDisplayValue.students}
+ setFieldValue={(model) => {
+ setCurrentStudentsDisplayValue(
+ model ? getDisplayValue.students(model) : \\"\\"
);
- setCurrentPostIDValue(value);
- const selectedRecord = postIDRecords.find((r) => r.id === value);
- if (selectedRecord) {
- setSelectedPostIDRecords([selectedRecord]);
- }
+ setCurrentStudentsValue(model);
}}
- inputFieldRef={postIDRef}
+ inputFieldRef={studentsRef}
defaultFieldValue={\\"\\"}
>
- arr.findIndex((member) => member?.id === r?.id) === i
- )
- .map((r) => ({
- id: r?.id,
- label: getDisplayValue.postID?.(r),
- }))}
- isLoading={postIDLoading}
+ placeholder=\\"Search Student\\"
+ value={currentStudentsDisplayValue}
+ options={studentsRecords.map((r) => ({
+ id: getIDValue.students?.(r),
+ label: getDisplayValue.students?.(r),
+ }))}
+ isLoading={studentsLoading}
onSelect={({ id, label }) => {
- setCurrentPostIDValue(id);
- setCurrentPostIDDisplayValue(label);
- runValidationTasks(\\"postID\\", label);
+ setCurrentStudentsValue(
+ studentsRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
+ )
+ );
+ setCurrentStudentsDisplayValue(label);
+ runValidationTasks(\\"students\\", label);
}}
onClear={() => {
- setCurrentPostIDDisplayValue(\\"\\");
+ setCurrentStudentsDisplayValue(\\"\\");
}}
- defaultValue={postID}
onChange={(e) => {
let { value } = e.target;
- fetchPostIDRecords(value);
- if (errors.postID?.hasError) {
- runValidationTasks(\\"postID\\", value);
+ fetchStudentsRecords(value);
+ if (errors.students?.hasError) {
+ runValidationTasks(\\"students\\", value);
}
- setCurrentPostIDDisplayValue(value);
- setCurrentPostIDValue(undefined);
+ setCurrentStudentsDisplayValue(value);
+ setCurrentStudentsValue(undefined);
}}
- onBlur={() => runValidationTasks(\\"postID\\", currentPostIDValue)}
- errorMessage={errors.postID?.errorMessage}
- hasError={errors.postID?.hasError}
- ref={postIDRef}
+ onBlur={() =>
+ runValidationTasks(\\"students\\", currentStudentsDisplayValue)
+ }
+ errorMessage={errors.students?.errorMessage}
+ hasError={errors.students?.hasError}
+ ref={studentsRef}
labelHidden={true}
- {...getOverrideProps(overrides, \\"postID\\")}
+ {...getOverrideProps(overrides, \\"students\\")}
>
e?.hasError)
}
{...getOverrideProps(overrides, \\"SubmitButton\\")}
@@ -13834,46 +15850,43 @@ export default function CommentUpdateForm(props) {
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with id field instead of belongsTo 2`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with many to many relationship 2`] = `
"import * as React from \\"react\\";
-import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
+import { AutocompleteProps, GridProps } from \\"@aws-amplify/ui-react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
-import { Comment } from \\"../API\\";
+import { Class, Student } from \\"../API\\";
export declare type ValidationResponse = {
hasError: boolean;
errorMessage?: string;
};
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
-export declare type CommentUpdateFormInputValues = {
- content?: string;
- postID?: string;
+export declare type ClassUpdateFormInputValues = {
+ students?: Student[];
};
-export declare type CommentUpdateFormValidationValues = {
- content?: ValidationFunction;
- postID?: ValidationFunction;
+export declare type ClassUpdateFormValidationValues = {
+ students?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
-export declare type CommentUpdateFormOverridesProps = {
- CommentUpdateFormGrid?: PrimitiveOverrideProps;
- content?: PrimitiveOverrideProps;
- postID?: PrimitiveOverrideProps;
+export declare type ClassUpdateFormOverridesProps = {
+ ClassUpdateFormGrid?: PrimitiveOverrideProps;
+ students?: PrimitiveOverrideProps;
} & EscapeHatchProps;
-export declare type CommentUpdateFormProps = React.PropsWithChildren<{
- overrides?: CommentUpdateFormOverridesProps | undefined | null;
+export declare type ClassUpdateFormProps = React.PropsWithChildren<{
+ overrides?: ClassUpdateFormOverridesProps | undefined | null;
} & {
id?: string;
- comment?: Comment;
- onSubmit?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
- onSuccess?: (fields: CommentUpdateFormInputValues) => void;
- onError?: (fields: CommentUpdateFormInputValues, errorMessage: string) => void;
- onChange?: (fields: CommentUpdateFormInputValues) => CommentUpdateFormInputValues;
- onValidate?: CommentUpdateFormValidationValues;
+ class?: Class;
+ onSubmit?: (fields: ClassUpdateFormInputValues) => ClassUpdateFormInputValues;
+ onSuccess?: (fields: ClassUpdateFormInputValues) => void;
+ onError?: (fields: ClassUpdateFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: ClassUpdateFormInputValues) => ClassUpdateFormInputValues;
+ onValidate?: ClassUpdateFormValidationValues;
} & React.CSSProperties>;
-export default function CommentUpdateForm(props: CommentUpdateFormProps): React.ReactElement;
+export default function ClassUpdateForm(props: ClassUpdateFormProps): React.ReactElement;
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with many to many relationship 1`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with nonModel field 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import {
@@ -13886,22 +15899,15 @@ import {
Icon,
ScrollView,
Text,
+ TextAreaField,
+ TextField,
useTheme,
} from \\"@aws-amplify/ui-react\\";
import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
import { fetchByPath, validateField } from \\"./utils\\";
-import {
- getClass,
- listStudentClasses,
- listStudents,
- studentClassesByClassId,
-} from \\"../graphql/queries\\";
import { API } from \\"aws-amplify\\";
-import {
- createStudentClass,
- deleteStudentClass,
- updateClass,
-} from \\"../graphql/mutations\\";
+import { getBasicTable, listParentTables } from \\"../graphql/queries\\";
+import { updateBasicTable } from \\"../graphql/mutations\\";
function ArrayField({
items = [],
onChange,
@@ -14057,10 +16063,10 @@ function ArrayField({
);
}
-export default function ClassUpdateForm(props) {
+export default function UpdateForm(props) {
const {
id: idProp,
- class: classModelProp,
+ basicTable: basicTableModelProp,
onSuccess,
onError,
onSubmit,
@@ -14070,69 +16076,73 @@ export default function ClassUpdateForm(props) {
...rest
} = props;
const initialValues = {
- students: [],
+ name: \\"\\",
+ nmTest: \\"\\",
+ parentTable: undefined,
};
- const [students, setStudents] = React.useState(initialValues.students);
- const [studentsLoading, setStudentsLoading] = React.useState(false);
- const [studentsRecords, setStudentsRecords] = React.useState([]);
+ const [name, setName] = React.useState(initialValues.name);
+ const [nmTest, setNmTest] = React.useState(initialValues.nmTest);
+ const [parentTable, setParentTable] = React.useState(
+ initialValues.parentTable
+ );
+ const [parentTableLoading, setParentTableLoading] = React.useState(false);
+ const [parentTableRecords, setParentTableRecords] = React.useState([]);
const autocompleteLength = 10;
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
- const cleanValues = classRecord
- ? { ...initialValues, ...classRecord, students: linkedStudents }
+ const cleanValues = basicTableRecord
+ ? { ...initialValues, ...basicTableRecord, parentTable }
: initialValues;
- setStudents(cleanValues.students ?? []);
- setCurrentStudentsValue(undefined);
- setCurrentStudentsDisplayValue(\\"\\");
+ setName(cleanValues.name);
+ setNmTest(
+ typeof cleanValues.nmTest === \\"string\\" || cleanValues.nmTest === null
+ ? cleanValues.nmTest
+ : JSON.stringify(cleanValues.nmTest)
+ );
+ setParentTable(cleanValues.parentTable);
+ setCurrentParentTableValue(undefined);
+ setCurrentParentTableDisplayValue(\\"\\");
setErrors({});
};
- const [classRecord, setClassRecord] = React.useState(classModelProp);
- const [linkedStudents, setLinkedStudents] = React.useState([]);
- const canUnlinkStudents = false;
+ const [basicTableRecord, setBasicTableRecord] =
+ React.useState(basicTableModelProp);
React.useEffect(() => {
const queryData = async () => {
const record = idProp
? (
await API.graphql({
- query: getClass.replaceAll(\\"__typename\\", \\"\\"),
+ query: getBasicTable.replaceAll(\\"__typename\\", \\"\\"),
variables: { id: idProp },
})
- )?.data?.getClass
- : classModelProp;
- const linkedStudents = record
- ? (
- await API.graphql({
- query: studentClassesByClassId.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- classId: record.id,
- },
- })
- ).data.studentClassesByClassId.items.map((t) => t.student)
- : [];
- setLinkedStudents(linkedStudents);
- setClassRecord(record);
+ )?.data?.getBasicTable
+ : basicTableModelProp;
+ const parentTableRecord = record ? await record.parentTable : undefined;
+ setParentTable(parentTableRecord);
+ setBasicTableRecord(record);
};
queryData();
- }, [idProp, classModelProp]);
- React.useEffect(resetStateValues, [classRecord, linkedStudents]);
- const [currentStudentsDisplayValue, setCurrentStudentsDisplayValue] =
+ }, [idProp, basicTableModelProp]);
+ React.useEffect(resetStateValues, [basicTableRecord, parentTable]);
+ const [currentParentTableDisplayValue, setCurrentParentTableDisplayValue] =
React.useState(\\"\\");
- const [currentStudentsValue, setCurrentStudentsValue] =
+ const [currentParentTableValue, setCurrentParentTableValue] =
React.useState(undefined);
- const studentsRef = React.createRef();
+ const parentTableRef = React.createRef();
const getIDValue = {
- students: (r) => JSON.stringify({ id: r?.id }),
+ parentTable: (r) => JSON.stringify({ id: r?.id }),
};
- const studentsIdSet = new Set(
- Array.isArray(students)
- ? students.map((r) => getIDValue.students?.(r))
- : getIDValue.students?.(students)
+ const parentTableIdSet = new Set(
+ Array.isArray(parentTable)
+ ? parentTable.map((r) => getIDValue.parentTable?.(r))
+ : getIDValue.parentTable?.(parentTable)
);
const getDisplayValue = {
- students: (r) => r?.id,
+ parentTable: (r) => \`\${r?.name ? r?.name + \\" - \\" : \\"\\"}\${r?.id}\`,
};
const validations = {
- students: [],
+ name: [],
+ nmTest: [{ type: \\"JSON\\" }],
+ parentTable: [],
};
const runValidationTasks = async (
fieldName,
@@ -14151,35 +16161,37 @@ export default function ClassUpdateForm(props) {
setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
return validationResponse;
};
- const fetchStudentsRecords = async (value) => {
- setStudentsLoading(true);
+ const fetchParentTableRecords = async (value) => {
+ setParentTableLoading(true);
const newOptions = [];
let newNext = \\"\\";
while (newOptions.length < autocompleteLength && newNext != null) {
const variables = {
limit: autocompleteLength * 5,
- filter: { or: [{ id: { contains: value } }] },
+ filter: {
+ or: [{ name: { contains: value } }, { id: { contains: value } }],
+ },
};
if (newNext) {
variables[\\"nextToken\\"] = newNext;
}
const result = (
await API.graphql({
- query: listStudents.replaceAll(\\"__typename\\", \\"\\"),
+ query: listParentTables.replaceAll(\\"__typename\\", \\"\\"),
variables,
})
- )?.data?.listStudents?.items;
+ )?.data?.listParentTables?.items;
var loaded = result.filter(
- (item) => !studentsIdSet.has(getIDValue.students?.(item))
+ (item) => !parentTableIdSet.has(getIDValue.parentTable?.(item))
);
newOptions.push(...loaded);
newNext = result.nextToken;
}
- setStudentsRecords(newOptions.slice(0, autocompleteLength));
- setStudentsLoading(false);
+ setParentTableRecords(newOptions.slice(0, autocompleteLength));
+ setParentTableLoading(false);
};
React.useEffect(() => {
- fetchStudentsRecords(\\"\\");
+ fetchParentTableRecords(\\"\\");
}, []);
return (
{
event.preventDefault();
let modelFields = {
- students: students ?? null,
+ name: name ?? null,
+ nmTest: nmTest ?? null,
+ parentTable: parentTable ?? null,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
@@ -14228,191 +16242,167 @@ export default function ClassUpdateForm(props) {
modelFields[key] = null;
}
});
- const promises = [];
- const studentsToLinkMap = new Map();
- const studentsToUnLinkMap = new Map();
- const studentsMap = new Map();
- const linkedStudentsMap = new Map();
- students.forEach((r) => {
- const count = studentsMap.get(getIDValue.students?.(r));
- const newCount = count ? count + 1 : 1;
- studentsMap.set(getIDValue.students?.(r), newCount);
- });
- linkedStudents.forEach((r) => {
- const count = linkedStudentsMap.get(getIDValue.students?.(r));
- const newCount = count ? count + 1 : 1;
- linkedStudentsMap.set(getIDValue.students?.(r), newCount);
- });
- linkedStudentsMap.forEach((count, id) => {
- const newCount = studentsMap.get(id);
- if (newCount) {
- const diffCount = count - newCount;
- if (diffCount > 0) {
- studentsToUnLinkMap.set(id, diffCount);
- }
- } else {
- studentsToUnLinkMap.set(id, count);
- }
- });
- studentsMap.forEach((count, id) => {
- const originalCount = linkedStudentsMap.get(id);
- if (originalCount) {
- const diffCount = count - originalCount;
- if (diffCount > 0) {
- studentsToLinkMap.set(id, diffCount);
- }
- } else {
- studentsToLinkMap.set(id, count);
- }
- });
- studentsToUnLinkMap.forEach(async (count, id) => {
- const recordKeys = JSON.parse(id);
- const studentClassRecords = (
- await API.graphql({
- query: listStudentClasses.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- filter: {
- and: [
- { studentId: { eq: recordKeys.id } },
- { classId: { eq: classRecord.id } },
- ],
- },
- },
- })
- )?.data?.listStudentClasses?.items;
- for (let i = 0; i < count; i++) {
- promises.push(
- API.graphql({
- query: deleteStudentClass.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- input: {
- id: studentClassRecords[i].id,
- },
- },
- })
- );
- }
- });
- studentsToLinkMap.forEach((count, id) => {
- const studentToLink = studentRecords.find((r) =>
- Object.entries(JSON.parse(id)).every(
- ([key, value]) => r[key] === value
- )
- );
- for (let i = count; i > 0; i--) {
- promises.push(
- API.graphql({
- query: createStudentClass.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- input: {
- classId: classRecord.id,
- studentId: studentToLink.id,
- },
- },
- })
- );
- }
- });
- const modelFieldsToSave = {};
- promises.push(
- API.graphql({
- query: updateClass.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- input: {
- id: classRecord.id,
- ...modelFieldsToSave,
- },
+ const modelFieldsToSave = {
+ name: modelFields.name ?? null,
+ parentTableBasicTablesId: modelFields?.parentTable?.id ?? null,
+ nmTest: modelFields.nmTest
+ ? JSON.parse(modelFields.nmTest)
+ : modelFields.nmTest,
+ };
+ await API.graphql({
+ query: updateBasicTable.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: basicTableRecord.id,
+ ...modelFieldsToSave,
},
- })
- );
- await Promise.all(promises);
+ },
+ });
if (onSuccess) {
onSuccess(modelFields);
}
- } catch (err) {
- if (onError) {
- const messages = err.errors.map((e) => e.message).join(\\"\\\\n\\");
- onError(modelFields, messages);
+ } catch (err) {
+ if (onError) {
+ const messages = err.errors.map((e) => e.message).join(\\"\\\\n\\");
+ onError(modelFields, messages);
+ }
+ }
+ }}
+ {...getOverrideProps(overrides, \\"UpdateForm\\")}
+ {...rest}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ name: value,
+ nmTest,
+ parentTable,
+ };
+ const result = onChange(modelFields);
+ value = result?.name ?? value;
+ }
+ if (errors.name?.hasError) {
+ runValidationTasks(\\"name\\", value);
+ }
+ setName(value);
+ }}
+ onBlur={() => runValidationTasks(\\"name\\", name)}
+ errorMessage={errors.name?.errorMessage}
+ hasError={errors.name?.hasError}
+ {...getOverrideProps(overrides, \\"name\\")}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ name,
+ nmTest: value,
+ parentTable,
+ };
+ const result = onChange(modelFields);
+ value = result?.nmTest ?? value;
+ }
+ if (errors.nmTest?.hasError) {
+ runValidationTasks(\\"nmTest\\", value);
}
- }
- }}
- {...getOverrideProps(overrides, \\"ClassUpdateForm\\")}
- {...rest}
- >
+ setNmTest(value);
+ }}
+ onBlur={() => runValidationTasks(\\"nmTest\\", nmTest)}
+ errorMessage={errors.nmTest?.errorMessage}
+ hasError={errors.nmTest?.hasError}
+ {...getOverrideProps(overrides, \\"nmTest\\")}
+ >
{
- let values = items;
+ let value = items[0];
if (onChange) {
const modelFields = {
- students: values,
+ name,
+ nmTest,
+ parentTable: value,
};
const result = onChange(modelFields);
- values = result?.students ?? values;
+ value = result?.parentTable ?? value;
}
- setStudents(values);
- setCurrentStudentsValue(undefined);
- setCurrentStudentsDisplayValue(\\"\\");
+ setParentTable(value);
+ setCurrentParentTableValue(undefined);
+ setCurrentParentTableDisplayValue(\\"\\");
}}
- currentFieldValue={currentStudentsValue}
- label={\\"Students\\"}
- items={students}
- hasError={errors?.students?.hasError}
+ currentFieldValue={currentParentTableValue}
+ label={\\"Parent table\\"}
+ items={parentTable ? [parentTable] : []}
+ hasError={errors?.parentTable?.hasError}
runValidationTasks={async () =>
- await runValidationTasks(\\"students\\", currentStudentsValue)
+ await runValidationTasks(\\"parentTable\\", currentParentTableValue)
}
- errorMessage={errors?.students?.errorMessage}
- getBadgeText={getDisplayValue.students}
+ errorMessage={errors?.parentTable?.errorMessage}
+ getBadgeText={getDisplayValue.parentTable}
setFieldValue={(model) => {
- setCurrentStudentsDisplayValue(
- model ? getDisplayValue.students(model) : \\"\\"
+ setCurrentParentTableDisplayValue(
+ model ? getDisplayValue.parentTable(model) : \\"\\"
);
- setCurrentStudentsValue(model);
+ setCurrentParentTableValue(model);
}}
- inputFieldRef={studentsRef}
+ inputFieldRef={parentTableRef}
defaultFieldValue={\\"\\"}
>
({
- id: getIDValue.students?.(r),
- label: getDisplayValue.students?.(r),
- }))}
- isLoading={studentsLoading}
+ placeholder=\\"Search ParentTable\\"
+ value={currentParentTableDisplayValue}
+ options={parentTableRecords
+ .filter((r) => !parentTableIdSet.has(getIDValue.parentTable?.(r)))
+ .map((r) => ({
+ id: getIDValue.parentTable?.(r),
+ label: getDisplayValue.parentTable?.(r),
+ }))}
+ isLoading={parentTableLoading}
onSelect={({ id, label }) => {
- setCurrentStudentsValue(
- studentsRecords.find((r) =>
+ setCurrentParentTableValue(
+ parentTableRecords.find((r) =>
Object.entries(JSON.parse(id)).every(
([key, value]) => r[key] === value
)
)
);
- setCurrentStudentsDisplayValue(label);
- runValidationTasks(\\"students\\", label);
+ setCurrentParentTableDisplayValue(label);
+ runValidationTasks(\\"parentTable\\", label);
}}
onClear={() => {
- setCurrentStudentsDisplayValue(\\"\\");
+ setCurrentParentTableDisplayValue(\\"\\");
}}
+ defaultValue={parentTable}
onChange={(e) => {
let { value } = e.target;
- fetchStudentsRecords(value);
- if (errors.students?.hasError) {
- runValidationTasks(\\"students\\", value);
+ fetchParentTableRecords(value);
+ if (errors.parentTable?.hasError) {
+ runValidationTasks(\\"parentTable\\", value);
}
- setCurrentStudentsDisplayValue(value);
- setCurrentStudentsValue(undefined);
+ setCurrentParentTableDisplayValue(value);
+ setCurrentParentTableValue(undefined);
}}
onBlur={() =>
- runValidationTasks(\\"students\\", currentStudentsDisplayValue)
+ runValidationTasks(\\"parentTable\\", currentParentTableDisplayValue)
}
- errorMessage={errors.students?.errorMessage}
- hasError={errors.students?.hasError}
- ref={studentsRef}
+ errorMessage={errors.parentTable?.errorMessage}
+ hasError={errors.parentTable?.hasError}
+ ref={parentTableRef}
labelHidden={true}
- {...getOverrideProps(overrides, \\"students\\")}
+ {...getOverrideProps(overrides, \\"parentTable\\")}
>
e?.hasError)
}
{...getOverrideProps(overrides, \\"SubmitButton\\")}
@@ -14451,43 +16441,49 @@ export default function ClassUpdateForm(props) {
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with many to many relationship 2`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an update form with nonModel field 2`] = `
"import * as React from \\"react\\";
-import { AutocompleteProps, GridProps } from \\"@aws-amplify/ui-react\\";
+import { AutocompleteProps, GridProps, TextAreaFieldProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
-import { Class, Student } from \\"../API\\";
+import { BasicTable, ParentTable } from \\"../API\\";
export declare type ValidationResponse = {
hasError: boolean;
errorMessage?: string;
};
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
-export declare type ClassUpdateFormInputValues = {
- students?: Student[];
+export declare type UpdateFormInputValues = {
+ name?: string;
+ nmTest?: string;
+ parentTable?: ParentTable;
};
-export declare type ClassUpdateFormValidationValues = {
- students?: ValidationFunction;
+export declare type UpdateFormValidationValues = {
+ name?: ValidationFunction;
+ nmTest?: ValidationFunction;
+ parentTable?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
-export declare type ClassUpdateFormOverridesProps = {
- ClassUpdateFormGrid?: PrimitiveOverrideProps;
- students?: PrimitiveOverrideProps;
+export declare type UpdateFormOverridesProps = {
+ UpdateFormGrid?: PrimitiveOverrideProps;
+ name?: PrimitiveOverrideProps;
+ nmTest?: PrimitiveOverrideProps;
+ parentTable?: PrimitiveOverrideProps;
} & EscapeHatchProps;
-export declare type ClassUpdateFormProps = React.PropsWithChildren<{
- overrides?: ClassUpdateFormOverridesProps | undefined | null;
+export declare type UpdateFormProps = React.PropsWithChildren<{
+ overrides?: UpdateFormOverridesProps | undefined | null;
} & {
id?: string;
- class?: Class;
- onSubmit?: (fields: ClassUpdateFormInputValues) => ClassUpdateFormInputValues;
- onSuccess?: (fields: ClassUpdateFormInputValues) => void;
- onError?: (fields: ClassUpdateFormInputValues, errorMessage: string) => void;
- onChange?: (fields: ClassUpdateFormInputValues) => ClassUpdateFormInputValues;
- onValidate?: ClassUpdateFormValidationValues;
+ basicTable?: BasicTable;
+ onSubmit?: (fields: UpdateFormInputValues) => UpdateFormInputValues;
+ onSuccess?: (fields: UpdateFormInputValues) => void;
+ onError?: (fields: UpdateFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: UpdateFormInputValues) => UpdateFormInputValues;
+ onValidate?: UpdateFormValidationValues;
} & React.CSSProperties>;
-export default function ClassUpdateForm(props: ClassUpdateFormProps): React.ReactElement;
+export default function UpdateForm(props: UpdateFormProps): React.ReactElement;
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with nonModel field 1`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an upgrade form with multiple relationship & cpk - amplify js v6 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
import {
@@ -14500,15 +16496,27 @@ import {
Icon,
ScrollView,
Text,
- TextAreaField,
TextField,
useTheme,
} from \\"@aws-amplify/ui-react\\";
import { getOverrideProps } from \\"@aws-amplify/ui-react/internal\\";
import { fetchByPath, validateField } from \\"./utils\\";
-import { API } from \\"aws-amplify\\";
-import { getBasicTable, listParentTables } from \\"../graphql/queries\\";
-import { updateBasicTable } from \\"../graphql/mutations\\";
+import {
+ cPKTeacherCPKClassesByCPKTeacherSpecialTeacherId,
+ getCPKTeacher,
+ listCPKClasses,
+ listCPKProjects,
+ listCPKStudents,
+ listCPKTeacherCPKClasses,
+} from \\"../graphql/queries\\";
+import { generateClient } from \\"aws-amplify/api\\";
+import {
+ createCPKTeacherCPKClass,
+ deleteCPKTeacherCPKClass,
+ updateCPKProject,
+ updateCPKTeacher,
+} from \\"../graphql/mutations\\";
+const client = generateClient();
function ArrayField({
items = [],
onChange,
@@ -14664,10 +16672,10 @@ function ArrayField({
);
}
-export default function UpdateForm(props) {
+export default function UpdateCPKTeacherForm(props) {
const {
- id: idProp,
- basicTable: basicTableModelProp,
+ specialTeacherId: specialTeacherIdProp,
+ cPKTeacher: cPKTeacherModelProp,
onSuccess,
onError,
onSubmit,
@@ -14677,73 +16685,143 @@ export default function UpdateForm(props) {
...rest
} = props;
const initialValues = {
- name: \\"\\",
- nmTest: \\"\\",
- parentTable: undefined,
+ specialTeacherId: \\"\\",
+ CPKStudent: undefined,
+ CPKClasses: [],
+ CPKProjects: [],
};
- const [name, setName] = React.useState(initialValues.name);
- const [nmTest, setNmTest] = React.useState(initialValues.nmTest);
- const [parentTable, setParentTable] = React.useState(
- initialValues.parentTable
+ const [specialTeacherId, setSpecialTeacherId] = React.useState(
+ initialValues.specialTeacherId
);
- const [parentTableLoading, setParentTableLoading] = React.useState(false);
- const [parentTableRecords, setParentTableRecords] = React.useState([]);
+ const [CPKStudent, setCPKStudent] = React.useState(initialValues.CPKStudent);
+ const [CPKStudentLoading, setCPKStudentLoading] = React.useState(false);
+ const [CPKStudentRecords, setCPKStudentRecords] = React.useState([]);
+ const [CPKClasses, setCPKClasses] = React.useState(initialValues.CPKClasses);
+ const [CPKClassesLoading, setCPKClassesLoading] = React.useState(false);
+ const [CPKClassesRecords, setCPKClassesRecords] = React.useState([]);
+ const [CPKProjects, setCPKProjects] = React.useState(
+ initialValues.CPKProjects
+ );
+ const [CPKProjectsLoading, setCPKProjectsLoading] = React.useState(false);
+ const [CPKProjectsRecords, setCPKProjectsRecords] = React.useState([]);
const autocompleteLength = 10;
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
- const cleanValues = basicTableRecord
- ? { ...initialValues, ...basicTableRecord, parentTable }
+ const cleanValues = cPKTeacherRecord
+ ? {
+ ...initialValues,
+ ...cPKTeacherRecord,
+ CPKStudent,
+ CPKClasses: linkedCPKClasses,
+ CPKProjects: linkedCPKProjects,
+ }
: initialValues;
- setName(cleanValues.name);
- setNmTest(
- typeof cleanValues.nmTest === \\"string\\" || cleanValues.nmTest === null
- ? cleanValues.nmTest
- : JSON.stringify(cleanValues.nmTest)
- );
- setParentTable(cleanValues.parentTable);
- setCurrentParentTableValue(undefined);
- setCurrentParentTableDisplayValue(\\"\\");
+ setSpecialTeacherId(cleanValues.specialTeacherId);
+ setCPKStudent(cleanValues.CPKStudent);
+ setCurrentCPKStudentValue(undefined);
+ setCurrentCPKStudentDisplayValue(\\"\\");
+ setCPKClasses(cleanValues.CPKClasses ?? []);
+ setCurrentCPKClassesValue(undefined);
+ setCurrentCPKClassesDisplayValue(\\"\\");
+ setCPKProjects(cleanValues.CPKProjects ?? []);
+ setCurrentCPKProjectsValue(undefined);
+ setCurrentCPKProjectsDisplayValue(\\"\\");
setErrors({});
};
- const [basicTableRecord, setBasicTableRecord] =
- React.useState(basicTableModelProp);
+ const [cPKTeacherRecord, setCPKTeacherRecord] =
+ React.useState(cPKTeacherModelProp);
+ const [linkedCPKClasses, setLinkedCPKClasses] = React.useState([]);
+ const canUnlinkCPKClasses = false;
+ const [linkedCPKProjects, setLinkedCPKProjects] = React.useState([]);
+ const canUnlinkCPKProjects = true;
React.useEffect(() => {
const queryData = async () => {
- const record = idProp
+ const record = specialTeacherIdProp
? (
- await API.graphql({
- query: getBasicTable.replaceAll(\\"__typename\\", \\"\\"),
- variables: { id: idProp },
+ await client.graphql({
+ query: getCPKTeacher.replaceAll(\\"__typename\\", \\"\\"),
+ variables: { specialTeacherId: specialTeacherIdProp },
})
- )?.data?.getBasicTable
- : basicTableModelProp;
- const parentTableRecord = record ? await record.parentTable : undefined;
- setParentTable(parentTableRecord);
- setBasicTableRecord(record);
+ )?.data?.getCPKTeacher
+ : cPKTeacherModelProp;
+ const CPKStudentRecord = record ? await record.CPKStudent : undefined;
+ setCPKStudent(CPKStudentRecord);
+ const linkedCPKClasses = record
+ ? (
+ await client.graphql({
+ query:
+ cPKTeacherCPKClassesByCPKTeacherSpecialTeacherId.replaceAll(
+ \\"__typename\\",
+ \\"\\"
+ ),
+ variables: {
+ cPKTeacherSpecialTeacherId: record.specialTeacherId,
+ },
+ })
+ ).data.cPKTeacherCPKClassesByCPKTeacherSpecialTeacherId.items.map(
+ (t) => t.cpkClass
+ )
+ : [];
+ setLinkedCPKClasses(linkedCPKClasses);
+ const linkedCPKProjects = record?.CPKProjects?.items ?? [];
+ setLinkedCPKProjects(linkedCPKProjects);
+ setCPKTeacherRecord(record);
};
queryData();
- }, [idProp, basicTableModelProp]);
- React.useEffect(resetStateValues, [basicTableRecord, parentTable]);
- const [currentParentTableDisplayValue, setCurrentParentTableDisplayValue] =
+ }, [specialTeacherIdProp, cPKTeacherModelProp]);
+ React.useEffect(resetStateValues, [
+ cPKTeacherRecord,
+ CPKStudent,
+ linkedCPKClasses,
+ linkedCPKProjects,
+ ]);
+ const [currentCPKStudentDisplayValue, setCurrentCPKStudentDisplayValue] =
React.useState(\\"\\");
- const [currentParentTableValue, setCurrentParentTableValue] =
+ const [currentCPKStudentValue, setCurrentCPKStudentValue] =
React.useState(undefined);
- const parentTableRef = React.createRef();
+ const CPKStudentRef = React.createRef();
+ const [currentCPKClassesDisplayValue, setCurrentCPKClassesDisplayValue] =
+ React.useState(\\"\\");
+ 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 getIDValue = {
- parentTable: (r) => JSON.stringify({ id: r?.id }),
+ CPKStudent: (r) =>
+ JSON.stringify({ specialStudentId: r?.specialStudentId }),
+ CPKClasses: (r) => JSON.stringify({ specialClassId: r?.specialClassId }),
+ CPKProjects: (r) =>
+ JSON.stringify({ specialProjectId: r?.specialProjectId }),
};
- const parentTableIdSet = new Set(
- Array.isArray(parentTable)
- ? parentTable.map((r) => getIDValue.parentTable?.(r))
- : getIDValue.parentTable?.(parentTable)
+ const CPKStudentIdSet = new Set(
+ Array.isArray(CPKStudent)
+ ? CPKStudent.map((r) => getIDValue.CPKStudent?.(r))
+ : getIDValue.CPKStudent?.(CPKStudent)
+ );
+ const CPKClassesIdSet = new Set(
+ Array.isArray(CPKClasses)
+ ? CPKClasses.map((r) => getIDValue.CPKClasses?.(r))
+ : getIDValue.CPKClasses?.(CPKClasses)
+ );
+ const CPKProjectsIdSet = new Set(
+ Array.isArray(CPKProjects)
+ ? CPKProjects.map((r) => getIDValue.CPKProjects?.(r))
+ : getIDValue.CPKProjects?.(CPKProjects)
);
const getDisplayValue = {
- parentTable: (r) => \`\${r?.name ? r?.name + \\" - \\" : \\"\\"}\${r?.id}\`,
+ CPKStudent: (r) => r?.specialStudentId,
+ CPKClasses: (r) => r?.specialClassId,
+ CPKProjects: (r) => r?.specialProjectId,
};
const validations = {
- name: [],
- nmTest: [{ type: \\"JSON\\" }],
- parentTable: [],
+ specialTeacherId: [{ type: \\"Required\\" }],
+ CPKStudent: [],
+ CPKClasses: [],
+ CPKProjects: [],
};
const runValidationTasks = async (
fieldName,
@@ -14762,37 +16840,91 @@ export default function UpdateForm(props) {
setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
return validationResponse;
};
- const fetchParentTableRecords = async (value) => {
- setParentTableLoading(true);
+ const fetchCPKStudentRecords = async (value) => {
+ setCPKStudentLoading(true);
const newOptions = [];
let newNext = \\"\\";
while (newOptions.length < autocompleteLength && newNext != null) {
const variables = {
limit: autocompleteLength * 5,
- filter: {
- or: [{ name: { contains: value } }, { id: { contains: value } }],
- },
+ filter: { or: [{ specialStudentId: { contains: value } }] },
};
if (newNext) {
variables[\\"nextToken\\"] = newNext;
}
const result = (
- await API.graphql({
- query: listParentTables.replaceAll(\\"__typename\\", \\"\\"),
+ await client.graphql({
+ query: listCPKStudents.replaceAll(\\"__typename\\", \\"\\"),
variables,
})
- )?.data?.listParentTables?.items;
+ )?.data?.listCPKStudents?.items;
var loaded = result.filter(
- (item) => !parentTableIdSet.has(getIDValue.parentTable?.(item))
+ (item) => !CPKStudentIdSet.has(getIDValue.CPKStudent?.(item))
);
newOptions.push(...loaded);
newNext = result.nextToken;
}
- setParentTableRecords(newOptions.slice(0, autocompleteLength));
- setParentTableLoading(false);
+ setCPKStudentRecords(newOptions.slice(0, autocompleteLength));
+ setCPKStudentLoading(false);
+ };
+ const fetchCPKClassesRecords = async (value) => {
+ setCPKClassesLoading(true);
+ const newOptions = [];
+ let newNext = \\"\\";
+ while (newOptions.length < autocompleteLength && newNext != null) {
+ const variables = {
+ limit: autocompleteLength * 5,
+ filter: { or: [{ specialClassId: { contains: value } }] },
+ };
+ if (newNext) {
+ variables[\\"nextToken\\"] = newNext;
+ }
+ const result = (
+ await client.graphql({
+ query: listCPKClasses.replaceAll(\\"__typename\\", \\"\\"),
+ variables,
+ })
+ )?.data?.listCPKClasses?.items;
+ var loaded = result.filter(
+ (item) => !CPKClassesIdSet.has(getIDValue.CPKClasses?.(item))
+ );
+ newOptions.push(...loaded);
+ newNext = result.nextToken;
+ }
+ setCPKClassesRecords(newOptions.slice(0, autocompleteLength));
+ setCPKClassesLoading(false);
+ };
+ const fetchCPKProjectsRecords = async (value) => {
+ setCPKProjectsLoading(true);
+ const newOptions = [];
+ let newNext = \\"\\";
+ while (newOptions.length < autocompleteLength && newNext != null) {
+ const variables = {
+ limit: autocompleteLength * 5,
+ filter: { or: [{ specialProjectId: { contains: value } }] },
+ };
+ if (newNext) {
+ variables[\\"nextToken\\"] = newNext;
+ }
+ const result = (
+ await client.graphql({
+ query: listCPKProjects.replaceAll(\\"__typename\\", \\"\\"),
+ variables,
+ })
+ )?.data?.listCPKProjects?.items;
+ var loaded = result.filter(
+ (item) => !CPKProjectsIdSet.has(getIDValue.CPKProjects?.(item))
+ );
+ newOptions.push(...loaded);
+ newNext = result.nextToken;
+ }
+ setCPKProjectsRecords(newOptions.slice(0, autocompleteLength));
+ setCPKProjectsLoading(false);
};
React.useEffect(() => {
- fetchParentTableRecords(\\"\\");
+ fetchCPKStudentRecords(\\"\\");
+ fetchCPKClassesRecords(\\"\\");
+ fetchCPKProjectsRecords(\\"\\");
}, []);
return (
{
event.preventDefault();
let modelFields = {
- name: name ?? null,
- nmTest: nmTest ?? null,
- parentTable: parentTable ?? null,
+ specialTeacherId,
+ CPKStudent: CPKStudent ?? null,
+ CPKClasses: CPKClasses ?? null,
+ CPKProjects: CPKProjects ?? null,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
if (Array.isArray(modelFields[fieldName])) {
promises.push(
- ...modelFields[fieldName].map((item) =>
- runValidationTasks(
- fieldName,
- item,
- getDisplayValue[fieldName]
- )
- )
+ ...modelFields[fieldName].map((item) =>
+ runValidationTasks(
+ fieldName,
+ item,
+ getDisplayValue[fieldName]
+ )
+ )
+ );
+ return promises;
+ }
+ promises.push(
+ runValidationTasks(
+ fieldName,
+ modelFields[fieldName],
+ getDisplayValue[fieldName]
+ )
+ );
+ return promises;
+ }, [])
+ );
+ if (validationResponses.some((r) => r.hasError)) {
+ return;
+ }
+ if (onSubmit) {
+ modelFields = onSubmit(modelFields);
+ }
+ try {
+ Object.entries(modelFields).forEach(([key, value]) => {
+ if (typeof value === \\"string\\" && value === \\"\\") {
+ modelFields[key] = null;
+ }
+ });
+ const promises = [];
+ const cPKClassesToLinkMap = new Map();
+ const cPKClassesToUnLinkMap = new Map();
+ const cPKClassesMap = new Map();
+ const linkedCPKClassesMap = new Map();
+ CPKClasses.forEach((r) => {
+ const count = cPKClassesMap.get(getIDValue.CPKClasses?.(r));
+ const newCount = count ? count + 1 : 1;
+ cPKClassesMap.set(getIDValue.CPKClasses?.(r), newCount);
+ });
+ linkedCPKClasses.forEach((r) => {
+ const count = linkedCPKClassesMap.get(getIDValue.CPKClasses?.(r));
+ const newCount = count ? count + 1 : 1;
+ linkedCPKClassesMap.set(getIDValue.CPKClasses?.(r), newCount);
+ });
+ linkedCPKClassesMap.forEach((count, id) => {
+ const newCount = cPKClassesMap.get(id);
+ if (newCount) {
+ const diffCount = count - newCount;
+ if (diffCount > 0) {
+ cPKClassesToUnLinkMap.set(id, diffCount);
+ }
+ } else {
+ cPKClassesToUnLinkMap.set(id, count);
+ }
+ });
+ cPKClassesMap.forEach((count, id) => {
+ const originalCount = linkedCPKClassesMap.get(id);
+ if (originalCount) {
+ const diffCount = count - originalCount;
+ if (diffCount > 0) {
+ cPKClassesToLinkMap.set(id, diffCount);
+ }
+ } else {
+ cPKClassesToLinkMap.set(id, count);
+ }
+ });
+ cPKClassesToUnLinkMap.forEach(async (count, id) => {
+ const recordKeys = JSON.parse(id);
+ const cPKTeacherCPKClassRecords = (
+ await client.graphql({
+ query: listCPKTeacherCPKClasses.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ filter: {
+ and: [
+ {
+ cPKClassSpecialClassId: {
+ eq: recordKeys.specialClassId,
+ },
+ },
+ {
+ cPKTeacherSpecialTeacherId: {
+ eq: cPKTeacherRecord.specialTeacherId,
+ },
+ },
+ ],
+ },
+ },
+ })
+ )?.data?.listCPKTeacherCPKClasses?.items;
+ for (let i = 0; i < count; i++) {
+ promises.push(
+ client.graphql({
+ query: deleteCPKTeacherCPKClass.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ id: cPKTeacherCPKClassRecords[i].id,
+ },
+ },
+ })
);
- return promises;
}
- promises.push(
- runValidationTasks(
- fieldName,
- modelFields[fieldName],
- getDisplayValue[fieldName]
+ });
+ cPKClassesToLinkMap.forEach((count, id) => {
+ const cPKClassToLink = cPKClassRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
)
);
- return promises;
- }, [])
- );
- if (validationResponses.some((r) => r.hasError)) {
- return;
- }
- if (onSubmit) {
- modelFields = onSubmit(modelFields);
- }
- try {
- Object.entries(modelFields).forEach(([key, value]) => {
- if (typeof value === \\"string\\" && value === \\"\\") {
- modelFields[key] = null;
+ for (let i = count; i > 0; i--) {
+ promises.push(
+ client.graphql({
+ query: createCPKTeacherCPKClass.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ cPKTeacherSpecialTeacherId:
+ cPKTeacherRecord.specialTeacherId,
+ cPKClassSpecialClassId: cPKClassToLink.specialClassId,
+ },
+ },
+ })
+ );
+ }
+ });
+ const cPKProjectsToLink = [];
+ const cPKProjectsToUnLink = [];
+ const cPKProjectsSet = new Set();
+ const linkedCPKProjectsSet = new Set();
+ CPKProjects.forEach((r) =>
+ cPKProjectsSet.add(getIDValue.CPKProjects?.(r))
+ );
+ linkedCPKProjects.forEach((r) =>
+ linkedCPKProjectsSet.add(getIDValue.CPKProjects?.(r))
+ );
+ linkedCPKProjects.forEach((r) => {
+ if (!cPKProjectsSet.has(getIDValue.CPKProjects?.(r))) {
+ cPKProjectsToUnLink.push(r);
+ }
+ });
+ CPKProjects.forEach((r) => {
+ if (!linkedCPKProjectsSet.has(getIDValue.CPKProjects?.(r))) {
+ cPKProjectsToLink.push(r);
+ }
+ });
+ cPKProjectsToUnLink.forEach((original) => {
+ if (!canUnlinkCPKProjects) {
+ throw Error(
+ \`CPKProject \${original.specialProjectId} cannot be unlinked from CPKTeacher because cPKTeacherID is a required field.\`
+ );
}
+ promises.push(
+ client.graphql({
+ query: updateCPKProject.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ specialProjectId: original.specialProjectId,
+ cPKTeacherID: null,
+ },
+ },
+ })
+ );
+ });
+ cPKProjectsToLink.forEach((original) => {
+ promises.push(
+ client.graphql({
+ query: updateCPKProject.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ specialProjectId: original.specialProjectId,
+ cPKTeacherID: cPKTeacherRecord.specialTeacherId,
+ },
+ },
+ })
+ );
});
const modelFieldsToSave = {
- name: modelFields.name ?? null,
- parentTableBasicTablesId: modelFields?.parentTable?.id ?? null,
- nmTest: modelFields.nmTest
- ? JSON.parse(modelFields.nmTest)
- : modelFields.nmTest,
+ specialTeacherId: modelFields.specialTeacherId,
+ cPKTeacherCPKStudentSpecialStudentId:
+ modelFields?.CPKStudent?.specialStudentId ?? null,
};
- await API.graphql({
- query: updateBasicTable.replaceAll(\\"__typename\\", \\"\\"),
- variables: {
- input: {
- id: basicTableRecord.id,
- ...modelFieldsToSave,
+ promises.push(
+ client.graphql({
+ query: updateCPKTeacher.replaceAll(\\"__typename\\", \\"\\"),
+ variables: {
+ input: {
+ specialTeacherId: cPKTeacherRecord.specialTeacherId,
+ ...modelFieldsToSave,
+ },
},
- },
- });
+ })
+ );
+ await Promise.all(promises);
if (onSuccess) {
onSuccess(modelFields);
}
@@ -14869,141 +17148,277 @@ export default function UpdateForm(props) {
}
}
}}
- {...getOverrideProps(overrides, \\"UpdateForm\\")}
+ {...getOverrideProps(overrides, \\"UpdateCPKTeacherForm\\")}
{...rest}
>
{
let { value } = e.target;
if (onChange) {
const modelFields = {
- name: value,
- nmTest,
- parentTable,
+ specialTeacherId: value,
+ CPKStudent,
+ CPKClasses,
+ CPKProjects,
};
const result = onChange(modelFields);
- value = result?.name ?? value;
+ value = result?.specialTeacherId ?? value;
}
- if (errors.name?.hasError) {
- runValidationTasks(\\"name\\", value);
+ if (errors.specialTeacherId?.hasError) {
+ runValidationTasks(\\"specialTeacherId\\", value);
+ }
+ setSpecialTeacherId(value);
+ }}
+ onBlur={() => runValidationTasks(\\"specialTeacherId\\", specialTeacherId)}
+ errorMessage={errors.specialTeacherId?.errorMessage}
+ hasError={errors.specialTeacherId?.hasError}
+ {...getOverrideProps(overrides, \\"specialTeacherId\\")}
+ >
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ specialTeacherId,
+ CPKStudent: value,
+ CPKClasses,
+ CPKProjects,
+ };
+ const result = onChange(modelFields);
+ value = result?.CPKStudent ?? value;
+ }
+ setCPKStudent(value);
+ setCurrentCPKStudentValue(undefined);
+ setCurrentCPKStudentDisplayValue(\\"\\");
+ }}
+ currentFieldValue={currentCPKStudentValue}
+ label={\\"Cpk student\\"}
+ items={CPKStudent ? [CPKStudent] : []}
+ hasError={errors?.CPKStudent?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks(\\"CPKStudent\\", currentCPKStudentValue)
+ }
+ errorMessage={errors?.CPKStudent?.errorMessage}
+ getBadgeText={getDisplayValue.CPKStudent}
+ setFieldValue={(model) => {
+ setCurrentCPKStudentDisplayValue(
+ model ? getDisplayValue.CPKStudent(model) : \\"\\"
+ );
+ setCurrentCPKStudentValue(model);
+ }}
+ inputFieldRef={CPKStudentRef}
+ defaultFieldValue={\\"\\"}
+ >
+ !CPKStudentIdSet.has(getIDValue.CPKStudent?.(r))
+ ).map((r) => ({
+ id: getIDValue.CPKStudent?.(r),
+ label: getDisplayValue.CPKStudent?.(r),
+ }))}
+ isLoading={CPKStudentLoading}
+ onSelect={({ id, label }) => {
+ setCurrentCPKStudentValue(
+ CPKStudentRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
+ )
+ );
+ setCurrentCPKStudentDisplayValue(label);
+ runValidationTasks(\\"CPKStudent\\", label);
+ }}
+ onClear={() => {
+ setCurrentCPKStudentDisplayValue(\\"\\");
+ }}
+ defaultValue={CPKStudent}
+ onChange={(e) => {
+ let { value } = e.target;
+ fetchCPKStudentRecords(value);
+ if (errors.CPKStudent?.hasError) {
+ runValidationTasks(\\"CPKStudent\\", value);
+ }
+ setCurrentCPKStudentDisplayValue(value);
+ setCurrentCPKStudentValue(undefined);
+ }}
+ onBlur={() =>
+ runValidationTasks(\\"CPKStudent\\", currentCPKStudentDisplayValue)
}
- setName(value);
- }}
- onBlur={() => runValidationTasks(\\"name\\", name)}
- errorMessage={errors.name?.errorMessage}
- hasError={errors.name?.hasError}
- {...getOverrideProps(overrides, \\"name\\")}
- >
- {
- let { value } = e.target;
+ errorMessage={errors.CPKStudent?.errorMessage}
+ hasError={errors.CPKStudent?.hasError}
+ ref={CPKStudentRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"CPKStudent\\")}
+ >
+
+ {
+ let values = items;
if (onChange) {
const modelFields = {
- name,
- nmTest: value,
- parentTable,
+ specialTeacherId,
+ CPKStudent,
+ CPKClasses: values,
+ CPKProjects,
};
const result = onChange(modelFields);
- value = result?.nmTest ?? value;
- }
- if (errors.nmTest?.hasError) {
- runValidationTasks(\\"nmTest\\", value);
+ values = result?.CPKClasses ?? values;
}
- setNmTest(value);
+ setCPKClasses(values);
+ setCurrentCPKClassesValue(undefined);
+ setCurrentCPKClassesDisplayValue(\\"\\");
}}
- onBlur={() => runValidationTasks(\\"nmTest\\", nmTest)}
- errorMessage={errors.nmTest?.errorMessage}
- hasError={errors.nmTest?.hasError}
- {...getOverrideProps(overrides, \\"nmTest\\")}
- >
+ currentFieldValue={currentCPKClassesValue}
+ label={\\"Cpk classes\\"}
+ items={CPKClasses}
+ hasError={errors?.CPKClasses?.hasError}
+ runValidationTasks={async () =>
+ await runValidationTasks(\\"CPKClasses\\", currentCPKClassesValue)
+ }
+ errorMessage={errors?.CPKClasses?.errorMessage}
+ getBadgeText={getDisplayValue.CPKClasses}
+ setFieldValue={(model) => {
+ setCurrentCPKClassesDisplayValue(
+ model ? getDisplayValue.CPKClasses(model) : \\"\\"
+ );
+ setCurrentCPKClassesValue(model);
+ }}
+ inputFieldRef={CPKClassesRef}
+ defaultFieldValue={\\"\\"}
+ >
+ ({
+ id: getIDValue.CPKClasses?.(r),
+ label: getDisplayValue.CPKClasses?.(r),
+ }))}
+ isLoading={CPKClassesLoading}
+ onSelect={({ id, label }) => {
+ setCurrentCPKClassesValue(
+ CPKClassesRecords.find((r) =>
+ Object.entries(JSON.parse(id)).every(
+ ([key, value]) => r[key] === value
+ )
+ )
+ );
+ setCurrentCPKClassesDisplayValue(label);
+ runValidationTasks(\\"CPKClasses\\", label);
+ }}
+ onClear={() => {
+ setCurrentCPKClassesDisplayValue(\\"\\");
+ }}
+ onChange={(e) => {
+ let { value } = e.target;
+ fetchCPKClassesRecords(value);
+ if (errors.CPKClasses?.hasError) {
+ runValidationTasks(\\"CPKClasses\\", value);
+ }
+ setCurrentCPKClassesDisplayValue(value);
+ setCurrentCPKClassesValue(undefined);
+ }}
+ onBlur={() =>
+ runValidationTasks(\\"CPKClasses\\", currentCPKClassesDisplayValue)
+ }
+ errorMessage={errors.CPKClasses?.errorMessage}
+ hasError={errors.CPKClasses?.hasError}
+ ref={CPKClassesRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"CPKClasses\\")}
+ >
+
{
- let value = items[0];
+ let values = items;
if (onChange) {
const modelFields = {
- name,
- nmTest,
- parentTable: value,
+ specialTeacherId,
+ CPKStudent,
+ CPKClasses,
+ CPKProjects: values,
};
const result = onChange(modelFields);
- value = result?.parentTable ?? value;
+ values = result?.CPKProjects ?? values;
}
- setParentTable(value);
- setCurrentParentTableValue(undefined);
- setCurrentParentTableDisplayValue(\\"\\");
+ setCPKProjects(values);
+ setCurrentCPKProjectsValue(undefined);
+ setCurrentCPKProjectsDisplayValue(\\"\\");
}}
- currentFieldValue={currentParentTableValue}
- label={\\"Parent table\\"}
- items={parentTable ? [parentTable] : []}
- hasError={errors?.parentTable?.hasError}
+ currentFieldValue={currentCPKProjectsValue}
+ label={\\"Cpk projects\\"}
+ items={CPKProjects}
+ hasError={errors?.CPKProjects?.hasError}
runValidationTasks={async () =>
- await runValidationTasks(\\"parentTable\\", currentParentTableValue)
+ await runValidationTasks(\\"CPKProjects\\", currentCPKProjectsValue)
}
- errorMessage={errors?.parentTable?.errorMessage}
- getBadgeText={getDisplayValue.parentTable}
+ errorMessage={errors?.CPKProjects?.errorMessage}
+ getBadgeText={getDisplayValue.CPKProjects}
setFieldValue={(model) => {
- setCurrentParentTableDisplayValue(
- model ? getDisplayValue.parentTable(model) : \\"\\"
+ setCurrentCPKProjectsDisplayValue(
+ model ? getDisplayValue.CPKProjects(model) : \\"\\"
);
- setCurrentParentTableValue(model);
+ setCurrentCPKProjectsValue(model);
}}
- inputFieldRef={parentTableRef}
+ inputFieldRef={CPKProjectsRef}
defaultFieldValue={\\"\\"}
>
!parentTableIdSet.has(getIDValue.parentTable?.(r)))
- .map((r) => ({
- id: getIDValue.parentTable?.(r),
- label: getDisplayValue.parentTable?.(r),
- }))}
- isLoading={parentTableLoading}
+ placeholder=\\"Search CPKProject\\"
+ value={currentCPKProjectsDisplayValue}
+ options={CPKProjectsRecords.filter(
+ (r) => !CPKProjectsIdSet.has(getIDValue.CPKProjects?.(r))
+ ).map((r) => ({
+ id: getIDValue.CPKProjects?.(r),
+ label: getDisplayValue.CPKProjects?.(r),
+ }))}
+ isLoading={CPKProjectsLoading}
onSelect={({ id, label }) => {
- setCurrentParentTableValue(
- parentTableRecords.find((r) =>
+ setCurrentCPKProjectsValue(
+ CPKProjectsRecords.find((r) =>
Object.entries(JSON.parse(id)).every(
([key, value]) => r[key] === value
)
)
);
- setCurrentParentTableDisplayValue(label);
- runValidationTasks(\\"parentTable\\", label);
+ setCurrentCPKProjectsDisplayValue(label);
+ runValidationTasks(\\"CPKProjects\\", label);
}}
onClear={() => {
- setCurrentParentTableDisplayValue(\\"\\");
+ setCurrentCPKProjectsDisplayValue(\\"\\");
}}
- defaultValue={parentTable}
onChange={(e) => {
let { value } = e.target;
- fetchParentTableRecords(value);
- if (errors.parentTable?.hasError) {
- runValidationTasks(\\"parentTable\\", value);
+ fetchCPKProjectsRecords(value);
+ if (errors.CPKProjects?.hasError) {
+ runValidationTasks(\\"CPKProjects\\", value);
}
- setCurrentParentTableDisplayValue(value);
- setCurrentParentTableValue(undefined);
+ setCurrentCPKProjectsDisplayValue(value);
+ setCurrentCPKProjectsValue(undefined);
}}
onBlur={() =>
- runValidationTasks(\\"parentTable\\", currentParentTableDisplayValue)
+ runValidationTasks(\\"CPKProjects\\", currentCPKProjectsDisplayValue)
}
- errorMessage={errors.parentTable?.errorMessage}
- hasError={errors.parentTable?.hasError}
- ref={parentTableRef}
+ errorMessage={errors.CPKProjects?.errorMessage}
+ hasError={errors.CPKProjects?.hasError}
+ ref={CPKProjectsRef}
labelHidden={true}
- {...getOverrideProps(overrides, \\"parentTable\\")}
+ {...getOverrideProps(overrides, \\"CPKProjects\\")}
>
e?.hasError)
}
{...getOverrideProps(overrides, \\"SubmitButton\\")}
@@ -15042,45 +17457,48 @@ export default function UpdateForm(props) {
"
`;
-exports[`amplify form renderer tests GraphQL form tests should generate an update form with nonModel field 2`] = `
+exports[`amplify form renderer tests GraphQL form tests should generate an upgrade form with multiple relationship & cpk - amplify js v6 2`] = `
"import * as React from \\"react\\";
-import { AutocompleteProps, GridProps, TextAreaFieldProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
+import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
-import { BasicTable, ParentTable } from \\"../API\\";
+import { CPKClass, CPKProject, CPKStudent, CPKTeacher } from \\"../API\\";
export declare type ValidationResponse = {
hasError: boolean;
errorMessage?: string;
};
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
-export declare type UpdateFormInputValues = {
- name?: string;
- nmTest?: string;
- parentTable?: ParentTable;
+export declare type UpdateCPKTeacherFormInputValues = {
+ specialTeacherId?: string;
+ CPKStudent?: CPKStudent;
+ CPKClasses?: CPKClass[];
+ CPKProjects?: CPKProject[];
};
-export declare type UpdateFormValidationValues = {
- name?: ValidationFunction;
- nmTest?: ValidationFunction;
- parentTable?: ValidationFunction;
+export declare type UpdateCPKTeacherFormValidationValues = {
+ specialTeacherId?: ValidationFunction;
+ CPKStudent?: ValidationFunction;
+ CPKClasses?: ValidationFunction;
+ CPKProjects?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
-export declare type UpdateFormOverridesProps = {
- UpdateFormGrid?: PrimitiveOverrideProps;
- name?: PrimitiveOverrideProps;
- nmTest?: PrimitiveOverrideProps;
- parentTable?: PrimitiveOverrideProps;
+export declare type UpdateCPKTeacherFormOverridesProps = {
+ UpdateCPKTeacherFormGrid?: PrimitiveOverrideProps;
+ specialTeacherId?: PrimitiveOverrideProps;
+ CPKStudent?: PrimitiveOverrideProps;
+ CPKClasses?: PrimitiveOverrideProps;
+ CPKProjects?: PrimitiveOverrideProps;
} & EscapeHatchProps;
-export declare type UpdateFormProps = React.PropsWithChildren<{
- overrides?: UpdateFormOverridesProps | undefined | null;
+export declare type UpdateCPKTeacherFormProps = React.PropsWithChildren<{
+ overrides?: UpdateCPKTeacherFormOverridesProps | undefined | null;
} & {
- id?: string;
- basicTable?: BasicTable;
- onSubmit?: (fields: UpdateFormInputValues) => UpdateFormInputValues;
- onSuccess?: (fields: UpdateFormInputValues) => void;
- onError?: (fields: UpdateFormInputValues, errorMessage: string) => void;
- onChange?: (fields: UpdateFormInputValues) => UpdateFormInputValues;
- onValidate?: UpdateFormValidationValues;
+ specialTeacherId?: string;
+ cPKTeacher?: CPKTeacher;
+ onSubmit?: (fields: UpdateCPKTeacherFormInputValues) => UpdateCPKTeacherFormInputValues;
+ onSuccess?: (fields: UpdateCPKTeacherFormInputValues) => void;
+ onError?: (fields: UpdateCPKTeacherFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: UpdateCPKTeacherFormInputValues) => UpdateCPKTeacherFormInputValues;
+ onValidate?: UpdateCPKTeacherFormValidationValues;
} & React.CSSProperties>;
-export default function UpdateForm(props: UpdateFormProps): React.ReactElement;
+export default function UpdateCPKTeacherForm(props: UpdateCPKTeacherFormProps): React.ReactElement;
"
`;
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 adbce169..bce2db1c 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
@@ -911,6 +911,32 @@ describe('amplify form renderer tests', () => {
expect(declaration).toMatchSnapshot();
});
+ it('should generate an update form with many to many relationship - amplify js v6', () => {
+ const { componentText, declaration } = generateWithAmplifyFormRenderer(
+ 'forms/relationships/update-class',
+ 'datastore/relationships/many-to-many-class',
+ { ...defaultCLIRenderConfig, ...rendererConfigWithGraphQL, dependencies: { 'aws-amplify': '^6.0.0' } },
+ { isNonModelSupported: true, isRelationshipSupported: true },
+ );
+
+ // check for import statement for graphql operation
+ // v6 api
+ expect(componentText).toContain('import { generateClient } from "aws-amplify/api";');
+ expect(componentText).toContain(`const client = generateClient();`);
+ expect(componentText).toContain('await client.graphql({');
+
+ expect(componentText).not.toContain('DataStore');
+ expect(componentText).not.toContain('import { API } from "aws-amplify";');
+ expect(componentText).not.toContain(`API.graphql`);
+
+ expect(componentText).toContain('createStudentClass');
+ expect(componentText).toContain('deleteStudentClass');
+ expect(componentText).toContain('updateClass');
+
+ expect(componentText).toMatchSnapshot();
+ expect(declaration).toMatchSnapshot();
+ });
+
it('should generate an update form with composite primary key', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/relationships/update-movie',
@@ -939,6 +965,30 @@ describe('amplify form renderer tests', () => {
expect(declaration).toMatchSnapshot();
});
+ it('should generate an update form with composite primary key - amplify js v6', () => {
+ const { componentText, declaration } = generateWithAmplifyFormRenderer(
+ 'forms/relationships/update-movie',
+ 'models/composite-key-movie',
+ { ...defaultCLIRenderConfig, ...rendererConfigWithGraphQL, dependencies: { 'aws-amplify': '^6.0.0' } },
+ { isNonModelSupported: true, isRelationshipSupported: true },
+ );
+
+ // no datastore reference
+ expect(componentText).not.toContain('DataStore');
+
+ // no v5 api references
+ expect(componentText).not.toContain('import { API } from "aws-amplify";');
+ expect(componentText).not.toContain(`API.graphql`);
+
+ // v6 api
+ expect(componentText).toContain('import { generateClient } from "aws-amplify/api";');
+ expect(componentText).toContain(`const client = generateClient();`);
+ expect(componentText).toContain('await client.graphql({');
+
+ expect(componentText).toMatchSnapshot();
+ expect(declaration).toMatchSnapshot();
+ });
+
it('should generate an upgrade form with multiple relationship & cpk', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/cpk-teacher-datastore-update',
@@ -971,6 +1021,29 @@ describe('amplify form renderer tests', () => {
expect(declaration).toMatchSnapshot();
});
+ it('should generate an upgrade form with multiple relationship & cpk - amplify js v6', () => {
+ const { componentText, declaration } = generateWithAmplifyFormRenderer(
+ 'forms/cpk-teacher-datastore-update',
+ 'datastore/cpk-relationships',
+ { ...defaultCLIRenderConfig, ...rendererConfigWithGraphQL, dependencies: { 'aws-amplify': '^6.0.0' } },
+ { isNonModelSupported: true, isRelationshipSupported: true },
+ );
+
+ // check for import statement for graphql operation
+ expect(componentText).not.toContain('DataStore');
+ // no v5 api references
+ expect(componentText).not.toContain('import { API } from "aws-amplify";');
+ expect(componentText).not.toContain(`API.graphql`);
+
+ // v6 api
+ expect(componentText).toContain('import { generateClient } from "aws-amplify/api";');
+ expect(componentText).toContain(`const client = generateClient();`);
+ expect(componentText).toContain('await client.graphql({');
+
+ expect(componentText).toMatchSnapshot();
+ expect(declaration).toMatchSnapshot();
+ });
+
it('should generate a create form with multiple hasOne relationships', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/book-datastore-relationship-multiple',
@@ -1001,6 +1074,26 @@ describe('amplify form renderer tests', () => {
expect(declaration).toMatchSnapshot();
});
+ it('should generate a create form with belongsTo relationship - amplify js v6', () => {
+ const { componentText } = generateWithAmplifyFormRenderer(
+ 'forms/member-datastore-create',
+ 'datastore/project-team-model',
+ { ...defaultCLIRenderConfig, ...rendererConfigWithGraphQL, dependencies: { 'aws-amplify': '^6.0.0' } },
+ { isNonModelSupported: true, isRelationshipSupported: true },
+ );
+
+ // check for import statement for graphql operation
+ expect(componentText).not.toContain('DataStore');
+ // no v5 api references
+ expect(componentText).not.toContain('import { API } from "aws-amplify";');
+ expect(componentText).not.toContain(`API.graphql`);
+
+ // v6 api
+ expect(componentText).toContain('import { generateClient } from "aws-amplify/api";');
+ expect(componentText).toContain(`const client = generateClient();`);
+ expect(componentText).toContain('await client.graphql({');
+ });
+
it('should generate a create form with nonModel field', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'models/table-with-custom-type/forms/BasicTableCreateFormDefault',
@@ -1108,6 +1201,24 @@ describe('amplify form renderer tests', () => {
expect(declaration).toMatchSnapshot();
});
+ it('should render a create form for child of 1:m relationship - amplify js v6', () => {
+ const { componentText } = generateWithAmplifyFormRenderer(
+ 'forms/composite-toy-datastore-create',
+ 'datastore/composite-relationships',
+ { ...defaultCLIRenderConfig, ...rendererConfigWithGraphQL, dependencies: { 'aws-amplify': '^6.0.0' } },
+ { isNonModelSupported: true, isRelationshipSupported: true },
+ );
+
+ // no v5 api references
+ expect(componentText).not.toContain('import { API } from "aws-amplify";');
+ expect(componentText).not.toContain(`API.graphql`);
+
+ // v6 api
+ expect(componentText).toContain('import { generateClient } from "aws-amplify/api";');
+ expect(componentText).toContain(`const client = generateClient();`);
+ expect(componentText).toContain('await client.graphql({');
+ });
+
it('should render a create form for child of 1:m-belongsTo relationship', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'forms/comment-datastore-create',
@@ -1249,6 +1360,27 @@ describe('amplify form renderer tests', () => {
expect(declaration).toMatchSnapshot();
});
+ it('should generate a create form with multiple relationship & cpk - amplify js v6', () => {
+ const { componentText } = generateWithAmplifyFormRenderer(
+ 'forms/cpk-teacher-datastore-create',
+ 'datastore/cpk-relationships',
+ { ...defaultCLIRenderConfig, ...rendererConfigWithGraphQL, dependencies: { 'aws-amplify': '^6.0.0' } },
+ { isNonModelSupported: true, isRelationshipSupported: true },
+ );
+
+ // no datastore reference
+ expect(componentText).not.toContain('DataStore');
+
+ // no v5 api references
+ expect(componentText).not.toContain('import { API } from "aws-amplify";');
+ expect(componentText).not.toContain(`API.graphql`);
+
+ // v6 api
+ expect(componentText).toContain('import { generateClient } from "aws-amplify/api";');
+ expect(componentText).toContain(`const client = generateClient();`);
+ expect(componentText).toContain('await client.graphql({');
+ });
+
it('should generate an update form with id field instead of belongsTo', () => {
const { componentText, declaration } = generateWithAmplifyFormRenderer(
'models/comment-with-postID/forms/CommentUpdateForm',
diff --git a/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts b/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts
index e4ff3287..3c67ad5e 100644
--- a/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts
+++ b/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts
@@ -937,6 +937,7 @@ export const buildManyToManyRelationshipStatements = (
relatedModelPrimaryKeys,
joinTableRelatedModelFields,
importCollection,
+ renderConfigDependencies,
)
: factory.createCallExpression(
factory.createPropertyAccessExpression(