@comet/admin-generator 8.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -0
- package/bin/admin-generator.js +5 -0
- package/lib/adminGenerator.d.ts +1 -0
- package/lib/adminGenerator.js +8 -0
- package/lib/commands/generate/generate-command.d.ts +197 -0
- package/lib/commands/generate/generate-command.js +114 -0
- package/lib/commands/generate/generateForm/generateComponentFormField.d.ts +5 -0
- package/lib/commands/generate/generateForm/generateComponentFormField.js +18 -0
- package/lib/commands/generate/generateForm/generateFields.d.ts +35 -0
- package/lib/commands/generate/generateForm/generateFields.js +88 -0
- package/lib/commands/generate/generateForm/generateForm.d.ts +13 -0
- package/lib/commands/generate/generateForm/generateForm.js +468 -0
- package/lib/commands/generate/generateForm/generateFormField.d.ts +12 -0
- package/lib/commands/generate/generateForm/generateFormField.js +525 -0
- package/lib/commands/generate/generateForm/generateFormLayout.d.ts +12 -0
- package/lib/commands/generate/generateForm/generateFormLayout.js +164 -0
- package/lib/commands/generate/generateForm/getForwardedGqlArgs.d.ts +19 -0
- package/lib/commands/generate/generateForm/getForwardedGqlArgs.js +79 -0
- package/lib/commands/generate/generateGrid/combinationColumn.d.ts +43 -0
- package/lib/commands/generate/generateGrid/combinationColumn.js +151 -0
- package/lib/commands/generate/generateGrid/findInputObjectType.d.ts +2 -0
- package/lib/commands/generate/generateGrid/findInputObjectType.js +16 -0
- package/lib/commands/generate/generateGrid/generateGqlFieldList.d.ts +5 -0
- package/lib/commands/generate/generateGrid/generateGqlFieldList.js +43 -0
- package/lib/commands/generate/generateGrid/generateGrid.d.ts +14 -0
- package/lib/commands/generate/generateGrid/generateGrid.js +827 -0
- package/lib/commands/generate/generateGrid/generateGridToolbar.d.ts +14 -0
- package/lib/commands/generate/generateGrid/generateGridToolbar.js +92 -0
- package/lib/commands/generate/generateGrid/getForwardedGqlArgs.d.ts +14 -0
- package/lib/commands/generate/generateGrid/getForwardedGqlArgs.js +64 -0
- package/lib/commands/generate/generateGrid/getPropsForFilterProp.d.ts +12 -0
- package/lib/commands/generate/generateGrid/getPropsForFilterProp.js +14 -0
- package/lib/commands/generate/generateGrid/usableFields.d.ts +8 -0
- package/lib/commands/generate/generateGrid/usableFields.js +2 -0
- package/lib/commands/generate/utils/camelCaseToHumanReadable.d.ts +1 -0
- package/lib/commands/generate/utils/camelCaseToHumanReadable.js +8 -0
- package/lib/commands/generate/utils/columnVisibility.d.ts +6 -0
- package/lib/commands/generate/utils/columnVisibility.js +2 -0
- package/lib/commands/generate/utils/findMutationType.d.ts +3 -0
- package/lib/commands/generate/utils/findMutationType.js +19 -0
- package/lib/commands/generate/utils/findQueryType.d.ts +2 -0
- package/lib/commands/generate/utils/findQueryType.js +19 -0
- package/lib/commands/generate/utils/findRootBlocks.d.ts +8 -0
- package/lib/commands/generate/utils/findRootBlocks.js +67 -0
- package/lib/commands/generate/utils/generateImportsCode.d.ts +5 -0
- package/lib/commands/generate/utils/generateImportsCode.js +27 -0
- package/lib/commands/generate/utils/intl.d.ts +1 -0
- package/lib/commands/generate/utils/intl.js +7 -0
- package/lib/commands/generate/utils/isFieldOptional.d.ts +7 -0
- package/lib/commands/generate/utils/isFieldOptional.js +21 -0
- package/lib/commands/generate/utils/writeGenerated.d.ts +1 -0
- package/lib/commands/generate/utils/writeGenerated.js +57 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -0
- package/package.json +67 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.generateForm = void 0;
|
|
15
|
+
const generate_command_1 = require("../generate-command");
|
|
16
|
+
const findMutationType_1 = require("../utils/findMutationType");
|
|
17
|
+
const generateImportsCode_1 = require("../utils/generateImportsCode");
|
|
18
|
+
const generateFields_1 = require("./generateFields");
|
|
19
|
+
const getForwardedGqlArgs_1 = require("./getForwardedGqlArgs");
|
|
20
|
+
function generateFormPropsCode(props) {
|
|
21
|
+
if (!props.length)
|
|
22
|
+
return { formPropsTypeCode: "", formPropsParamsCode: "" };
|
|
23
|
+
const uniqueProps = props.reduce((acc, item) => {
|
|
24
|
+
const propWithSameName = acc.find((prop) => prop.name == item.name);
|
|
25
|
+
if (!propWithSameName)
|
|
26
|
+
return [item, ...acc];
|
|
27
|
+
if (propWithSameName.type != item.type || propWithSameName.optional != item.optional) {
|
|
28
|
+
// this is currently not supported
|
|
29
|
+
return [item, ...acc];
|
|
30
|
+
}
|
|
31
|
+
return acc;
|
|
32
|
+
}, []);
|
|
33
|
+
return {
|
|
34
|
+
formPropsTypeCode: `interface FormProps {
|
|
35
|
+
${uniqueProps.map((prop) => `${prop.name}${prop.optional ? `?` : ``}: ${prop.type};`).join("\n")}
|
|
36
|
+
}`,
|
|
37
|
+
formPropsParamsCode: `{${uniqueProps.map((prop) => prop.name).join(", ")}}: FormProps`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function generateForm({ exportName, baseOutputFilename, targetDirectory, gqlIntrospection, },
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
|
+
config) {
|
|
43
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
44
|
+
assertValidConfig(config);
|
|
45
|
+
const gqlType = config.gqlType;
|
|
46
|
+
const instanceGqlType = gqlType[0].toLowerCase() + gqlType.substring(1);
|
|
47
|
+
const formFragmentName = (_a = config.fragmentName) !== null && _a !== void 0 ? _a : `${gqlType}Form`;
|
|
48
|
+
const gqlDocuments = {};
|
|
49
|
+
const imports = [];
|
|
50
|
+
const props = [];
|
|
51
|
+
const mode = (_b = config.mode) !== null && _b !== void 0 ? _b : "all";
|
|
52
|
+
const editMode = mode === "edit" || mode == "all";
|
|
53
|
+
const addMode = mode === "add" || mode == "all";
|
|
54
|
+
const createMutationType = addMode && (0, findMutationType_1.findMutationTypeOrThrow)((_c = config.createMutation) !== null && _c !== void 0 ? _c : `create${gqlType}`, gqlIntrospection);
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
|
+
const formFields = config.fields.reduce((acc, field) => {
|
|
57
|
+
if ((0, generate_command_1.isFormLayoutConfig)(field)) {
|
|
58
|
+
// using forEach instead of acc.push(...field.fields.filter(isFormFieldConfig)) because typescript can't handle mixed typing
|
|
59
|
+
field.fields.forEach((nestedFieldConfig) => {
|
|
60
|
+
if ((0, generate_command_1.isFormFieldConfig)(nestedFieldConfig)) {
|
|
61
|
+
acc.push(nestedFieldConfig);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
else if ((0, generate_command_1.isFormFieldConfig)(field)) {
|
|
66
|
+
acc.push(field);
|
|
67
|
+
}
|
|
68
|
+
return acc;
|
|
69
|
+
}, []);
|
|
70
|
+
const gqlArgs = [];
|
|
71
|
+
if (createMutationType) {
|
|
72
|
+
const { imports: forwardedGqlArgsImports, props: forwardedGqlArgsProps, gqlArgs: forwardedGqlArgs, } = (0, getForwardedGqlArgs_1.getForwardedGqlArgs)({
|
|
73
|
+
fields: formFields,
|
|
74
|
+
gqlOperation: createMutationType,
|
|
75
|
+
gqlIntrospection,
|
|
76
|
+
});
|
|
77
|
+
imports.push(...forwardedGqlArgsImports);
|
|
78
|
+
props.push(...forwardedGqlArgsProps);
|
|
79
|
+
gqlArgs.push(...forwardedGqlArgs);
|
|
80
|
+
}
|
|
81
|
+
if (editMode) {
|
|
82
|
+
if (mode === "all") {
|
|
83
|
+
props.push({ name: "id", optional: true, type: "string" });
|
|
84
|
+
}
|
|
85
|
+
else if (mode === "edit") {
|
|
86
|
+
props.push({ name: "id", optional: false, type: "string" });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const { formPropsTypeCode, formPropsParamsCode } = generateFormPropsCode(props);
|
|
90
|
+
const rootBlockFields = formFields
|
|
91
|
+
.filter((field) => field.type == "block")
|
|
92
|
+
.map((field) => {
|
|
93
|
+
// map is for ts to infer block type correctly
|
|
94
|
+
if (field.type !== "block")
|
|
95
|
+
throw new Error("Field is not a block field");
|
|
96
|
+
return field;
|
|
97
|
+
});
|
|
98
|
+
rootBlockFields.forEach((field) => {
|
|
99
|
+
imports.push({
|
|
100
|
+
name: field.block.name,
|
|
101
|
+
importPath: field.block.import,
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
const readOnlyFields = formFields.filter((field) => field.readOnly);
|
|
105
|
+
const fileFields = formFields.filter((field) => field.type == "fileUpload");
|
|
106
|
+
if (fileFields.length > 0) {
|
|
107
|
+
imports.push({ name: "GQLFinalFormFileUploadFragment", importPath: "@comet/cms-admin" });
|
|
108
|
+
}
|
|
109
|
+
// Unnecessary field.type == "fileUpload" check to make TypeScript happy
|
|
110
|
+
const downloadableFileFields = fileFields.filter((field) => field.type == "fileUpload" && field.download);
|
|
111
|
+
if (fileFields.length > 0) {
|
|
112
|
+
imports.push({ name: "GQLFinalFormFileUploadDownloadableFragment", importPath: "@comet/cms-admin" });
|
|
113
|
+
}
|
|
114
|
+
let hooksCode = "";
|
|
115
|
+
let formValueToGqlInputCode = "";
|
|
116
|
+
const formFragmentFields = [];
|
|
117
|
+
const formValuesConfig = [];
|
|
118
|
+
const _h = (0, generateFields_1.generateFields)({
|
|
119
|
+
gqlIntrospection,
|
|
120
|
+
baseOutputFilename,
|
|
121
|
+
fields: config.fields,
|
|
122
|
+
formFragmentName,
|
|
123
|
+
formConfig: config,
|
|
124
|
+
gqlType: config.gqlType,
|
|
125
|
+
}), { code: fieldsCode } = _h, generatedFields = __rest(_h, ["code"]);
|
|
126
|
+
for (const name in generatedFields.gqlDocuments) {
|
|
127
|
+
gqlDocuments[name] = {
|
|
128
|
+
document: generatedFields.gqlDocuments[name].document,
|
|
129
|
+
export: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
imports.push(...generatedFields.imports);
|
|
133
|
+
hooksCode += generatedFields.hooksCode;
|
|
134
|
+
formValueToGqlInputCode += generatedFields.formValueToGqlInputCode;
|
|
135
|
+
formFragmentFields.push(...generatedFields.formFragmentFields);
|
|
136
|
+
formValuesConfig.push(...generatedFields.formValuesConfig);
|
|
137
|
+
gqlDocuments[`${instanceGqlType}FormFragment`] = {
|
|
138
|
+
document: `
|
|
139
|
+
fragment ${formFragmentName} on ${gqlType} {
|
|
140
|
+
${formFragmentFields.join("\n")}
|
|
141
|
+
}
|
|
142
|
+
${fileFields.length > 0 && fileFields.length !== downloadableFileFields.length ? "${finalFormFileUploadFragment}" : ""}
|
|
143
|
+
${downloadableFileFields.length > 0 ? "${finalFormFileUploadDownloadableFragment}" : ""}
|
|
144
|
+
`,
|
|
145
|
+
export: editMode,
|
|
146
|
+
};
|
|
147
|
+
if (editMode) {
|
|
148
|
+
gqlDocuments[`${instanceGqlType}Query`] = {
|
|
149
|
+
document: `
|
|
150
|
+
query ${gqlType}($id: ID!) {
|
|
151
|
+
${instanceGqlType}(id: $id) {
|
|
152
|
+
id
|
|
153
|
+
updatedAt
|
|
154
|
+
...${formFragmentName}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
\${${`${instanceGqlType}FormFragment`}}
|
|
158
|
+
`,
|
|
159
|
+
export: true,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (addMode && createMutationType) {
|
|
163
|
+
gqlDocuments[`create${gqlType}Mutation`] = {
|
|
164
|
+
document: `
|
|
165
|
+
mutation Create${gqlType}(${gqlArgs.filter((gqlArg) => !gqlArg.isInputArgSubfield).length
|
|
166
|
+
? `${gqlArgs
|
|
167
|
+
.filter((gqlArg) => !gqlArg.isInputArgSubfield)
|
|
168
|
+
.map((gqlArg) => {
|
|
169
|
+
return `$${gqlArg.name}: ${gqlArg.type}!`;
|
|
170
|
+
})
|
|
171
|
+
.join(", ")}, `
|
|
172
|
+
: ``}$input: ${gqlType}Input!) {
|
|
173
|
+
${createMutationType.name}(${gqlArgs.filter((gqlArg) => !gqlArg.isInputArgSubfield).length
|
|
174
|
+
? `${gqlArgs
|
|
175
|
+
.filter((gqlArg) => !gqlArg.isInputArgSubfield)
|
|
176
|
+
.map((gqlArg) => {
|
|
177
|
+
return `${gqlArg.name}: $${gqlArg.name}`;
|
|
178
|
+
})
|
|
179
|
+
.join(", ")}, `
|
|
180
|
+
: ``}input: $input) {
|
|
181
|
+
id
|
|
182
|
+
updatedAt
|
|
183
|
+
...${formFragmentName}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
\${${`${instanceGqlType}FormFragment`}}
|
|
187
|
+
`,
|
|
188
|
+
export: true,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
if (editMode) {
|
|
192
|
+
gqlDocuments[`update${gqlType}Mutation`] = {
|
|
193
|
+
document: `
|
|
194
|
+
mutation Update${gqlType}($id: ID!, $input: ${gqlType}UpdateInput!) {
|
|
195
|
+
update${gqlType}(id: $id, input: $input) {
|
|
196
|
+
id
|
|
197
|
+
updatedAt
|
|
198
|
+
...${formFragmentName}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
\${${`${instanceGqlType}FormFragment`}}
|
|
202
|
+
`,
|
|
203
|
+
export: true,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
for (const name in gqlDocuments) {
|
|
207
|
+
const gqlDocument = gqlDocuments[name];
|
|
208
|
+
imports.push({
|
|
209
|
+
name: name,
|
|
210
|
+
importPath: `./${baseOutputFilename}.gql`,
|
|
211
|
+
});
|
|
212
|
+
const match = gqlDocument.document.match(/^\s*(query|mutation|fragment)\s+(\w+)/);
|
|
213
|
+
if (!match)
|
|
214
|
+
throw new Error(`Could not find query or mutation name in ${gqlDocument}`);
|
|
215
|
+
const type = match[1];
|
|
216
|
+
const documentName = match[2];
|
|
217
|
+
imports.push({
|
|
218
|
+
name: `GQL${documentName}${type[0].toUpperCase() + type.substring(1)}`,
|
|
219
|
+
importPath: `./${baseOutputFilename}.gql.generated`,
|
|
220
|
+
});
|
|
221
|
+
imports.push({
|
|
222
|
+
name: `GQL${documentName}${type[0].toUpperCase() + type.substring(1)}Variables`,
|
|
223
|
+
importPath: `./${baseOutputFilename}.gql.generated`,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
const finalFormSubscription = Object.keys((_e = (_d = generatedFields.finalFormConfig) === null || _d === void 0 ? void 0 : _d.subscription) !== null && _e !== void 0 ? _e : {});
|
|
227
|
+
const finalFormRenderProps = Object.keys((_g = (_f = generatedFields.finalFormConfig) === null || _f === void 0 ? void 0 : _f.renderProps) !== null && _g !== void 0 ? _g : {});
|
|
228
|
+
let filterByFragmentType = `GQL${formFragmentName}Fragment`;
|
|
229
|
+
let customFilterByFragment = "";
|
|
230
|
+
if (fileFields.length > 0) {
|
|
231
|
+
const keysToOverride = fileFields.map((field) => field.name);
|
|
232
|
+
customFilterByFragment = `type ${formFragmentName}Fragment = Omit<${filterByFragmentType}, ${keysToOverride
|
|
233
|
+
.map((key) => `"${String(key)}"`)
|
|
234
|
+
.join(" | ")}> & {
|
|
235
|
+
${fileFields
|
|
236
|
+
.map((field) => {
|
|
237
|
+
if (field.type !== "fileUpload") {
|
|
238
|
+
throw new Error("Field is not a file upload field");
|
|
239
|
+
}
|
|
240
|
+
if (("multiple" in field && field.multiple) ||
|
|
241
|
+
("maxFiles" in field && typeof field.maxFiles === "number" && field.maxFiles > 1)) {
|
|
242
|
+
return `${String(field.name)}: ${field.download ? "GQLFinalFormFileUploadDownloadableFragment" : "GQLFinalFormFileUploadFragment"}[];`;
|
|
243
|
+
}
|
|
244
|
+
return `${String(field.name)}: ${field.download ? "GQLFinalFormFileUploadDownloadableFragment" : "GQLFinalFormFileUploadFragment"} | null;`;
|
|
245
|
+
})
|
|
246
|
+
.join("\n")}
|
|
247
|
+
}`;
|
|
248
|
+
filterByFragmentType = `${formFragmentName}Fragment`;
|
|
249
|
+
}
|
|
250
|
+
const code = `import { useApolloClient, useQuery, gql } from "@apollo/client";
|
|
251
|
+
import {
|
|
252
|
+
AsyncSelectField,
|
|
253
|
+
CheckboxField,
|
|
254
|
+
Field,
|
|
255
|
+
filterByFragment,
|
|
256
|
+
FinalForm,
|
|
257
|
+
FinalFormInput,
|
|
258
|
+
FinalFormRangeInput,
|
|
259
|
+
FinalFormSelect,
|
|
260
|
+
FinalFormSubmitEvent,
|
|
261
|
+
Loading,
|
|
262
|
+
RadioGroupField,
|
|
263
|
+
TextAreaField,
|
|
264
|
+
TextField,
|
|
265
|
+
useFormApiRef,
|
|
266
|
+
useStackSwitchApi,
|
|
267
|
+
} from "@comet/admin";
|
|
268
|
+
import { ArrowLeft, Lock } from "@comet/admin-icons";
|
|
269
|
+
import { DateTimeField, FinalFormDatePicker } from "@comet/admin-date-time";
|
|
270
|
+
import { BlockState, createFinalFormBlock, queryUpdatedAt, resolveHasSaveConflict, useFormSaveConflict, FileUploadField } from "@comet/cms-admin";
|
|
271
|
+
import { FormControlLabel, IconButton, MenuItem, InputAdornment } from "@mui/material";
|
|
272
|
+
import { FormApi } from "final-form";
|
|
273
|
+
import isEqual from "lodash.isequal";
|
|
274
|
+
import { useMemo } from "react";
|
|
275
|
+
import { FormattedMessage } from "react-intl";
|
|
276
|
+
${(0, generateImportsCode_1.generateImportsCode)(imports)}
|
|
277
|
+
${rootBlockFields.length > 0
|
|
278
|
+
? `const rootBlocks = {
|
|
279
|
+
${rootBlockFields.map((field) => `${String(field.name)}: ${field.block.name}`)}
|
|
280
|
+
};`
|
|
281
|
+
: ""}
|
|
282
|
+
|
|
283
|
+
${customFilterByFragment}
|
|
284
|
+
|
|
285
|
+
type FormValues = ${formValuesConfig.filter((config) => !!config.omitFromFragmentType).length > 0
|
|
286
|
+
? `Omit<${filterByFragmentType}, ${formValuesConfig
|
|
287
|
+
.filter((config) => !!config.omitFromFragmentType)
|
|
288
|
+
.map((config) => `"${config.omitFromFragmentType}"`)
|
|
289
|
+
.join(" | ")}>`
|
|
290
|
+
: `${filterByFragmentType}`} ${formValuesConfig.filter((config) => !!config.typeCode).length > 0
|
|
291
|
+
? `& {
|
|
292
|
+
${formValuesConfig
|
|
293
|
+
.filter((config) => !!config.typeCode)
|
|
294
|
+
.map((config) => config.typeCode)
|
|
295
|
+
.join("\n")}
|
|
296
|
+
}`
|
|
297
|
+
: ""};
|
|
298
|
+
|
|
299
|
+
${formPropsTypeCode}
|
|
300
|
+
|
|
301
|
+
export function ${exportName}(${formPropsParamsCode}) {
|
|
302
|
+
const client = useApolloClient();
|
|
303
|
+
${mode == "all" ? `const mode = id ? "edit" : "add";` : ""}
|
|
304
|
+
const formApiRef = useFormApiRef<FormValues>();
|
|
305
|
+
${addMode ? `const stackSwitchApi = useStackSwitchApi();` : ""}
|
|
306
|
+
|
|
307
|
+
${editMode
|
|
308
|
+
? `
|
|
309
|
+
const { data, error, loading, refetch } = useQuery<GQL${gqlType}Query, GQL${gqlType}QueryVariables>(
|
|
310
|
+
${instanceGqlType}Query,
|
|
311
|
+
${mode == "edit" ? `{ variables: { id } }` : `id ? { variables: { id } } : { skip: true }`},
|
|
312
|
+
);
|
|
313
|
+
`
|
|
314
|
+
: ""}
|
|
315
|
+
|
|
316
|
+
${editMode
|
|
317
|
+
? `const initialValues = useMemo<Partial<FormValues>>(() => data?.${instanceGqlType}
|
|
318
|
+
? {
|
|
319
|
+
...filterByFragment<${filterByFragmentType}>(${instanceGqlType}FormFragment, data.${instanceGqlType}),
|
|
320
|
+
${formValuesConfig
|
|
321
|
+
.filter((config) => !!config.initializationCode)
|
|
322
|
+
.map((config) => config.initializationCode)
|
|
323
|
+
.join(",\n")}
|
|
324
|
+
}
|
|
325
|
+
: {
|
|
326
|
+
${formValuesConfig
|
|
327
|
+
.filter((config) => !!config.defaultInitializationCode)
|
|
328
|
+
.map((config) => config.defaultInitializationCode)
|
|
329
|
+
.join(",\n")}
|
|
330
|
+
}
|
|
331
|
+
, [data]);`
|
|
332
|
+
: `const initialValues = {
|
|
333
|
+
${formValuesConfig
|
|
334
|
+
.filter((config) => !!config.defaultInitializationCode)
|
|
335
|
+
.map((config) => config.defaultInitializationCode)
|
|
336
|
+
.join(",\n")}
|
|
337
|
+
};`}
|
|
338
|
+
|
|
339
|
+
${editMode
|
|
340
|
+
? `
|
|
341
|
+
const saveConflict = useFormSaveConflict({
|
|
342
|
+
checkConflict: async () => {
|
|
343
|
+
const updatedAt = await queryUpdatedAt(client, "${instanceGqlType}", id);
|
|
344
|
+
return resolveHasSaveConflict(data?.${instanceGqlType}.updatedAt, updatedAt);
|
|
345
|
+
},
|
|
346
|
+
formApiRef,
|
|
347
|
+
loadLatestVersion: async () => {
|
|
348
|
+
await refetch();
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
`
|
|
352
|
+
: ""}
|
|
353
|
+
|
|
354
|
+
const handleSubmit = async (${formValuesConfig.filter((config) => !!config.destructFromFormValues).length
|
|
355
|
+
? `{ ${formValuesConfig
|
|
356
|
+
.filter((config) => !!config.destructFromFormValues)
|
|
357
|
+
.map((config) => config.destructFromFormValues)
|
|
358
|
+
.join(", ")}, ...formValues }`
|
|
359
|
+
: `formValues`}: FormValues, form: FormApi<FormValues>${addMode ? `, event: FinalFormSubmitEvent` : ""}) => {
|
|
360
|
+
${editMode ? `if (await saveConflict.checkForConflicts()) throw new Error("Conflicts detected");` : ""}
|
|
361
|
+
const output = {
|
|
362
|
+
...formValues,
|
|
363
|
+
${formValueToGqlInputCode}
|
|
364
|
+
};
|
|
365
|
+
${mode == "all" ? `if (mode === "edit") {` : ""}
|
|
366
|
+
${editMode
|
|
367
|
+
? `
|
|
368
|
+
${readOnlyFields.some((field) => field.name === "id") ? "" : "if (!id) throw new Error();"}
|
|
369
|
+
const { ${readOnlyFields.map((field) => `${String(field.name)},`).join("")} ...updateInput } = output;
|
|
370
|
+
await client.mutate<GQLUpdate${gqlType}Mutation, GQLUpdate${gqlType}MutationVariables>({
|
|
371
|
+
mutation: update${gqlType}Mutation,
|
|
372
|
+
variables: { id, input: updateInput },
|
|
373
|
+
});
|
|
374
|
+
`
|
|
375
|
+
: ""}
|
|
376
|
+
${mode == "all" ? `} else {` : ""}
|
|
377
|
+
${addMode && createMutationType
|
|
378
|
+
? `
|
|
379
|
+
const { data: mutationResponse } = await client.mutate<GQLCreate${gqlType}Mutation, GQLCreate${gqlType}MutationVariables>({
|
|
380
|
+
mutation: create${gqlType}Mutation,
|
|
381
|
+
variables: { input: ${gqlArgs.filter((prop) => prop.isInputArgSubfield).length
|
|
382
|
+
? `{ ...output, ${gqlArgs
|
|
383
|
+
.filter((prop) => prop.isInputArgSubfield)
|
|
384
|
+
.map((prop) => prop.name)
|
|
385
|
+
.join(",")} }`
|
|
386
|
+
: "output"}${gqlArgs.filter((prop) => !prop.isInputArgSubfield).length
|
|
387
|
+
? `, ${gqlArgs
|
|
388
|
+
.filter((prop) => !prop.isInputArgSubfield)
|
|
389
|
+
.map((arg) => arg.name)
|
|
390
|
+
.join(",")}`
|
|
391
|
+
: ""} },
|
|
392
|
+
});
|
|
393
|
+
if (!event.navigatingBack) {
|
|
394
|
+
const id = mutationResponse?.${createMutationType.name}.id;
|
|
395
|
+
if (id) {
|
|
396
|
+
setTimeout(() => {
|
|
397
|
+
stackSwitchApi.activatePage(\`edit\`, id);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
`
|
|
402
|
+
: ""}
|
|
403
|
+
${mode == "all" ? `}` : ""}
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
${hooksCode}
|
|
407
|
+
|
|
408
|
+
${editMode
|
|
409
|
+
? ` if (error) throw error;
|
|
410
|
+
|
|
411
|
+
if (loading) {
|
|
412
|
+
return <Loading behavior="fillPageHeight" />;
|
|
413
|
+
}`
|
|
414
|
+
: ``}
|
|
415
|
+
|
|
416
|
+
return (
|
|
417
|
+
<FinalForm<FormValues>
|
|
418
|
+
apiRef={formApiRef}
|
|
419
|
+
onSubmit={handleSubmit}
|
|
420
|
+
mode=${mode == "all" ? `{mode}` : editMode ? `"edit"` : `"add"`}
|
|
421
|
+
initialValues={initialValues}
|
|
422
|
+
initialValuesEqual={isEqual} //required to compare block data correctly
|
|
423
|
+
subscription={{ ${finalFormSubscription.length ? finalFormSubscription.map((field) => `${field}: true`).join(", ") : ``} }}
|
|
424
|
+
>
|
|
425
|
+
{(${finalFormRenderProps.length ? `{${finalFormRenderProps.join(", ")}}` : ``}) => (
|
|
426
|
+
${editMode ? `<>` : ``}
|
|
427
|
+
${editMode ? `{saveConflict.dialogs}` : ``}
|
|
428
|
+
<>
|
|
429
|
+
${fieldsCode}
|
|
430
|
+
</>
|
|
431
|
+
${editMode ? `</>` : ``}
|
|
432
|
+
)}
|
|
433
|
+
</FinalForm>
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
`;
|
|
438
|
+
return {
|
|
439
|
+
code,
|
|
440
|
+
gqlDocuments,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
exports.generateForm = generateForm;
|
|
444
|
+
/**
|
|
445
|
+
* Checks if the provided form config is valid.
|
|
446
|
+
*
|
|
447
|
+
* Examples of invalid configs:
|
|
448
|
+
* - The "id" field is not read-only
|
|
449
|
+
*
|
|
450
|
+
* @param config The form config to check.
|
|
451
|
+
* @throws Will throw an error if the provided config is invalid.
|
|
452
|
+
*/
|
|
453
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
454
|
+
function assertValidConfig(config) {
|
|
455
|
+
function validateFields(fields) {
|
|
456
|
+
for (const field of fields) {
|
|
457
|
+
if ((0, generate_command_1.isFormFieldConfig)(field)) {
|
|
458
|
+
if (field.name === "id" && !field.readOnly) {
|
|
459
|
+
throw new Error(`Invalid form config: the "id" field must be read-only`);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
else if ((0, generate_command_1.isFormLayoutConfig)(field)) {
|
|
463
|
+
validateFields(field.fields);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
validateFields(config.fields);
|
|
468
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type IntrospectionQuery } from "graphql";
|
|
2
|
+
import { type FormConfig, type FormFieldConfig } from "../generate-command";
|
|
3
|
+
import { type GenerateFieldsReturn } from "./generateFields";
|
|
4
|
+
export declare function generateFormField({ gqlIntrospection, baseOutputFilename, config, formConfig, gqlType, namePrefix, }: {
|
|
5
|
+
gqlIntrospection: IntrospectionQuery;
|
|
6
|
+
baseOutputFilename: string;
|
|
7
|
+
config: FormFieldConfig<any>;
|
|
8
|
+
formFragmentName: string;
|
|
9
|
+
formConfig: FormConfig<any>;
|
|
10
|
+
gqlType: string;
|
|
11
|
+
namePrefix?: string;
|
|
12
|
+
}): GenerateFieldsReturn;
|