@firecms/collection_editor 3.0.1 → 3.1.0-canary.1df3b2c

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.
Files changed (90) hide show
  1. package/dist/ConfigControllerProvider.d.ts +6 -0
  2. package/dist/api/generateCollectionApi.d.ts +71 -0
  3. package/dist/api/index.d.ts +1 -0
  4. package/dist/index.d.ts +5 -1
  5. package/dist/index.es.js +9418 -5587
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +9413 -5582
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/types/collection_editor_controller.d.ts +14 -0
  10. package/dist/types/collection_inference.d.ts +8 -2
  11. package/dist/types/config_controller.d.ts +23 -2
  12. package/dist/ui/AddKanbanColumnAction.d.ts +11 -0
  13. package/dist/ui/KanbanSetupAction.d.ts +10 -0
  14. package/dist/ui/collection_editor/AICollectionGeneratorPopover.d.ts +33 -0
  15. package/dist/ui/collection_editor/AIModifiedPathsContext.d.ts +20 -0
  16. package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +2 -3
  17. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +20 -0
  18. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +3 -1
  19. package/dist/ui/collection_editor/CollectionJsonImportDialog.d.ts +7 -0
  20. package/dist/ui/collection_editor/CollectionYupValidation.d.ts +9 -13
  21. package/dist/ui/collection_editor/DisplaySettingsForm.d.ts +3 -0
  22. package/dist/ui/collection_editor/EntityActionsEditTab.d.ts +2 -1
  23. package/dist/ui/collection_editor/ExtendSettingsForm.d.ts +14 -0
  24. package/dist/ui/collection_editor/GeneralSettingsForm.d.ts +7 -0
  25. package/dist/ui/collection_editor/KanbanConfigSection.d.ts +4 -0
  26. package/dist/ui/collection_editor/PropertyEditView.d.ts +6 -1
  27. package/dist/ui/collection_editor/PropertyTree.d.ts +2 -1
  28. package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +2 -1
  29. package/dist/ui/collection_editor/ViewModeSwitch.d.ts +6 -0
  30. package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +2 -1
  31. package/dist/ui/collection_editor/properties/conditions/ConditionsEditor.d.ts +10 -0
  32. package/dist/ui/collection_editor/properties/conditions/ConditionsPanel.d.ts +2 -0
  33. package/dist/ui/collection_editor/properties/conditions/EnumConditionsEditor.d.ts +6 -0
  34. package/dist/ui/collection_editor/properties/conditions/index.d.ts +6 -0
  35. package/dist/ui/collection_editor/properties/conditions/property_paths.d.ts +19 -0
  36. package/dist/useCollectionEditorPlugin.d.ts +7 -1
  37. package/dist/utils/validateCollectionJson.d.ts +22 -0
  38. package/package.json +11 -11
  39. package/src/ConfigControllerProvider.tsx +81 -47
  40. package/src/api/generateCollectionApi.ts +119 -0
  41. package/src/api/index.ts +1 -0
  42. package/src/index.ts +28 -1
  43. package/src/types/collection_editor_controller.tsx +16 -3
  44. package/src/types/collection_inference.ts +15 -2
  45. package/src/types/config_controller.tsx +27 -2
  46. package/src/ui/AddKanbanColumnAction.tsx +203 -0
  47. package/src/ui/EditorCollectionActionStart.tsx +1 -2
  48. package/src/ui/HomePageEditorCollectionAction.tsx +41 -13
  49. package/src/ui/KanbanSetupAction.tsx +38 -0
  50. package/src/ui/MissingReferenceWidget.tsx +1 -1
  51. package/src/ui/NewCollectionButton.tsx +1 -1
  52. package/src/ui/PropertyAddColumnComponent.tsx +1 -1
  53. package/src/ui/collection_editor/AICollectionGeneratorPopover.tsx +225 -0
  54. package/src/ui/collection_editor/AIModifiedPathsContext.tsx +88 -0
  55. package/src/ui/collection_editor/CollectionDetailsForm.tsx +209 -257
  56. package/src/ui/collection_editor/CollectionEditorDialog.tsx +226 -167
  57. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +130 -67
  58. package/src/ui/collection_editor/CollectionJsonImportDialog.tsx +171 -0
  59. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +190 -91
  60. package/src/ui/collection_editor/DisplaySettingsForm.tsx +333 -0
  61. package/src/ui/collection_editor/EntityActionsEditTab.tsx +106 -96
  62. package/src/ui/collection_editor/EntityActionsSelectDialog.tsx +6 -7
  63. package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +1 -3
  64. package/src/ui/collection_editor/EnumForm.tsx +147 -100
  65. package/src/ui/collection_editor/ExtendSettingsForm.tsx +93 -0
  66. package/src/ui/collection_editor/GeneralSettingsForm.tsx +335 -0
  67. package/src/ui/collection_editor/GetCodeDialog.tsx +57 -36
  68. package/src/ui/collection_editor/KanbanConfigSection.tsx +207 -0
  69. package/src/ui/collection_editor/LayoutModeSwitch.tsx +22 -41
  70. package/src/ui/collection_editor/PropertyEditView.tsx +205 -141
  71. package/src/ui/collection_editor/PropertyFieldPreview.tsx +1 -1
  72. package/src/ui/collection_editor/PropertyTree.tsx +130 -58
  73. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +171 -162
  74. package/src/ui/collection_editor/UnsavedChangesDialog.tsx +0 -2
  75. package/src/ui/collection_editor/ViewModeSwitch.tsx +41 -0
  76. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +0 -2
  77. package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +1 -0
  78. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +117 -35
  79. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +28 -21
  80. package/src/ui/collection_editor/properties/MapPropertyField.tsx +0 -2
  81. package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +115 -39
  82. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +1 -1
  83. package/src/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +861 -0
  84. package/src/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +28 -0
  85. package/src/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +599 -0
  86. package/src/ui/collection_editor/properties/conditions/index.ts +6 -0
  87. package/src/ui/collection_editor/properties/conditions/property_paths.ts +92 -0
  88. package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -1
  89. package/src/useCollectionEditorPlugin.tsx +32 -17
  90. package/src/utils/validateCollectionJson.ts +380 -0
@@ -30,19 +30,21 @@ import { EntityCustomViewsSelectDialog } from "./EntityCustomViewsSelectDialog";
30
30
  import { useFormex } from "@firecms/formex";
31
31
 
32
32
  export function SubcollectionsEditTab({
33
- collection,
34
- parentCollection,
35
- configController,
36
- collectionInference,
37
- getUser,
38
- parentCollectionIds
39
- }: {
33
+ collection,
34
+ parentCollection,
35
+ configController,
36
+ collectionInference,
37
+ getUser,
38
+ parentCollectionIds,
39
+ embedded = false
40
+ }: {
40
41
  collection: PersistedCollection,
41
42
  parentCollection?: EntityCollection,
42
43
  configController: CollectionsConfigController;
43
44
  collectionInference?: CollectionInference;
44
45
  getUser?: (uid: string) => User | null;
45
46
  parentCollectionIds?: string[];
47
+ embedded?: boolean;
46
48
  }) {
47
49
 
48
50
  const { entityViews: contextEntityViews } = useCustomizationController();
@@ -68,177 +70,184 @@ export function SubcollectionsEditTab({
68
70
  const hardCodedEntityViews = collection.entityViews?.filter(e => typeof e !== "string") as EntityCustomView[] ?? [];
69
71
  const totalEntityViews = resolvedEntityViews.length + hardCodedEntityViews.length;
70
72
 
71
- return (
72
- <div className={"overflow-auto my-auto"}>
73
- <Container maxWidth={"2xl"} className={"flex flex-col gap-4 p-8 m-auto"}>
74
- <div className={"flex flex-col gap-16"}>
73
+ const content = (
74
+ <div className={"flex flex-col gap-16"}>
75
75
 
76
- <div className={"flex-grow flex flex-col gap-4 items-start"}>
77
- <Typography variant={"h5"}>
78
- Subcollections of {values.name}
79
- </Typography>
76
+ <div className={"flex-grow flex flex-col gap-4 items-start"}>
77
+ <Typography variant={"h6"}>
78
+ Subcollections of {values.name}
79
+ </Typography>
80
80
 
81
- <Paper className={"flex flex-col gap-4 p-2 w-full"}>
82
- {subcollections && subcollections.length > 0 && <Table>
83
- <TableBody>
84
- {subcollections.map((subcollection) => (
85
- <TableRow key={subcollection.path}
86
- onClick={() => setCurrentDialog({
87
- isNewCollection: false,
88
- editedCollectionId: subcollection.id
89
- })}>
90
- <TableCell
91
- align="left">
92
- <Typography variant={"subtitle2"} className={"flex-grow"}>
93
- {subcollection.name}
94
- </Typography>
95
- </TableCell>
96
- <TableCell
97
- align="right">
98
- <Tooltip title={"Remove"}
99
- asChild={true}>
100
- <IconButton size="small"
101
- onClick={(e) => {
102
- e.preventDefault();
103
- e.stopPropagation();
104
- setSubcollectionToDelete(subcollection.id);
105
- }}
106
- color="inherit">
107
- <DeleteIcon size={"small"}/>
108
- </IconButton>
109
- </Tooltip>
110
- </TableCell>
111
- </TableRow>
112
- ))}
113
- </TableBody>
114
- </Table>}
81
+ <Paper className={"flex flex-col gap-4 p-2 w-full"}>
82
+ {subcollections && subcollections.length > 0 && <Table>
83
+ <TableBody>
84
+ {subcollections.map((subcollection) => (
85
+ <TableRow key={subcollection.path}
86
+ onClick={() => setCurrentDialog({
87
+ isNewCollection: false,
88
+ editedCollectionId: subcollection.id
89
+ })}>
90
+ <TableCell
91
+ align="left">
92
+ <Typography variant={"subtitle2"} className={"flex-grow"}>
93
+ {subcollection.name}
94
+ </Typography>
95
+ </TableCell>
96
+ <TableCell
97
+ align="right">
98
+ <Tooltip title={"Remove"}
99
+ asChild={true}>
100
+ <IconButton size="small"
101
+ onClick={(e) => {
102
+ e.preventDefault();
103
+ e.stopPropagation();
104
+ setSubcollectionToDelete(subcollection.id);
105
+ }}
106
+ color="inherit">
107
+ <DeleteIcon size={"small"} />
108
+ </IconButton>
109
+ </Tooltip>
110
+ </TableCell>
111
+ </TableRow>
112
+ ))}
113
+ </TableBody>
114
+ </Table>}
115
115
 
116
- <Button
117
- onClick={() => {
118
- setCurrentDialog({
119
- isNewCollection: true
120
- });
121
- }}
122
- variant={"text"}
123
- startIcon={<AddIcon/>}>
124
- Add subcollection
125
- </Button>
116
+ <Button
117
+ onClick={() => {
118
+ setCurrentDialog({
119
+ isNewCollection: true
120
+ });
121
+ }}
122
+ startIcon={<AddIcon />}>
123
+ Add subcollection
124
+ </Button>
126
125
 
127
- </Paper>
126
+ </Paper>
128
127
 
129
- </div>
128
+ </div>
130
129
 
131
- <div className={"flex-grow flex flex-col gap-4 items-start"}>
132
- <Typography variant={"h5"}>
133
- Custom views
134
- </Typography>
130
+ <div className={"flex-grow flex flex-col gap-4 items-start"}>
131
+ <Typography variant={"h6"}>
132
+ Custom views
133
+ </Typography>
135
134
 
136
- {totalEntityViews === 0 &&
137
- <Alert action={<Button variant="text"
138
- size={"small"}
139
- href={"https://firecms.co/docs/cloud/quickstart"}
140
- component={"a"}
141
- rel="noopener noreferrer"
142
- target="_blank">More info</Button>}>
143
- Define your own custom views by uploading them with the CLI.
144
- </Alert>
145
- }
135
+ {totalEntityViews === 0 &&
136
+ <Alert action={<Button variant="text"
137
+ size={"small"}
138
+ href={"https://firecms.co/docs/cloud/quickstart"}
139
+ component={"a"}
140
+ rel="noopener noreferrer"
141
+ target="_blank">More info</Button>}>
142
+ Define your own custom views by uploading them with the CLI.
143
+ </Alert>
144
+ }
146
145
 
147
- {<>
148
- <Paper className={"flex flex-col gap-4 p-2 w-full"}>
149
- <Table>
150
- <TableBody>
151
- {resolvedEntityViews.map((view) => (
152
- <TableRow key={view.key}>
153
- <TableCell
154
- align="left">
155
- <Typography variant={"subtitle2"} className={"flex-grow"}>
156
- {view.name}
157
- </Typography>
158
- </TableCell>
159
- <TableCell
160
- align="right">
161
- <Tooltip title={"Remove"}
162
- asChild={true}>
163
- <IconButton size="small"
164
- onClick={(e) => {
165
- e.preventDefault();
166
- e.stopPropagation();
167
- setViewToDelete(view.key);
168
- }}
169
- color="inherit">
170
- <DeleteIcon size={"small"}/>
171
- </IconButton>
172
- </Tooltip>
173
- </TableCell>
174
- </TableRow>
175
- ))}
176
- {hardCodedEntityViews.map((view) => (
177
- <TableRow key={view.key}>
178
- <TableCell
179
- align="left">
180
- <Typography variant={"subtitle2"} className={"flex-grow"}>
181
- {view.name}
182
- </Typography>
183
- <Typography variant={"caption"} className={"flex-grow"}>
184
- This view is defined in code with
185
- key <code>{view.key}</code>
186
- </Typography>
187
- </TableCell>
188
- </TableRow>
189
- ))}
190
- </TableBody>
191
- </Table>
146
+ {<>
147
+ <Paper className={"flex flex-col gap-4 p-2 w-full"}>
148
+ <Table>
149
+ <TableBody>
150
+ {resolvedEntityViews.map((view) => (
151
+ <TableRow key={view.key}>
152
+ <TableCell
153
+ align="left">
154
+ <Typography variant={"subtitle2"} className={"flex-grow"}>
155
+ {view.name}
156
+ </Typography>
157
+ </TableCell>
158
+ <TableCell
159
+ align="right">
160
+ <Tooltip title={"Remove"}
161
+ asChild={true}>
162
+ <IconButton size="small"
163
+ onClick={(e) => {
164
+ e.preventDefault();
165
+ e.stopPropagation();
166
+ setViewToDelete(view.key);
167
+ }}
168
+ color="inherit">
169
+ <DeleteIcon size={"small"} />
170
+ </IconButton>
171
+ </Tooltip>
172
+ </TableCell>
173
+ </TableRow>
174
+ ))}
175
+ {hardCodedEntityViews.map((view) => (
176
+ <TableRow key={view.key}>
177
+ <TableCell
178
+ align="left">
179
+ <Typography variant={"subtitle2"} className={"flex-grow"}>
180
+ {view.name}
181
+ </Typography>
182
+ <Typography variant={"caption"} className={"flex-grow"}>
183
+ This view is defined in code with
184
+ key <code>{view.key}</code>
185
+ </Typography>
186
+ </TableCell>
187
+ </TableRow>
188
+ ))}
189
+ </TableBody>
190
+ </Table>
192
191
 
193
- <Button
194
- onClick={() => {
195
- setAddEntityViewDialogOpen(true);
196
- }}
197
- variant={"text"}
198
- startIcon={<AddIcon/>}>
199
- Add custom entity view
200
- </Button>
201
- </Paper>
192
+ <Button
193
+ onClick={() => {
194
+ setAddEntityViewDialogOpen(true);
195
+ }}
196
+ startIcon={<AddIcon />}>
197
+ Add custom entity view
198
+ </Button>
199
+ </Paper>
202
200
 
203
- </>}
201
+ </>}
204
202
 
205
203
 
206
- </div>
204
+ </div>
207
205
 
208
- </div>
209
- </Container>
206
+ </div>
207
+ );
210
208
 
211
- <div style={{ height: "52px" }}/>
209
+ return (
210
+ <>
211
+ {embedded ? (
212
+ content
213
+ ) : (
214
+ <div className={"overflow-auto my-auto"}>
215
+ <Container maxWidth={"2xl"} className={"flex flex-col gap-4 p-8 m-auto"}>
216
+ {content}
217
+ </Container>
218
+ <div style={{ height: "52px" }} />
219
+ </div>
220
+ )}
212
221
 
213
222
  {subcollectionToDelete &&
214
223
  <ConfirmationDialog open={Boolean(subcollectionToDelete)}
215
- onAccept={() => {
216
- const props = {
217
- id: subcollectionToDelete,
218
- parentCollectionIds: [...(parentCollectionIds ?? []), collection.id]
219
- };
220
- console.debug("Deleting subcollection", props)
221
- configController.deleteCollection(props).then(() => {
222
- setSubcollectionToDelete(undefined);
223
- setSubcollections(subcollections?.filter(e => e.id !== subcollectionToDelete))
224
- });
225
- }}
226
- onCancel={() => setSubcollectionToDelete(undefined)}
227
- title={<>Delete this subcollection?</>}
228
- body={<> This will <b>not
229
- delete any data</b>, only
230
- the collection in the CMS</>}/>}
224
+ onAccept={() => {
225
+ const props = {
226
+ id: subcollectionToDelete,
227
+ parentCollectionIds: [...(parentCollectionIds ?? []), collection.id]
228
+ };
229
+ console.debug("Deleting subcollection", props)
230
+ configController.deleteCollection(props).then(() => {
231
+ setSubcollectionToDelete(undefined);
232
+ setSubcollections(subcollections?.filter(e => e.id !== subcollectionToDelete))
233
+ });
234
+ }}
235
+ onCancel={() => setSubcollectionToDelete(undefined)}
236
+ title={<>Delete this subcollection?</>}
237
+ body={<> This will <b>not
238
+ delete any data</b>, only
239
+ the collection in the CMS</>} />}
231
240
  {viewToDelete &&
232
241
  <ConfirmationDialog open={Boolean(viewToDelete)}
233
- onAccept={() => {
234
- setFieldValue("entityViews", values.entityViews?.filter(e => e !== viewToDelete));
235
- setViewToDelete(undefined);
236
- }}
237
- onCancel={() => setViewToDelete(undefined)}
238
- title={<>Remove this view?</>}
239
- body={<>This will <b>not
240
- delete any data</b>, only
241
- the view in the CMS</>}/>}
242
+ onAccept={() => {
243
+ setFieldValue("entityViews", values.entityViews?.filter(e => e !== viewToDelete));
244
+ setViewToDelete(undefined);
245
+ }}
246
+ onCancel={() => setViewToDelete(undefined)}
247
+ title={<>Remove this view?</>}
248
+ body={<>This will <b>not
249
+ delete any data</b>, only
250
+ the view in the CMS</>} />}
242
251
 
243
252
  <CollectionEditorDialog
244
253
  open={Boolean(currentDialog)}
@@ -254,7 +263,7 @@ export function SubcollectionsEditTab({
254
263
  setSubcollections([...subcollections, updatedCollection]);
255
264
  }
256
265
  setCurrentDialog(undefined);
257
- }}/>
266
+ }} />
258
267
 
259
268
  <EntityCustomViewsSelectDialog
260
269
  open={addEntityViewDialogOpen}
@@ -263,7 +272,7 @@ export function SubcollectionsEditTab({
263
272
  setFieldValue("entityViews", [...(values.entityViews ?? []), selectedViewKey]);
264
273
  }
265
274
  setAddEntityViewDialogOpen(false);
266
- }}/>
267
- </div>
275
+ }} />
276
+ </>
268
277
  );
269
278
  }
@@ -38,10 +38,8 @@ export function UnsavedChangesDialog({
38
38
 
39
39
  <DialogActions>
40
40
  <Button variant="text"
41
- color={"primary"}
42
41
  onClick={handleCancel} autoFocus> Cancel </Button>
43
42
  <Button
44
- color={"primary"}
45
43
  onClick={handleOk}> Ok </Button>
46
44
  </DialogActions>
47
45
  </Dialog>
@@ -0,0 +1,41 @@
1
+ import { ViewMode } from "@firecms/core";
2
+ import { AppsIcon, cls, ListIcon, ToggleButtonGroup, Typography, ViewKanbanIcon } from "@firecms/ui";
3
+
4
+ export function ViewModeSwitch({
5
+ value,
6
+ onChange,
7
+ className
8
+ }: {
9
+ value: ViewMode;
10
+ onChange: (value: ViewMode) => void;
11
+ className?: string;
12
+ }) {
13
+
14
+ return <div className={cls(className)}>
15
+ <Typography variant={"label"} color={"secondary"} className={"ml-3.5"}>Default collection view</Typography>
16
+ <div className={"my-2"}>
17
+ <ToggleButtonGroup
18
+ value={value}
19
+ onValueChange={onChange}
20
+ options={[
21
+ {
22
+ value: "table",
23
+ label: "Table",
24
+ icon: <ListIcon />
25
+ },
26
+ {
27
+ value: "cards",
28
+ label: "Cards",
29
+ icon: <AppsIcon />
30
+ },
31
+ {
32
+ value: "kanban",
33
+ label: "Kanban",
34
+ icon: <ViewKanbanIcon />
35
+ }
36
+ ]}
37
+ />
38
+ </div>
39
+ <Typography variant={"caption"} color={"secondary"} className={"ml-3.5"}>Choose how entities should be displayed by default</Typography>
40
+ </div>
41
+ }
@@ -71,8 +71,6 @@ export function BlockPropertyField({
71
71
 
72
72
  const addChildButton = <Button
73
73
  autoFocus
74
- color="primary"
75
-
76
74
  onClick={() => setPropertyDialogOpen(true)}
77
75
  startIcon={<AddIcon/>}
78
76
  >
@@ -27,6 +27,7 @@ export function BooleanPropertyField({ disabled }: {
27
27
  name={"defaultValue"}>
28
28
  {({ field, form }: FormexFieldProps) => {
29
29
  return <SwitchControl
30
+ size={"medium"}
30
31
  label={defaultValue === null || defaultValue === undefined ? "Default value not set" : ("Default value is " + defaultValue.toString())}
31
32
  disabled={disabled}
32
33
  allowIndeterminate={true} field={field}