Skip to content

Commit de605ba

Browse files
committed
richer has many support in auto form
1 parent c847e08 commit de605ba

11 files changed

+109
-20
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { AppProvider, Card, Page } from "@shopify/polaris";
2+
import translations from "@shopify/polaris/locales/en.json";
3+
import React from "react";
4+
import { FormProvider, useForm } from "react-hook-form";
5+
import { Provider } from "../../../src/GadgetProvider.tsx";
6+
import { PolarisAutoForm } from "../../../src/auto/polaris/PolarisAutoForm.tsx";
7+
import { PolarisAutoInput } from "../../../src/auto/polaris/inputs/PolarisAutoInput.tsx";
8+
import { PolarisAutoHasManyInput } from "../../../src/auto/polaris/inputs/relationships/PolarisAutoHasManyInput.tsx";
9+
import { PolarisAutoRelatedForm } from "../../../src/auto/polaris/inputs/relationships/PolarisAutoRelatedForm.tsx";
10+
import { PolarisAutoSubmit } from "../../../src/auto/polaris/submit/PolarisAutoSubmit.tsx";
11+
import { testApi as api } from "../../apis.ts";
12+
13+
const ExampleAutoRelatedForm = (props) => {
14+
return (
15+
<PolarisAutoForm {...props}>
16+
<PolarisAutoInput field="name" />
17+
<PolarisAutoHasManyInput field="widgets" />
18+
<PolarisAutoRelatedForm field="widgets">
19+
<PolarisAutoInput field="name" />
20+
</PolarisAutoRelatedForm>
21+
<PolarisAutoSubmit />
22+
</PolarisAutoForm>
23+
);
24+
};
25+
26+
export default {
27+
title: "Polaris/AutoForm/AutoRelatedForm",
28+
component: ExampleAutoRelatedForm,
29+
decorators: [
30+
(Story) => {
31+
return (
32+
<Provider api={api}>
33+
<AppProvider i18n={translations}>
34+
<FormProvider {...useForm()}>
35+
<Page>
36+
<Card>
37+
<Story />
38+
</Card>
39+
</Page>
40+
</FormProvider>
41+
</AppProvider>
42+
</Provider>
43+
);
44+
},
45+
],
46+
};
47+
48+
export const Primary = {
49+
args: {
50+
action: api.section.update,
51+
findBy: "1",
52+
},
53+
};

packages/react/src/auto/hooks/useBelongsToInputController.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useController } from "react-hook-form";
33
import { useAutoFormMetadata } from "../AutoFormContext.js";
44
import type { AutoRelationshipInputProps } from "../interfaces/AutoRelationshipInputProps.js";
55
import { useFieldMetadata } from "./useFieldMetadata.js";
6-
import { useRelatedModelOptions } from "./useRelatedModelOptions.js";
6+
import { useRelatedModelOptions } from "./useRelatedModel.js";
77

88
export const useBelongsToInputController = (props: AutoRelationshipInputProps) => {
99
const { field, control } = props;

packages/react/src/auto/hooks/useHasManyInputController.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { GadgetHasManyConfig } from "../../internal/gql/graphql.js";
44
import { uniq } from "../../utils.js";
55
import type { AutoRelationshipInputProps } from "../interfaces/AutoRelationshipInputProps.js";
66
import { useFieldMetadata } from "./useFieldMetadata.js";
7-
import { useRelatedModelOptions } from "./useRelatedModelOptions.js";
7+
import { useRelatedModelOptions } from "./useRelatedModel.js";
88

99
export const useHasManyInputController = (props: AutoRelationshipInputProps) => {
1010
const { field } = props;

packages/react/src/auto/hooks/useHasOneInputController.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { GadgetHasOneConfig } from "../../internal/gql/graphql.js";
44
import { uniq } from "../../utils.js";
55
import type { AutoRelationshipInputProps } from "../interfaces/AutoRelationshipInputProps.js";
66
import { useFieldMetadata } from "./useFieldMetadata.js";
7-
import { useRelatedModelOptions } from "./useRelatedModelOptions.js";
7+
import { useRelatedModelOptions } from "./useRelatedModel.js";
88

99
export const useHasOneInputController = (props: AutoRelationshipInputProps) => {
1010
const { field } = props;

packages/react/src/auto/hooks/useRelatedModelOptions.tsx renamed to packages/react/src/auto/hooks/useRelatedModel.tsx

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ import { useModelManager } from "./useModelManager.js";
1313
export const optionRecordsToLoadCount = 25;
1414
export const selectedRecordsToLoadCount = 25;
1515

16-
export const useRelatedModelOptions = (props: {
17-
field: string; // Field API identifier
18-
optionLabel?: OptionLabel; // The label to display for each related model record
19-
}) => {
16+
export const useRelatedModelRecords = (props: { field: string }) => {
2017
const { field } = props;
2118
const { metadata } = useFieldMetadata(field);
2219
const { findBy, model } = useAutoFormMetadata();
@@ -30,11 +27,6 @@ export const useRelatedModelOptions = (props: {
3027
const relatedModelInverseFieldApiId =
3128
"inverseField" in relationshipFieldConfig ? relationshipFieldConfig.inverseField?.apiIdentifier : undefined;
3229

33-
const optionLabel = assert(
34-
props.optionLabel ?? relationshipFieldConfig.relatedModel?.defaultDisplayField.apiIdentifier,
35-
"Option label is required for relationships"
36-
);
37-
3830
const { selected } = isBelongsToField
3931
? // eslint-disable-next-line
4032
useLinkedChildModelRelatedModelRecords({
@@ -54,8 +46,30 @@ export const useRelatedModelOptions = (props: {
5446

5547
const relatedModelRecords = useAllRelatedModelRecords({
5648
relatedModel: { apiIdentifier: relatedModelApiIdentifier!, namespace: relatedModelNamespace },
57-
optionLabel,
49+
filter: isBelongsToField ? undefined : { [relatedModelInverseFieldApiId + "Id"]: { isSet: false } },
5850
});
51+
52+
return {
53+
selected,
54+
relatedModelRecords,
55+
};
56+
};
57+
58+
export const useRelatedModelOptions = (props: {
59+
field: string; // Field API identifier
60+
optionLabel?: OptionLabel; // The label to display for each related model record
61+
}) => {
62+
const { field } = props;
63+
const { metadata } = useFieldMetadata(field);
64+
65+
const relationshipFieldConfig = metadata.configuration as RelationshipFieldConfig;
66+
67+
const optionLabel = assert(
68+
props.optionLabel ?? relationshipFieldConfig.relatedModel?.defaultDisplayField.apiIdentifier,
69+
"Option label is required for relationships"
70+
);
71+
const { selected, relatedModelRecords } = useRelatedModelRecords(props);
72+
5973
const { relatedModel, pagination, search } = relatedModelRecords;
6074

6175
const getOptions = () => {
@@ -120,7 +134,7 @@ export const getRecordsAsOptions = (records: Record<string, any>[], optionLabel:
120134
*
121135
* The lookup is done using the `findBy` to lookup on the current model to retrieve the related model record data
122136
*/
123-
export const useLinkedChildModelRelatedModelRecords = (props: {
137+
const useLinkedChildModelRelatedModelRecords = (props: {
124138
belongsToFieldApiId: string;
125139
currentRecordId?: string;
126140
currentModel: { apiIdentifier: string; namespace?: string[] | string | null };
@@ -154,7 +168,7 @@ export const useLinkedChildModelRelatedModelRecords = (props: {
154168
/**
155169
* For getting the related child model records in a HasOne/HasMany relationship
156170
*/
157-
export const useLinkedParentModelRelatedModelRecords = (props: {
171+
const useLinkedParentModelRelatedModelRecords = (props: {
158172
relatedModel: {
159173
apiIdentifier: string;
160174
namespace?: string[] | string | null;
@@ -177,7 +191,7 @@ export const useLinkedParentModelRelatedModelRecords = (props: {
177191
pause: !currentRecordId, // HasOne/HasMany need the current record to query the inverse field in the related model
178192

179193
first: selectedRecordsToLoadCount, // Many records can point to the current record in hasOne/hasMany
180-
filter: { [inverseFieldApiIdentifier]: { equals: currentRecordId } }, // Filter by the inverse field belongsTo field value
194+
filter: { [inverseFieldApiIdentifier + "Id"]: { equals: currentRecordId } }, // Filter by the inverse field belongsTo field value
181195
});
182196

183197
return {
@@ -189,8 +203,9 @@ export const useLinkedParentModelRelatedModelRecords = (props: {
189203
};
190204
};
191205

192-
export const useAllRelatedModelRecords = (props: {
206+
const useAllRelatedModelRecords = (props: {
193207
optionLabel?: OptionLabel;
208+
filter?: Record<string, any>;
194209
relatedModel: { apiIdentifier: string; namespace?: string[] | string | null };
195210
}) => {
196211
const { optionLabel, relatedModel } = props;
@@ -204,6 +219,7 @@ export const useAllRelatedModelRecords = (props: {
204219

205220
const [{ data: newlyFetchedRecords, fetching, error }, _refetch] = useFindMany(relatedModelManager as any, {
206221
first: optionRecordsToLoadCount,
222+
...(props.filter && { filter: props.filter }),
207223
...(paginationPage && { after: paginationPage }),
208224
...(searchValue && { search: searchValue }),
209225
...(optionLabelIsFieldName && { select: { id: true, [optionLabel]: true } }),

packages/react/src/auto/polaris/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ export {
2020
} from "./inputs/PolarisAutoTextInput.js";
2121
export { PolarisAutoBelongsToInput as AutoBelongsToInput } from "./inputs/relationships/PolarisAutoBelongsToInput.js";
2222
export { PolarisAutoHasManyInput as AutoHasManyInput } from "./inputs/relationships/PolarisAutoHasManyInput.js";
23+
export { PolarisAutoRelatedForm as AutoRelatedForm } from "./inputs/relationships/PolarisAutoRelatedForm.js";
2324
export { PolarisAutoSubmit as AutoSubmit } from "./submit/PolarisAutoSubmit.js";
2425
export { PolarisSubmitResultBanner as SubmitResultBanner } from "./submit/PolarisSubmitResultBanner.js";

packages/react/src/auto/polaris/inputs/relationships/PolarisAutoBelongsToInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Combobox, Tag } from "@shopify/polaris";
22
import React from "react";
33
import { useBelongsToInputController } from "../../../hooks/useBelongsToInputController.js";
4-
import { optionRecordsToLoadCount } from "../../../hooks/useRelatedModelOptions.js";
4+
import { optionRecordsToLoadCount } from "../../../hooks/useRelatedModel.js";
55
import type { AutoRelationshipInputProps } from "../../../interfaces/AutoRelationshipInputProps.js";
66
import { RelatedModelOptions } from "./RelatedModelOptions.js";
77

packages/react/src/auto/polaris/inputs/relationships/PolarisAutoHasManyInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { GadgetRecordList } from "@gadgetinc/api-client-core";
22
import { Banner, Combobox } from "@shopify/polaris";
33
import React from "react";
44
import { useHasManyInputController } from "../../../hooks/useHasManyInputController.js";
5-
import { optionRecordsToLoadCount } from "../../../hooks/useRelatedModelOptions.js";
5+
import { optionRecordsToLoadCount } from "../../../hooks/useRelatedModel.js";
66
import type { AutoRelationshipInputProps } from "../../../interfaces/AutoRelationshipInputProps.js";
77
import { RelatedModelOptions } from "./RelatedModelOptions.js";
88
import { getSelectedRelatedRecordTags } from "./SelectedRelatedRecordTags.js";

packages/react/src/auto/polaris/inputs/relationships/PolarisAutoHasOneInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Banner, Combobox } from "@shopify/polaris";
22
import React from "react";
33
import { useHasOneInputController } from "../../../hooks/useHasOneInputController.js";
4-
import { optionRecordsToLoadCount } from "../../../hooks/useRelatedModelOptions.js";
4+
import { optionRecordsToLoadCount } from "../../../hooks/useRelatedModel.js";
55
import type { AutoRelationshipInputProps } from "../../../interfaces/AutoRelationshipInputProps.js";
66
import { RelatedModelOptions } from "./RelatedModelOptions.js";
77
import { getSelectedRelatedRecordTags } from "./SelectedRelatedRecordTags.js";
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from "react";
2+
import { useFormContext } from "react-hook-form";
3+
import { useFieldMetadata } from "../../../hooks/useFieldMetadata.js";
4+
import { useRelatedModelRecords } from "../../../hooks/useRelatedModel.js";
5+
6+
export const PolarisAutoRelatedForm = (props: { field: string; children: React.ReactNode }) => {
7+
const { field } = props;
8+
const { getValues } = useFormContext();
9+
const { metadata, path } = useFieldMetadata(field);
10+
const { selected, relatedModelRecords } = useRelatedModelRecords(props);
11+
12+
const values = getValues(path);
13+
14+
console.log({ values, path, field, selected, relatedModelRecords, metadata }, "foo foo fas");
15+
16+
return <div>hi</div>;
17+
};

0 commit comments

Comments
 (0)