@comet/admin-generator 8.0.0-beta.4 → 8.0.0-beta.6
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/bin/admin-generator.js +3 -0
- package/lib/commands/generate/config/parseConfig.d.ts +1 -0
- package/lib/commands/generate/config/parseConfig.js +72 -0
- package/lib/commands/generate/config/transformConfig.d.ts +1 -0
- package/lib/commands/generate/config/transformConfig.js +239 -0
- package/lib/commands/generate/generate-command.d.ts +13 -14
- package/lib/commands/generate/generate-command.js +6 -6
- package/lib/commands/generate/generateForm/generateForm.js +51 -37
- package/lib/commands/generate/generateForm/generateFormField.js +1 -1
- package/lib/commands/generate/generateGrid/generateGrid.js +142 -54
- package/lib/commands/generate/generateGrid/generateGridToolbar.js +1 -1
- package/lib/commands/generate/utils/writeGenerated.js +63 -24
- package/package.json +11 -13
- package/lib/commands/generate/utils/tsMorphHelper.d.ts +0 -4
- package/lib/commands/generate/utils/tsMorphHelper.js +0 -216
|
@@ -115,7 +115,7 @@ const getValueOptionsLabelData = (messageId, label) => {
|
|
|
115
115
|
};
|
|
116
116
|
};
|
|
117
117
|
function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntrospection, }, config) {
|
|
118
|
-
var _a, _b;
|
|
118
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
119
119
|
const gqlType = config.gqlType;
|
|
120
120
|
const gqlTypePlural = (0, pluralize_1.plural)(gqlType);
|
|
121
121
|
//const title = config.title ?? camelCaseToHumanReadable(gqlType);
|
|
@@ -123,8 +123,58 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
123
123
|
const instanceGqlTypePlural = gqlTypePlural[0].toLowerCase() + gqlTypePlural.substring(1);
|
|
124
124
|
const gridQuery = config.query ? config.query : instanceGqlType != instanceGqlTypePlural ? instanceGqlTypePlural : `${instanceGqlTypePlural}List`;
|
|
125
125
|
const gqlDocuments = {};
|
|
126
|
-
const imports = [
|
|
127
|
-
|
|
126
|
+
const imports = [
|
|
127
|
+
{ name: "FormattedMessage", importPath: "react-intl" },
|
|
128
|
+
{ name: "FormattedNumber", importPath: "react-intl" },
|
|
129
|
+
{ name: "useIntl", importPath: "react-intl" },
|
|
130
|
+
{ name: "ReactNode", importPath: "react" },
|
|
131
|
+
{ name: "gql", importPath: "@apollo/client" },
|
|
132
|
+
{ name: "useApolloClient", importPath: "@apollo/client" },
|
|
133
|
+
{ name: "useQuery", importPath: "@apollo/client" },
|
|
134
|
+
{ name: "Button", importPath: "@comet/admin" },
|
|
135
|
+
{ name: "CrudContextMenu", importPath: "@comet/admin" },
|
|
136
|
+
{ name: "CrudMoreActionsMenu", importPath: "@comet/admin" },
|
|
137
|
+
{ name: "DataGridToolbar", importPath: "@comet/admin" },
|
|
138
|
+
{ name: "ExportApi", importPath: "@comet/admin" },
|
|
139
|
+
{ name: "filterByFragment", importPath: "@comet/admin" },
|
|
140
|
+
{ name: "GridFilterButton", importPath: "@comet/admin" },
|
|
141
|
+
{ name: "GridCellContent", importPath: "@comet/admin" },
|
|
142
|
+
{ name: "GridColDef", importPath: "@comet/admin" },
|
|
143
|
+
{ name: "dataGridDateTimeColumn", importPath: "@comet/admin" },
|
|
144
|
+
{ name: "dataGridDateColumn", importPath: "@comet/admin" },
|
|
145
|
+
{ name: "renderStaticSelectCell", importPath: "@comet/admin" },
|
|
146
|
+
{ name: "messages", importPath: "@comet/admin" },
|
|
147
|
+
{ name: "muiGridFilterToGql", importPath: "@comet/admin" },
|
|
148
|
+
{ name: "muiGridSortToGql", importPath: "@comet/admin" },
|
|
149
|
+
{ name: "StackLink", importPath: "@comet/admin" },
|
|
150
|
+
{ name: "FillSpace", importPath: "@comet/admin" },
|
|
151
|
+
{ name: "Tooltip", importPath: "@comet/admin" },
|
|
152
|
+
{ name: "useBufferedRowCount", importPath: "@comet/admin" },
|
|
153
|
+
{ name: "useDataGridExcelExport", importPath: "@comet/admin" },
|
|
154
|
+
{ name: "useDataGridRemote", importPath: "@comet/admin" },
|
|
155
|
+
{ name: "usePersistentColumnState", importPath: "@comet/admin" },
|
|
156
|
+
{ name: "BlockPreviewContent", importPath: "@comet/cms-admin" },
|
|
157
|
+
{ name: "useContentScope", importPath: "@comet/cms-admin" },
|
|
158
|
+
{ name: "Alert", importPath: "@mui/material" },
|
|
159
|
+
{ name: "Box", importPath: "@mui/material" },
|
|
160
|
+
{ name: "IconButton", importPath: "@mui/material" },
|
|
161
|
+
{ name: "Typography", importPath: "@mui/material" },
|
|
162
|
+
{ name: "useTheme", importPath: "@mui/material" },
|
|
163
|
+
{ name: "Menu", importPath: "@mui/material" },
|
|
164
|
+
{ name: "MenuItem", importPath: "@mui/material" },
|
|
165
|
+
{ name: "ListItemIcon", importPath: "@mui/material" },
|
|
166
|
+
{ name: "ListItemText", importPath: "@mui/material" },
|
|
167
|
+
{ name: "CircularProgress", importPath: "@mui/material" },
|
|
168
|
+
{ name: "DataGridPro", importPath: "@mui/x-data-grid-pro" },
|
|
169
|
+
{ name: "GridLogicOperator", importPath: "@mui/x-data-grid-pro" },
|
|
170
|
+
{ name: "GridRenderCellParams", importPath: "@mui/x-data-grid-pro" },
|
|
171
|
+
{ name: "GridSlotsComponent", importPath: "@mui/x-data-grid-pro" },
|
|
172
|
+
{ name: "GridToolbarProps", importPath: "@mui/x-data-grid-pro" },
|
|
173
|
+
{ name: "GridColumnHeaderTitle", importPath: "@mui/x-data-grid-pro" },
|
|
174
|
+
{ name: "GridToolbarQuickFilter", importPath: "@mui/x-data-grid-pro" },
|
|
175
|
+
{ name: "GridRowOrderChangeParams", importPath: "@mui/x-data-grid-pro" },
|
|
176
|
+
];
|
|
177
|
+
const iconsToImport = ["Add", "Edit", "Info", "Excel"];
|
|
128
178
|
const props = [];
|
|
129
179
|
const fieldList = (0, generateGqlFieldList_1.generateGqlFieldList)({
|
|
130
180
|
columns: config.columns.filter((column) => {
|
|
@@ -161,12 +211,29 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
161
211
|
});
|
|
162
212
|
const gridQueryType = (0, findQueryType_1.findQueryTypeOrThrow)(gridQuery, gqlIntrospection);
|
|
163
213
|
const createMutationType = (0, findMutationType_1.findMutationType)(`create${gqlType}`, gqlIntrospection);
|
|
214
|
+
const updateMutationType = (0, findMutationType_1.findMutationType)(`update${gqlType}`, gqlIntrospection);
|
|
164
215
|
const hasDeleteMutation = !!(0, findMutationType_1.findMutationType)(`delete${gqlType}`, gqlIntrospection);
|
|
165
216
|
const hasCreateMutation = !!createMutationType;
|
|
217
|
+
const hasUpdateMutation = !!updateMutationType;
|
|
166
218
|
const allowCopyPaste = (typeof config.copyPaste === "undefined" || config.copyPaste === true) && !config.readOnly && hasCreateMutation;
|
|
167
219
|
const allowAdding = (typeof config.add === "undefined" || config.add === true) && !config.readOnly;
|
|
168
220
|
const allowEditing = (typeof config.edit === "undefined" || config.edit === true) && !config.readOnly;
|
|
169
221
|
const allowDeleting = (typeof config.delete === "undefined" || config.delete === true) && !config.readOnly && hasDeleteMutation;
|
|
222
|
+
const allowRowReordering = typeof ((_a = config.rowReordering) === null || _a === void 0 ? void 0 : _a.enabled) !== "undefined" && ((_b = config.rowReordering) === null || _b === void 0 ? void 0 : _b.enabled) && hasUpdateMutation;
|
|
223
|
+
const updateInputArg = updateMutationType === null || updateMutationType === void 0 ? void 0 : updateMutationType.args.find((arg) => arg.name === "input");
|
|
224
|
+
if (allowRowReordering && updateInputArg) {
|
|
225
|
+
const inputType = (0, findInputObjectType_1.findInputObjectType)(updateInputArg, gqlIntrospection);
|
|
226
|
+
if (!inputType)
|
|
227
|
+
throw new Error("Can't find update input type");
|
|
228
|
+
if (!((_c = inputType.inputFields) === null || _c === void 0 ? void 0 : _c.find((field) => field.name === "position"))) {
|
|
229
|
+
throw new Error("Position field is needed when using 'rowReordering'");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const hasRowReorderingOnDragField = allowRowReordering && typeof ((_d = config.rowReordering) === null || _d === void 0 ? void 0 : _d.dragPreviewField) !== "undefined";
|
|
233
|
+
if (hasRowReorderingOnDragField &&
|
|
234
|
+
!config.columns.find((column) => { var _a; return column.type !== "actions" && (column === null || column === void 0 ? void 0 : column.name) === ((_a = config.rowReordering) === null || _a === void 0 ? void 0 : _a.dragPreviewField); })) {
|
|
235
|
+
throw new Error(`rowReorderingOnDragField '${(_e = config.rowReordering) === null || _e === void 0 ? void 0 : _e.dragPreviewField}' must exist in columns`);
|
|
236
|
+
}
|
|
170
237
|
const forwardRowAction = allowEditing && config.rowActionProp;
|
|
171
238
|
const showActionsColumn = allowCopyPaste || allowEditing || allowDeleting;
|
|
172
239
|
const showCrudContextMenuInActionsColumn = allowCopyPaste || allowDeleting;
|
|
@@ -175,9 +242,9 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
175
242
|
const { imports: forwardedGqlArgsImports, props: forwardedGqlArgsProps, gqlArgs, } = (0, getForwardedGqlArgs_1.getForwardedGqlArgs)([gridQueryType, ...(createMutationType ? [createMutationType] : [])]);
|
|
176
243
|
imports.push(...forwardedGqlArgsImports);
|
|
177
244
|
props.push(...forwardedGqlArgsProps);
|
|
178
|
-
const renderToolbar = (
|
|
245
|
+
const renderToolbar = (_f = config.toolbar) !== null && _f !== void 0 ? _f : true;
|
|
179
246
|
const filterArg = gridQueryType.args.find((arg) => arg.name === "filter");
|
|
180
|
-
const hasFilter = !!filterArg && renderToolbar;
|
|
247
|
+
const hasFilter = !!filterArg && renderToolbar && !allowRowReordering;
|
|
181
248
|
let hasFilterProp = false;
|
|
182
249
|
let filterFields = [];
|
|
183
250
|
if (filterArg) {
|
|
@@ -223,8 +290,11 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
223
290
|
if (!sortInputEnum)
|
|
224
291
|
throw new Error("Can't find sortInputEnum");
|
|
225
292
|
sortFields = sortInputEnum.enumValues.map((v) => v.name.replace(/_/g, "."));
|
|
293
|
+
if (allowRowReordering && !sortFields.includes("position")) {
|
|
294
|
+
throw new Error("Sort argument must include 'position' field for row reordering");
|
|
295
|
+
}
|
|
226
296
|
}
|
|
227
|
-
const hasSearch = gridQueryType.args.some((arg) => arg.name === "search");
|
|
297
|
+
const hasSearch = gridQueryType.args.some((arg) => arg.name === "search") && !allowRowReordering;
|
|
228
298
|
const hasScope = gridQueryType.args.some((arg) => arg.name === "scope");
|
|
229
299
|
const schemaEntity = gqlIntrospection.__schema.types.find((type) => type.kind === "OBJECT" && type.name === gqlType);
|
|
230
300
|
if (!schemaEntity)
|
|
@@ -247,7 +317,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
247
317
|
return true;
|
|
248
318
|
});
|
|
249
319
|
const actionsColumnConfig = config.columns.find((column) => column.type === "actions");
|
|
250
|
-
const
|
|
320
|
+
const _j = actionsColumnConfig !== null && actionsColumnConfig !== void 0 ? actionsColumnConfig : {}, { component: actionsColumnComponent, type: actionsColumnType, headerName: actionsColumnHeaderName, pinned: actionsColumnPinned = "right", width: actionsColumnWidth = defaultActionsColumnWidth, visible: actionsColumnVisible = undefined } = _j, restActionsColumnConfig = __rest(_j, ["component", "type", "headerName", "pinned", "width", "visible"]);
|
|
251
321
|
if (actionsColumnComponent) {
|
|
252
322
|
if (!(0, runtimeTypeGuards_1.isGeneratorConfigImport)(actionsColumnComponent)) {
|
|
253
323
|
throw new Error("Unsupported actionsColumnComponent, only imports are supported");
|
|
@@ -281,6 +351,12 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
281
351
|
}
|
|
282
352
|
else if (type == "number") {
|
|
283
353
|
gridType = "number";
|
|
354
|
+
const defaultDecimals = column.currency ? 2 : 0;
|
|
355
|
+
const decimals = typeof column.decimals === "number" ? column.decimals : defaultDecimals;
|
|
356
|
+
const currencyProps = column.currency ? `style="currency" currency="${column.currency}"` : "";
|
|
357
|
+
renderCell = `({ value }) => {
|
|
358
|
+
return (typeof value === "number") ? <FormattedNumber value={value} ${currencyProps} minimumFractionDigits={${decimals}} maximumFractionDigits={${decimals}} /> : "";
|
|
359
|
+
}`;
|
|
284
360
|
}
|
|
285
361
|
else if (type == "boolean") {
|
|
286
362
|
gridType = "boolean";
|
|
@@ -325,10 +401,10 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
325
401
|
throw new Error(`Enum type not found`);
|
|
326
402
|
}
|
|
327
403
|
const values = columnValues.map((value) => {
|
|
328
|
-
if (typeof value === "string") {
|
|
404
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
329
405
|
return {
|
|
330
406
|
value,
|
|
331
|
-
label: (0, camelCaseToHumanReadable_1.camelCaseToHumanReadable)(value),
|
|
407
|
+
label: (0, camelCaseToHumanReadable_1.camelCaseToHumanReadable)(value.toString()),
|
|
332
408
|
};
|
|
333
409
|
}
|
|
334
410
|
else {
|
|
@@ -337,7 +413,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
337
413
|
});
|
|
338
414
|
const valueOptions = `[${values
|
|
339
415
|
.map(({ value, label }) => {
|
|
340
|
-
const labelData = getValueOptionsLabelData(`${instanceGqlType}.${name}.${value.charAt(0).toLowerCase() + value.slice(1)}`, label);
|
|
416
|
+
const labelData = getValueOptionsLabelData(`${instanceGqlType}.${name}.${value.toString().charAt(0).toLowerCase() + value.toString().slice(1)}`, label);
|
|
341
417
|
return `{
|
|
342
418
|
value: ${JSON.stringify(value)},
|
|
343
419
|
label: ${labelData.textLabel},
|
|
@@ -419,7 +495,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
419
495
|
createMutationInputFields = inputType.inputFields.filter((field) => fieldsToLoad.some((gridColumnField) => gridColumnField.name == field.name));
|
|
420
496
|
}
|
|
421
497
|
}
|
|
422
|
-
const fragmentName = (
|
|
498
|
+
const fragmentName = (_g = config.fragmentName) !== null && _g !== void 0 ? _g : `${gqlTypePlural}Form`;
|
|
423
499
|
if (forwardRowAction) {
|
|
424
500
|
props.push({
|
|
425
501
|
name: "rowAction",
|
|
@@ -458,7 +534,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
458
534
|
: ""}
|
|
459
535
|
${config.initialFilter
|
|
460
536
|
? `initialFilter:{ ${config.initialFilter.linkOperator
|
|
461
|
-
? `linkOperator:
|
|
537
|
+
? `linkOperator: GridLogicOperator.${config.initialFilter.linkOperator === "or" ? "Or" : "And"},`
|
|
462
538
|
: ""}
|
|
463
539
|
items: [${config.initialFilter.items
|
|
464
540
|
.map((item) => {
|
|
@@ -469,47 +545,17 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
469
545
|
${config.queryParamsPrefix ? `queryParamsPrefix: "${config.queryParamsPrefix}",` : ""}
|
|
470
546
|
}`
|
|
471
547
|
: "";
|
|
472
|
-
const code = `import {
|
|
473
|
-
import {
|
|
474
|
-
Button,
|
|
475
|
-
CrudContextMenu,
|
|
476
|
-
CrudMoreActionsMenu,
|
|
477
|
-
DataGridToolbar,
|
|
478
|
-
ExportApi,
|
|
479
|
-
filterByFragment,
|
|
480
|
-
GridFilterButton,
|
|
481
|
-
GridCellContent,
|
|
482
|
-
GridColDef,
|
|
483
|
-
dataGridDateTimeColumn,
|
|
484
|
-
dataGridDateColumn,
|
|
485
|
-
renderStaticSelectCell,
|
|
486
|
-
messages,
|
|
487
|
-
muiGridFilterToGql,
|
|
488
|
-
muiGridSortToGql,
|
|
489
|
-
StackLink,
|
|
490
|
-
FillSpace,
|
|
491
|
-
Tooltip,
|
|
492
|
-
useBufferedRowCount,
|
|
493
|
-
useDataGridExcelExport,
|
|
494
|
-
useDataGridRemote,
|
|
495
|
-
usePersistentColumnState,
|
|
496
|
-
} from "@comet/admin";
|
|
497
|
-
import { Add as AddIcon, Edit, Info, MoreVertical, Excel } from "@comet/admin-icons";
|
|
498
|
-
import { BlockPreviewContent } from "@comet/cms-admin";
|
|
499
|
-
import { Alert, Box, IconButton, Typography, useTheme, Menu, MenuItem, ListItemIcon, ListItemText, CircularProgress } from "@mui/material";
|
|
500
|
-
import { DataGridPro, GridLinkOperator, GridRenderCellParams, GridSlotsComponent, GridToolbarProps, GridColumnHeaderTitle, GridToolbarQuickFilter } from "@mui/x-data-grid-pro";
|
|
501
|
-
import { useContentScope } from "@src/common/ContentScopeProvider";
|
|
502
|
-
import {
|
|
548
|
+
const code = `import {
|
|
503
549
|
GQL${gqlTypePlural}GridQuery,
|
|
504
550
|
GQL${gqlTypePlural}GridQueryVariables,
|
|
505
551
|
GQL${fragmentName}Fragment,
|
|
506
552
|
GQLCreate${gqlType}Mutation,
|
|
507
553
|
GQLCreate${gqlType}MutationVariables,
|
|
554
|
+
GQLUpdate${gqlType}PositionMutation,
|
|
555
|
+
GQLUpdate${gqlType}PositionMutationVariables,
|
|
508
556
|
GQLDelete${gqlType}Mutation,
|
|
509
557
|
GQLDelete${gqlType}MutationVariables
|
|
510
558
|
} from "./${baseOutputFilename}.generated";
|
|
511
|
-
import { ReactNode } from "react";
|
|
512
|
-
import { FormattedMessage, FormattedNumber, useIntl } from "react-intl";
|
|
513
559
|
${(0, generateImportsCode_1.generateImportsCode)(imports)}
|
|
514
560
|
|
|
515
561
|
const ${instanceGqlTypePlural}Fragment = gql\`
|
|
@@ -545,6 +591,17 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
545
591
|
\${${instanceGqlTypePlural}Fragment}
|
|
546
592
|
\`;
|
|
547
593
|
|
|
594
|
+
${allowRowReordering
|
|
595
|
+
? `const update${gqlType}PositionMutation = gql\`
|
|
596
|
+
mutation Update${gqlType}Position($id: ID!, $input: ${gqlType}UpdateInput!) {
|
|
597
|
+
update${gqlType}(id: $id, input: $input) {
|
|
598
|
+
id
|
|
599
|
+
position
|
|
600
|
+
updatedAt
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
\`;`
|
|
604
|
+
: ""}
|
|
548
605
|
|
|
549
606
|
${allowDeleting
|
|
550
607
|
? `const delete${gqlType}Mutation = gql\`
|
|
@@ -600,6 +657,8 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
600
657
|
${hasScope ? `const { scope } = useContentScope();` : ""}
|
|
601
658
|
${gridNeedsTheme ? `const theme = useTheme();` : ""}
|
|
602
659
|
|
|
660
|
+
${generateHandleRowOrderChange(allowRowReordering, gqlType, instanceGqlTypePlural)}
|
|
661
|
+
|
|
603
662
|
const columns: GridColDef<GQL${fragmentName}Fragment>[] = [
|
|
604
663
|
${gridColumnFields
|
|
605
664
|
.map((column) => {
|
|
@@ -630,7 +689,7 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
630
689
|
<Tooltip
|
|
631
690
|
title={<FormattedMessage id="${instanceGqlType}.${column.name}.tooltip" defaultMessage="${column.headerInfoTooltip}" />}
|
|
632
691
|
>
|
|
633
|
-
<
|
|
692
|
+
<InfoIcon sx={{ marginLeft: 1 }} />
|
|
634
693
|
</Tooltip>
|
|
635
694
|
</>
|
|
636
695
|
)`
|
|
@@ -639,8 +698,8 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
639
698
|
? `intl.formatMessage({ id: "${instanceGqlType}.${column.name}", defaultMessage: "${column.headerName || (0, camelCaseToHumanReadable_1.camelCaseToHumanReadable)(column.name)}" })`
|
|
640
699
|
: undefined,
|
|
641
700
|
type: column.gridType ? `"${column.gridType}"` : undefined,
|
|
642
|
-
filterable: !column.filterOperators && !filterFields.includes(column.name) ? `false` : undefined,
|
|
643
|
-
sortable: !sortFields.includes(column.name) ? `false` : undefined,
|
|
701
|
+
filterable: (!column.filterOperators && !filterFields.includes(column.name)) || allowRowReordering ? `false` : undefined,
|
|
702
|
+
sortable: !sortFields.includes(column.name) || allowRowReordering ? `false` : undefined,
|
|
644
703
|
valueGetter: column.valueGetter,
|
|
645
704
|
valueFormatter: column.valueFormatter,
|
|
646
705
|
valueOptions: column.valueOptions,
|
|
@@ -753,17 +812,20 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
753
812
|
: []
|
|
754
813
|
: []),
|
|
755
814
|
...(hasSearch ? ["search: gqlSearch"] : []),
|
|
756
|
-
...
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
815
|
+
...(!allowRowReordering
|
|
816
|
+
? [
|
|
817
|
+
`offset: dataGridProps.paginationModel.page * dataGridProps.paginationModel.pageSize`,
|
|
818
|
+
`limit: dataGridProps.paginationModel.pageSize`,
|
|
819
|
+
`sort: muiGridSortToGql(dataGridProps.sortModel)`,
|
|
820
|
+
]
|
|
821
|
+
: // TODO: offset and limit should not be necessary for row reordering but not yet possible to disable in the api generator
|
|
822
|
+
[`offset: 0`, `limit: 100`, `sort: { field: "position", direction: "ASC" }`]),
|
|
761
823
|
].join(", ")}
|
|
762
824
|
},
|
|
763
825
|
});
|
|
764
826
|
const rowCount = useBufferedRowCount(data?.${gridQuery}.totalCount);
|
|
765
827
|
if (error) throw error;
|
|
766
|
-
const rows = data?.${gridQuery}.nodes ?? [];
|
|
828
|
+
const rows = ${!allowRowReordering ? `data?.${gridQuery}.nodes` : generateRowReorderingRows(gridQuery, fieldList, (_h = config.rowReordering) === null || _h === void 0 ? void 0 : _h.dragPreviewField)} ?? [];
|
|
767
829
|
|
|
768
830
|
${generateGridExportApi(config.excelExport, gqlTypePlural, gridQuery)}
|
|
769
831
|
|
|
@@ -779,6 +841,11 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
779
841
|
toolbar: ${gridToolbarComponentName} as GridSlotsComponent["toolbar"],
|
|
780
842
|
}}
|
|
781
843
|
${getDataGridSlotProps(gridToolbarComponentName, forwardToolbarAction, config.excelExport)}`
|
|
844
|
+
: ""}
|
|
845
|
+
${allowRowReordering
|
|
846
|
+
? `rowReordering
|
|
847
|
+
onRowOrderChange={handleRowOrderChange}
|
|
848
|
+
hideFooterPagination`
|
|
782
849
|
: ""}
|
|
783
850
|
/>
|
|
784
851
|
);
|
|
@@ -789,6 +856,14 @@ function generateGrid({ exportName, baseOutputFilename, targetDirectory, gqlIntr
|
|
|
789
856
|
gqlDocuments,
|
|
790
857
|
};
|
|
791
858
|
}
|
|
859
|
+
const generateRowReorderingRows = (gridQuery, fieldList, dragPreviewField) => {
|
|
860
|
+
const fields = fieldList.split(" ");
|
|
861
|
+
const reorderField = dragPreviewField || fields.find((field) => field === "title" || field === "name") || "id";
|
|
862
|
+
return `data?.${gridQuery}.nodes.map((node) => ({
|
|
863
|
+
...node,
|
|
864
|
+
__reorder__: node.${reorderField}
|
|
865
|
+
}))`;
|
|
866
|
+
};
|
|
792
867
|
const getDefaultActionsColumnWidth = (showCrudContextMenu, showEdit) => {
|
|
793
868
|
let numberOfActions = 0;
|
|
794
869
|
if (showCrudContextMenu) {
|
|
@@ -830,3 +905,16 @@ const generateGridExportApi = (excelExport, gqlTypePlural, gridQuery) => {
|
|
|
830
905
|
},
|
|
831
906
|
});`;
|
|
832
907
|
};
|
|
908
|
+
const generateHandleRowOrderChange = (allowRowReordering, gqlType, instanceGqlTypePlural) => {
|
|
909
|
+
if (!allowRowReordering) {
|
|
910
|
+
return "";
|
|
911
|
+
}
|
|
912
|
+
return `const handleRowOrderChange = async ({ row: { id }, targetIndex }: GridRowOrderChangeParams) => {
|
|
913
|
+
await client.mutate<GQLUpdate${gqlType}PositionMutation, GQLUpdate${gqlType}PositionMutationVariables>({
|
|
914
|
+
mutation: update${gqlType}PositionMutation,
|
|
915
|
+
variables: { id, input: { position: targetIndex + 1 } },
|
|
916
|
+
awaitRefetchQueries: true,
|
|
917
|
+
refetchQueries: [${instanceGqlTypePlural}Query]
|
|
918
|
+
});
|
|
919
|
+
};`;
|
|
920
|
+
};
|
|
@@ -59,7 +59,7 @@ const renderToolbarActions = ({ forwardToolbarAction, addItemText, excelExport,
|
|
|
59
59
|
${excelExport
|
|
60
60
|
? `{
|
|
61
61
|
label: <FormattedMessage {...messages.downloadAsExcel} />,
|
|
62
|
-
icon: exportApi.loading ? <CircularProgress size={20} /> : <
|
|
62
|
+
icon: exportApi.loading ? <CircularProgress size={20} /> : <ExcelIcon />,
|
|
63
63
|
onClick: () => exportApi.exportGrid(),
|
|
64
64
|
disabled: exportApi.loading,
|
|
65
65
|
}`
|
|
@@ -46,39 +46,78 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.writeGenerated = writeGenerated;
|
|
49
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
50
|
-
const eslint_1 = require("eslint");
|
|
51
49
|
const fs_1 = require("fs");
|
|
52
50
|
const path = __importStar(require("path"));
|
|
51
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
53
52
|
function writeGenerated(filePath, contents) {
|
|
54
53
|
return __awaiter(this, void 0, void 0, function* () {
|
|
55
54
|
const header = `// This file has been generated by comet admin-generator.
|
|
56
55
|
// You may choose to use this file as scaffold by moving this file out of generated folder and removing this comment.
|
|
57
56
|
`;
|
|
58
57
|
yield fs_1.promises.mkdir(path.dirname(filePath), { recursive: true });
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
const sourceFile = typescript_1.default.createSourceFile(filePath, header + contents, typescript_1.default.ScriptTarget.Latest, true, typescript_1.default.ScriptKind.TSX);
|
|
59
|
+
const result = typescript_1.default.transform(sourceFile, [removeUnusedImports()]);
|
|
60
|
+
const printer = typescript_1.default.createPrinter({
|
|
61
|
+
newLine: typescript_1.default.NewLineKind.LineFeed,
|
|
62
|
+
removeComments: false,
|
|
62
63
|
});
|
|
63
|
-
|
|
64
|
-
yield fs_1.promises.writeFile(filePath,
|
|
65
|
-
const lintResult = yield eslint.lintText(header + contents, {
|
|
66
|
-
filePath,
|
|
67
|
-
});
|
|
68
|
-
if (lintResult[0].errorCount > 0 || lintResult[0].fatalErrorCount > 0) {
|
|
69
|
-
const errorMessage = lintResult[0].messages
|
|
70
|
-
.map((message) => {
|
|
71
|
-
return message.message;
|
|
72
|
-
})
|
|
73
|
-
.join(".");
|
|
74
|
-
console.error(chalk_1.default.red(`Linting error in ${filePath}: \n${errorMessage}`));
|
|
75
|
-
}
|
|
76
|
-
else if (lintResult[0].output != null) {
|
|
77
|
-
yield fs_1.promises.writeFile(filePath, lintResult[0].output);
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
console.error(chalk_1.default.red("No output from linting"));
|
|
81
|
-
}
|
|
64
|
+
const prettyCode = printer.printFile(result.transformed[0]).replace(/gql `/g, "gql`");
|
|
65
|
+
yield fs_1.promises.writeFile(filePath, prettyCode);
|
|
82
66
|
console.log(`generated ${filePath}`);
|
|
83
67
|
});
|
|
84
68
|
}
|
|
69
|
+
// copy from @comet/api-generator
|
|
70
|
+
function removeUnusedImports() {
|
|
71
|
+
return (context) => {
|
|
72
|
+
function visit(sourceFile) {
|
|
73
|
+
const usedIdentifiers = new Set();
|
|
74
|
+
// Step 1: Collect all used identifiers
|
|
75
|
+
function collectUsage(node) {
|
|
76
|
+
if (typescript_1.default.isIdentifier(node)) {
|
|
77
|
+
usedIdentifiers.add(node.text);
|
|
78
|
+
}
|
|
79
|
+
else if (typescript_1.default.isImportDeclaration(node)) {
|
|
80
|
+
// Skip import declarations (those identifiers are not usages)
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
typescript_1.default.forEachChild(node, collectUsage);
|
|
84
|
+
}
|
|
85
|
+
typescript_1.default.forEachChild(sourceFile, collectUsage);
|
|
86
|
+
// Step 2: Visit and update the import declarations
|
|
87
|
+
function visitor(node) {
|
|
88
|
+
if (typescript_1.default.isImportDeclaration(node) && node.importClause) {
|
|
89
|
+
const { name, namedBindings } = node.importClause;
|
|
90
|
+
const updatedBindings = [];
|
|
91
|
+
if (name && usedIdentifiers.has(name.text)) {
|
|
92
|
+
// default import is used
|
|
93
|
+
}
|
|
94
|
+
else if (name) {
|
|
95
|
+
// default import is unused
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
if (namedBindings && typescript_1.default.isNamedImports(namedBindings)) {
|
|
99
|
+
for (const specifier of namedBindings.elements) {
|
|
100
|
+
const importName = specifier.name.text;
|
|
101
|
+
if (usedIdentifiers.has(importName)) {
|
|
102
|
+
updatedBindings.push(specifier);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (updatedBindings.length === 0 && !name) {
|
|
106
|
+
// nothing left in this import
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
return typescript_1.default.factory.updateImportDeclaration(node, node.modifiers, typescript_1.default.factory.updateImportClause(node.importClause, node.importClause.isTypeOnly, name, updatedBindings.length > 0 ? typescript_1.default.factory.updateNamedImports(namedBindings, updatedBindings) : undefined), node.moduleSpecifier, node.assertClause);
|
|
110
|
+
}
|
|
111
|
+
if (!namedBindings && !name) {
|
|
112
|
+
// empty import, probably a side-effect import
|
|
113
|
+
return node;
|
|
114
|
+
}
|
|
115
|
+
return node;
|
|
116
|
+
}
|
|
117
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
118
|
+
}
|
|
119
|
+
return typescript_1.default.visitNode(sourceFile, visitor);
|
|
120
|
+
}
|
|
121
|
+
return (sourceFile) => visit(sourceFile);
|
|
122
|
+
};
|
|
123
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@comet/admin-generator",
|
|
3
|
-
"version": "8.0.0-beta.
|
|
3
|
+
"version": "8.0.0-beta.6",
|
|
4
4
|
"repository": {
|
|
5
5
|
"directory": "packages/admin/admin-generator",
|
|
6
6
|
"type": "git",
|
|
@@ -19,24 +19,22 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@graphql-tools/graphql-file-loader": "^7.5.17",
|
|
21
21
|
"@graphql-tools/load": "^7.8.14",
|
|
22
|
-
"chalk": "^5.4.1",
|
|
23
22
|
"change-case": "^4.1.2",
|
|
24
23
|
"commander": "^9.5.0",
|
|
25
24
|
"glob": "^10.4.5",
|
|
26
25
|
"graphql": "^16.10.0",
|
|
27
26
|
"object-path": "^0.11.8",
|
|
28
27
|
"pluralize": "^8.0.0",
|
|
29
|
-
"ts-morph": "^25.0.1",
|
|
30
28
|
"ts-node": "^10.9.2"
|
|
31
29
|
},
|
|
32
30
|
"devDependencies": {
|
|
33
|
-
"@mui/material": "^7.
|
|
34
|
-
"@mui/x-data-grid": "^7.
|
|
31
|
+
"@mui/material": "^7.1.0",
|
|
32
|
+
"@mui/x-data-grid": "^7.29.4",
|
|
35
33
|
"@types/jest": "^29.5.14",
|
|
36
|
-
"@types/node": "^22.
|
|
34
|
+
"@types/node": "^22.15.34",
|
|
37
35
|
"@types/object-path": "^0.11.4",
|
|
38
36
|
"@types/pluralize": "^0.0.33",
|
|
39
|
-
"@types/react": "^18.3.
|
|
37
|
+
"@types/react": "^18.3.22",
|
|
40
38
|
"eslint": "^9.22.0",
|
|
41
39
|
"final-form": "^4.20.10",
|
|
42
40
|
"jest": "^29.7.0",
|
|
@@ -47,10 +45,10 @@
|
|
|
47
45
|
"rimraf": "^6.0.1",
|
|
48
46
|
"ts-jest": "^29.2.6",
|
|
49
47
|
"typescript": "^5.7.3",
|
|
50
|
-
"@comet/admin": "8.0.0-beta.
|
|
51
|
-
"@comet/admin-icons": "8.0.0-beta.
|
|
52
|
-
"@comet/cms-admin": "8.0.0-beta.
|
|
53
|
-
"@comet/eslint-config": "8.0.0-beta.
|
|
48
|
+
"@comet/admin": "8.0.0-beta.6",
|
|
49
|
+
"@comet/admin-icons": "8.0.0-beta.6",
|
|
50
|
+
"@comet/cms-admin": "8.0.0-beta.6",
|
|
51
|
+
"@comet/eslint-config": "8.0.0-beta.6"
|
|
54
52
|
},
|
|
55
53
|
"engines": {
|
|
56
54
|
"node": ">=22.0.0"
|
|
@@ -67,7 +65,7 @@
|
|
|
67
65
|
"lint:eslint": "eslint --max-warnings 0 src/ **/*.json --no-warn-ignored",
|
|
68
66
|
"lint:prettier": "npx prettier --check './**/*.{js,json,md,yml,yaml}'",
|
|
69
67
|
"lint:tsc": "tsc",
|
|
70
|
-
"test": "jest --passWithNoTests",
|
|
71
|
-
"test:watch": "jest --watch"
|
|
68
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests",
|
|
69
|
+
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
|
|
72
70
|
}
|
|
73
71
|
}
|