@firecms/collection_editor 3.0.0-alpha.5 → 3.0.0-alpha.51

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 (140) hide show
  1. package/dist/ConfigControllerProvider.d.ts +36 -0
  2. package/dist/index.d.ts +11 -0
  3. package/dist/index.es.js +6995 -0
  4. package/dist/index.es.js.map +1 -0
  5. package/dist/index.umd.js +4 -0
  6. package/dist/index.umd.js.map +1 -0
  7. package/dist/types/collection_editor_controller.d.ts +35 -0
  8. package/dist/types/collection_inference.d.ts +2 -0
  9. package/dist/types/config_controller.d.ts +41 -0
  10. package/dist/types/config_permissions.d.ts +19 -0
  11. package/dist/types/persisted_collection.d.ts +6 -0
  12. package/dist/ui/CollectionViewHeaderAction.d.ts +10 -0
  13. package/dist/ui/EditorCollectionAction.d.ts +2 -0
  14. package/dist/ui/HomePageEditorCollectionAction.d.ts +2 -0
  15. package/dist/ui/MissingReferenceWidget.d.ts +3 -0
  16. package/dist/ui/NewCollectionCard.d.ts +2 -0
  17. package/dist/ui/PropertyAddColumnComponent.d.ts +6 -0
  18. package/dist/ui/RootCollectionSuggestions.d.ts +1 -0
  19. package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +9 -0
  20. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +38 -0
  21. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +15 -0
  22. package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +20 -0
  23. package/dist/ui/collection_editor/CollectionYupValidation.d.ts +14 -0
  24. package/dist/ui/collection_editor/EntityCustomViewsSelectDialog.d.ts +4 -0
  25. package/dist/ui/collection_editor/EnumForm.d.ts +13 -0
  26. package/dist/ui/collection_editor/GetCodeDialog.d.ts +5 -0
  27. package/dist/ui/collection_editor/PropertyEditView.d.ts +40 -0
  28. package/dist/ui/collection_editor/PropertyFieldPreview.d.ts +15 -0
  29. package/dist/ui/collection_editor/PropertySelectItem.d.ts +8 -0
  30. package/dist/ui/collection_editor/PropertyTree.d.ts +32 -0
  31. package/dist/ui/collection_editor/SelectIcons.d.ts +6 -0
  32. package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +12 -0
  33. package/dist/ui/collection_editor/UnsavedChangesDialog.d.ts +9 -0
  34. package/dist/ui/collection_editor/import/CollectionEditorImportDataPreview.d.ts +7 -0
  35. package/dist/ui/collection_editor/import/CollectionEditorImportMapping.d.ts +7 -0
  36. package/dist/ui/collection_editor/import/clean_import_data.d.ts +7 -0
  37. package/dist/ui/collection_editor/properties/BlockPropertyField.d.ts +8 -0
  38. package/dist/ui/collection_editor/properties/BooleanPropertyField.d.ts +3 -0
  39. package/dist/ui/collection_editor/properties/CommonPropertyFields.d.ts +10 -0
  40. package/dist/ui/collection_editor/properties/DateTimePropertyField.d.ts +3 -0
  41. package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +8 -0
  42. package/dist/ui/collection_editor/properties/FieldHelperView.d.ts +4 -0
  43. package/dist/ui/collection_editor/properties/KeyValuePropertyField.d.ts +3 -0
  44. package/dist/ui/collection_editor/properties/MapPropertyField.d.ts +8 -0
  45. package/dist/ui/collection_editor/properties/NumberPropertyField.d.ts +3 -0
  46. package/dist/ui/collection_editor/properties/ReferencePropertyField.d.ts +13 -0
  47. package/dist/ui/collection_editor/properties/RepeatPropertyField.d.ts +10 -0
  48. package/dist/ui/collection_editor/properties/StoragePropertyField.d.ts +5 -0
  49. package/dist/ui/collection_editor/properties/StringPropertyField.d.ts +5 -0
  50. package/dist/ui/collection_editor/properties/UrlPropertyField.d.ts +4 -0
  51. package/dist/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.d.ts +3 -0
  52. package/dist/ui/collection_editor/properties/validation/ArrayPropertyValidation.d.ts +5 -0
  53. package/dist/ui/collection_editor/properties/validation/GeneralPropertyValidation.d.ts +4 -0
  54. package/dist/ui/collection_editor/properties/validation/NumberPropertyValidation.d.ts +3 -0
  55. package/dist/ui/collection_editor/properties/validation/StringPropertyValidation.d.ts +11 -0
  56. package/dist/ui/collection_editor/properties/validation/ValidationPanel.d.ts +2 -0
  57. package/dist/ui/collection_editor/templates/blog_template.d.ts +2 -0
  58. package/dist/ui/collection_editor/templates/products_template.d.ts +2 -0
  59. package/dist/ui/collection_editor/templates/users_template.d.ts +2 -0
  60. package/dist/ui/collection_editor/util.d.ts +4 -0
  61. package/dist/ui/collection_editor/utils/strings.d.ts +1 -0
  62. package/dist/ui/collection_editor/utils/supported_fields.d.ts +3 -0
  63. package/dist/ui/collection_editor/utils/update_property_for_widget.d.ts +2 -0
  64. package/dist/ui/collection_editor/utils/useTraceUpdate.d.ts +1 -0
  65. package/dist/useCollectionEditorController.d.ts +6 -0
  66. package/dist/useCollectionEditorPlugin.d.ts +45 -0
  67. package/dist/useCollectionsConfigController.d.ts +6 -0
  68. package/dist/utils/arrays.d.ts +1 -0
  69. package/dist/utils/entities.d.ts +3 -0
  70. package/dist/utils/icons.d.ts +1 -0
  71. package/dist/utils/synonyms.d.ts +1951 -0
  72. package/package.json +26 -23
  73. package/src/ConfigControllerProvider.tsx +321 -0
  74. package/src/index.ts +35 -0
  75. package/src/types/collection_editor_controller.tsx +42 -0
  76. package/src/types/collection_inference.ts +3 -0
  77. package/src/types/config_controller.tsx +50 -0
  78. package/src/types/config_permissions.ts +20 -0
  79. package/src/types/persisted_collection.ts +9 -0
  80. package/src/ui/CollectionViewHeaderAction.tsx +42 -0
  81. package/src/ui/EditorCollectionAction.tsx +95 -0
  82. package/src/ui/HomePageEditorCollectionAction.tsx +88 -0
  83. package/src/ui/MissingReferenceWidget.tsx +34 -0
  84. package/src/ui/NewCollectionCard.tsx +46 -0
  85. package/src/ui/PropertyAddColumnComponent.tsx +41 -0
  86. package/src/ui/RootCollectionSuggestions.tsx +62 -0
  87. package/src/ui/collection_editor/CollectionDetailsForm.tsx +353 -0
  88. package/src/ui/collection_editor/CollectionEditorDialog.tsx +744 -0
  89. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +212 -0
  90. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +480 -0
  91. package/src/ui/collection_editor/CollectionYupValidation.tsx +7 -0
  92. package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +36 -0
  93. package/src/ui/collection_editor/EnumForm.tsx +356 -0
  94. package/src/ui/collection_editor/GetCodeDialog.tsx +118 -0
  95. package/src/ui/collection_editor/PropertyEditView.tsx +565 -0
  96. package/src/ui/collection_editor/PropertyFieldPreview.tsx +201 -0
  97. package/src/ui/collection_editor/PropertySelectItem.tsx +31 -0
  98. package/src/ui/collection_editor/PropertyTree.tsx +238 -0
  99. package/src/ui/collection_editor/SelectIcons.tsx +72 -0
  100. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +252 -0
  101. package/src/ui/collection_editor/UnsavedChangesDialog.tsx +47 -0
  102. package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +37 -0
  103. package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +275 -0
  104. package/src/ui/collection_editor/import/clean_import_data.ts +53 -0
  105. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +134 -0
  106. package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +36 -0
  107. package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +111 -0
  108. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +86 -0
  109. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +116 -0
  110. package/src/ui/collection_editor/properties/FieldHelperView.tsx +13 -0
  111. package/src/ui/collection_editor/properties/KeyValuePropertyField.tsx +20 -0
  112. package/src/ui/collection_editor/properties/MapPropertyField.tsx +157 -0
  113. package/src/ui/collection_editor/properties/NumberPropertyField.tsx +38 -0
  114. package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +184 -0
  115. package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +107 -0
  116. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +194 -0
  117. package/src/ui/collection_editor/properties/StringPropertyField.tsx +79 -0
  118. package/src/ui/collection_editor/properties/UrlPropertyField.tsx +89 -0
  119. package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +36 -0
  120. package/src/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +50 -0
  121. package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +49 -0
  122. package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +99 -0
  123. package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +131 -0
  124. package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +28 -0
  125. package/src/ui/collection_editor/templates/blog_template.ts +115 -0
  126. package/src/ui/collection_editor/templates/products_template.ts +88 -0
  127. package/src/ui/collection_editor/templates/users_template.ts +34 -0
  128. package/src/ui/collection_editor/util.ts +21 -0
  129. package/src/ui/collection_editor/utils/strings.ts +8 -0
  130. package/src/ui/collection_editor/utils/supported_fields.tsx +29 -0
  131. package/src/ui/collection_editor/utils/update_property_for_widget.ts +271 -0
  132. package/src/ui/collection_editor/utils/useTraceUpdate.tsx +23 -0
  133. package/src/useCollectionEditorController.tsx +9 -0
  134. package/src/useCollectionEditorPlugin.tsx +128 -0
  135. package/src/useCollectionsConfigController.tsx +9 -0
  136. package/src/utils/arrays.ts +3 -0
  137. package/src/utils/entities.ts +38 -0
  138. package/src/utils/icons.ts +17 -0
  139. package/src/utils/synonyms.ts +1952 -0
  140. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,353 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import {
3
+ Autocomplete,
4
+ AutocompleteItem,
5
+ BooleanSwitchWithLabel,
6
+ Chip,
7
+ cn,
8
+ Container,
9
+ DebouncedTextField,
10
+ Dialog,
11
+ EntityCollection,
12
+ ExpandablePanel,
13
+ getIconForView,
14
+ IconButton,
15
+ Select,
16
+ SelectItem,
17
+ SettingsIcon,
18
+ singular,
19
+ TextField,
20
+ Tooltip,
21
+ toSnakeCase,
22
+ Typography,
23
+ useAutoComplete
24
+ } from "@firecms/core";
25
+ import { Field, getIn, useFormikContext } from "formik";
26
+
27
+ //@ts-ignore
28
+ import { SearchIcons } from "./SelectIcons";
29
+ import { FieldHelperView } from "./properties/FieldHelperView";
30
+
31
+ export function CollectionDetailsForm({
32
+ isNewCollection,
33
+ reservedGroups,
34
+ existingPaths,
35
+ existingIds,
36
+ groups,
37
+ parentCollection
38
+ }: {
39
+ isNewCollection: boolean,
40
+ reservedGroups?: string[];
41
+ existingPaths?: string[];
42
+ existingIds?: string[];
43
+ groups: string[] | null;
44
+ parentCollection?: EntityCollection;
45
+ }) {
46
+
47
+ const groupRef = React.useRef<HTMLInputElement>(null);
48
+ const {
49
+ values,
50
+ setFieldValue,
51
+ handleChange,
52
+ touched,
53
+ errors,
54
+ setFieldTouched,
55
+ isSubmitting,
56
+ submitCount
57
+ } = useFormikContext<EntityCollection>();
58
+
59
+ const [iconDialogOpen, setIconDialogOpen] = useState(false);
60
+ const [advancedPanelExpanded, setAdvancedPanelExpanded] = useState(false);
61
+
62
+ const updateName = (name: string) => {
63
+ setFieldValue("name", name);
64
+
65
+ const pathTouched = getIn(touched, "path");
66
+ if (!pathTouched && isNewCollection && name) {
67
+ setFieldValue("path", toSnakeCase(name));
68
+ }
69
+
70
+ const idTouched = getIn(touched, "id");
71
+ if (!idTouched && isNewCollection && name) {
72
+ setFieldValue("id", toSnakeCase(name));
73
+ }
74
+
75
+ const singularNameTouched = getIn(touched, "singularName");
76
+ if (!singularNameTouched && isNewCollection && name) {
77
+ setFieldValue("singularName", singular(name))
78
+ }
79
+
80
+ };
81
+
82
+ useEffect(() => {
83
+ if (errors.id) {
84
+ setAdvancedPanelExpanded(true);
85
+ }
86
+ }, [errors.id]);
87
+
88
+ const collectionIcon = getIconForView(values);
89
+
90
+ const groupOptions = groups?.filter((group) => !reservedGroups?.includes(group));
91
+
92
+ const {
93
+ inputFocused,
94
+ autoCompleteOpen,
95
+ setAutoCompleteOpen
96
+ } = useAutoComplete({
97
+ ref: groupRef
98
+ });
99
+
100
+ const isSubcollection = !!parentCollection;
101
+
102
+ let customIdValue: "true" | "false" | "optional" | "code_defined" | undefined;
103
+ if (customIdValue) {
104
+ if (typeof values.customId === "object") {
105
+ customIdValue = "code_defined";
106
+ } else if (values.customId === true) {
107
+ customIdValue = "true";
108
+ } else if (values.customId === false) {
109
+ customIdValue = "false";
110
+ } else if (values.customId === "optional") {
111
+ customIdValue = "optional";
112
+ }
113
+ }
114
+ return (
115
+ <div className={"overflow-auto my-auto"}>
116
+ <Container maxWidth={"4xl"} className={"flex flex-col gap-4 p-8 m-auto"}>
117
+
118
+ <div>
119
+ <div
120
+ className="flex flex-row py-2 pt-3 items-center">
121
+ <Typography variant={!isNewCollection ? "h5" : "h4"} className={"flex-grow"}>
122
+ {isNewCollection ? "New collection" : `${values?.name} collection`}
123
+ </Typography>
124
+ <Tooltip title={"Change icon"}>
125
+ <IconButton
126
+ shape={"square"}
127
+ onClick={() => setIconDialogOpen(true)}>
128
+ {collectionIcon}
129
+ </IconButton>
130
+ </Tooltip>
131
+ </div>
132
+
133
+ {parentCollection && <Chip colorScheme={"tealDarker"}>
134
+ <Typography variant={"caption"}>
135
+ This is a subcollection of <b>{parentCollection.name}</b>
136
+ </Typography>
137
+ </Chip>}
138
+
139
+ </div>
140
+ <div className={"grid grid-cols-12 gap-4"}>
141
+
142
+ <div className={"col-span-12"}>
143
+ <TextField
144
+ value={values.name ?? ""}
145
+ onChange={(e: any) => updateName(e.target.value)}
146
+ label={"Name"}
147
+ required
148
+ error={touched.name && Boolean(errors.name)}/>
149
+ <FieldHelperView error={touched.name && Boolean(errors.name)}>
150
+ {touched.name && Boolean(errors.name) ? errors.name : "Name of in this collection, usually a plural name (e.g. Products)"}
151
+ </FieldHelperView>
152
+ </div>
153
+
154
+ <div className={cn("col-span-12 ", isSubcollection ? "" : "sm:col-span-8")}>
155
+ <Field name={"path"}
156
+ as={DebouncedTextField}
157
+ label={"Path"}
158
+ disabled={!isNewCollection}
159
+ required
160
+ error={touched.path && Boolean(errors.path)}/>
161
+
162
+ <FieldHelperView error={touched.path && Boolean(errors.path)}>
163
+ {touched.path && Boolean(errors.path) ? errors.path : "Path that this collection is stored in, in the database"}
164
+ </FieldHelperView>
165
+
166
+ </div>
167
+
168
+ {!isSubcollection && <div className={"col-span-12 sm:col-span-4 relative"}>
169
+
170
+ <TextField error={touched.group && Boolean(errors.group)}
171
+ disabled={isSubmitting}
172
+ value={values.group ?? ""}
173
+ autoComplete="off"
174
+ onChange={(event) => setFieldValue("group", event.target.value)}
175
+ name={"group"}
176
+ inputRef={groupRef}
177
+ label="Group"/>
178
+ <Autocomplete
179
+ open={autoCompleteOpen && (groupOptions ?? []).length > 0}
180
+ setOpen={setAutoCompleteOpen}>
181
+ {groupOptions?.map((group, index) => {
182
+ return <AutocompleteItem
183
+ key={index + "_" + group}
184
+ onClick={() => {
185
+ setAutoCompleteOpen(false);
186
+ setFieldValue("group", group ?? null);
187
+ }}
188
+ >
189
+ <div className={"flex-grow"}>
190
+ {group}
191
+ </div>
192
+ </AutocompleteItem>;
193
+ })}
194
+ </Autocomplete>
195
+ <FieldHelperView>
196
+ {touched.group && Boolean(errors.group) ? errors.group : "Group of the collection"}
197
+ </FieldHelperView>
198
+ </div>}
199
+
200
+ <div className={"col-span-12"}>
201
+ <ExpandablePanel
202
+ expanded={advancedPanelExpanded}
203
+ onExpandedChange={setAdvancedPanelExpanded}
204
+ title={
205
+ <div className="flex flex-row text-gray-500">
206
+ <SettingsIcon/>
207
+ <Typography variant={"subtitle2"}
208
+ className="ml-2">
209
+ Advanced
210
+ </Typography>
211
+ </div>}
212
+ initiallyExpanded={false}>
213
+ <div className={"grid grid-cols-12 gap-4 p-4"}>
214
+ <div className={"col-span-12"}>
215
+ <TextField
216
+ error={touched.singularName && Boolean(errors.singularName)}
217
+ id={"singularName"}
218
+ aria-describedby={"singularName-helper"}
219
+ onChange={(e) => {
220
+ setFieldTouched("singularName", true);
221
+ return handleChange(e);
222
+ }}
223
+ value={values.singularName ?? ""}
224
+ label={"Singular name"}/>
225
+ <FieldHelperView error={touched.singularName && Boolean(errors.singularName)}>
226
+ {touched.singularName && Boolean(errors.singularName) ? errors.singularName : "Optionally define a singular name for your entities"}
227
+ </FieldHelperView>
228
+ </div>
229
+ <div className={"col-span-12"}>
230
+ <TextField
231
+ error={touched.description && Boolean(errors.description)}
232
+ id="description"
233
+ value={values.description ?? ""}
234
+ onChange={handleChange}
235
+ multiline
236
+ rows={2}
237
+ aria-describedby="description-helper-text"
238
+ label="Description"
239
+ />
240
+ <FieldHelperView error={touched.description && Boolean(errors.description)}>
241
+ {touched.description && Boolean(errors.description) ? errors.description : "Description of the collection, you can use markdown"}
242
+ </FieldHelperView>
243
+ </div>
244
+
245
+ <div className={"col-span-12"}>
246
+ <Field name={"id"}
247
+ as={DebouncedTextField}
248
+ disabled={!isNewCollection}
249
+ label={"Collection id"}
250
+ error={touched.id && Boolean(errors.id)}/>
251
+ <FieldHelperView error={touched.id && Boolean(errors.id)}>
252
+ {touched.id && Boolean(errors.id) ? errors.id : "This id identifies this collection"}
253
+ </FieldHelperView>
254
+ </div>
255
+
256
+ <div className={"col-span-12"}>
257
+ <Select
258
+ name="defaultSize"
259
+ label="Default row size"
260
+ position={"item-aligned"}
261
+ onChange={handleChange}
262
+ value={values.defaultSize ?? ""}
263
+ renderValue={(value: any) => value.toUpperCase()}
264
+ >
265
+ {["xs", "s", "m", "l", "xl"].map((value) => (
266
+ <SelectItem
267
+ key={`size-select-${value}`}
268
+ value={value}>
269
+ {value.toUpperCase()}
270
+ </SelectItem>
271
+ ))}
272
+ </Select>
273
+ </div>
274
+ <div className={"col-span-12"}>
275
+ <Select
276
+ name="customId"
277
+ label="Data IDs generation"
278
+ position={"item-aligned"}
279
+ disabled={customIdValue === "code_defined"}
280
+ onValueChange={(v) => {
281
+ if (v === "code_defined")
282
+ throw new Error("This should not happen");
283
+ else if (v === "true")
284
+ setFieldValue("customId", true);
285
+ else if (v === "false")
286
+ setFieldValue("customId", false);
287
+ else if (v === "optional")
288
+ setFieldValue("customId", "optional");
289
+ }}
290
+ value={customIdValue ?? ""}
291
+ renderValue={(value: any) => {
292
+ if (value === "code_defined")
293
+ return "Code defined";
294
+ else if (value === "true")
295
+ return "Users must define an ID";
296
+ else if (value === "optional")
297
+ return "Users can define an ID, but it is not required";
298
+ else
299
+ return "Document ID is generated automatically";
300
+ }}
301
+ >
302
+ <SelectItem value={"false"}>
303
+ Document ID is generated automatically
304
+ </SelectItem>
305
+ <SelectItem value={"true"}>
306
+ Users must define an ID
307
+ </SelectItem>
308
+ <SelectItem value={"optional"}>
309
+ Users can define an ID, but it is not required
310
+ </SelectItem>
311
+ </Select>
312
+ </div>
313
+ <div className={"col-span-12"}>
314
+ <BooleanSwitchWithLabel
315
+ position={"start"}
316
+ label="Collection group"
317
+ onValueChange={(v) => setFieldValue("collectionGroup", v)}
318
+ value={values.collectionGroup ?? false}
319
+ />
320
+ <FieldHelperView>
321
+ A collection group consists of all collections with the same ID. This allows you
322
+ to query over multiple collections at once.
323
+ </FieldHelperView>
324
+ </div>
325
+ </div>
326
+ </ExpandablePanel>
327
+
328
+ </div>
329
+
330
+ </div>
331
+
332
+ <div style={{ height: "52px" }}/>
333
+
334
+ <Dialog
335
+ open={iconDialogOpen}
336
+ onOpenChange={setIconDialogOpen}
337
+ maxWidth={"xl"}
338
+ fullWidth
339
+ >
340
+ <div className={"p-4 overflow-auto min-h-[200px]"}>
341
+ <SearchIcons selectedIcon={values.icon}
342
+ onIconSelected={(icon: string) => {
343
+ setIconDialogOpen(false);
344
+ setFieldValue("icon", icon);
345
+ }}/>
346
+ </div>
347
+
348
+ </Dialog>
349
+
350
+ </Container>
351
+ </div>
352
+ );
353
+ }