@firecms/collection_editor 3.0.1 → 3.1.0-canary.768c91f
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/dist/ConfigControllerProvider.d.ts +6 -0
- package/dist/api/generateCollectionApi.d.ts +71 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.es.js +9466 -5588
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +9461 -5583
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collection_editor_controller.d.ts +14 -0
- package/dist/types/collection_inference.d.ts +8 -2
- package/dist/types/config_controller.d.ts +23 -2
- package/dist/ui/AddKanbanColumnAction.d.ts +11 -0
- package/dist/ui/KanbanSetupAction.d.ts +10 -0
- package/dist/ui/collection_editor/AICollectionGeneratorPopover.d.ts +37 -0
- package/dist/ui/collection_editor/AIModifiedPathsContext.d.ts +20 -0
- package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +2 -3
- package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +24 -0
- package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +4 -1
- package/dist/ui/collection_editor/CollectionJsonImportDialog.d.ts +7 -0
- package/dist/ui/collection_editor/CollectionYupValidation.d.ts +9 -13
- package/dist/ui/collection_editor/DisplaySettingsForm.d.ts +3 -0
- package/dist/ui/collection_editor/EntityActionsEditTab.d.ts +2 -1
- package/dist/ui/collection_editor/ExtendSettingsForm.d.ts +14 -0
- package/dist/ui/collection_editor/GeneralSettingsForm.d.ts +7 -0
- package/dist/ui/collection_editor/KanbanConfigSection.d.ts +4 -0
- package/dist/ui/collection_editor/PropertyEditView.d.ts +6 -1
- package/dist/ui/collection_editor/PropertyTree.d.ts +2 -1
- package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +2 -1
- package/dist/ui/collection_editor/ViewModeSwitch.d.ts +6 -0
- package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +2 -1
- package/dist/ui/collection_editor/properties/conditions/ConditionsEditor.d.ts +10 -0
- package/dist/ui/collection_editor/properties/conditions/ConditionsPanel.d.ts +2 -0
- package/dist/ui/collection_editor/properties/conditions/EnumConditionsEditor.d.ts +6 -0
- package/dist/ui/collection_editor/properties/conditions/index.d.ts +6 -0
- package/dist/ui/collection_editor/properties/conditions/property_paths.d.ts +19 -0
- package/dist/useCollectionEditorPlugin.d.ts +7 -1
- package/dist/utils/validateCollectionJson.d.ts +22 -0
- package/package.json +15 -15
- package/src/ConfigControllerProvider.tsx +82 -47
- package/src/api/generateCollectionApi.ts +119 -0
- package/src/api/index.ts +1 -0
- package/src/index.ts +28 -1
- package/src/types/collection_editor_controller.tsx +16 -3
- package/src/types/collection_inference.ts +15 -2
- package/src/types/config_controller.tsx +27 -2
- package/src/ui/AddKanbanColumnAction.tsx +203 -0
- package/src/ui/EditorCollectionActionStart.tsx +1 -2
- package/src/ui/HomePageEditorCollectionAction.tsx +41 -13
- package/src/ui/KanbanSetupAction.tsx +38 -0
- package/src/ui/MissingReferenceWidget.tsx +1 -1
- package/src/ui/NewCollectionButton.tsx +1 -1
- package/src/ui/PropertyAddColumnComponent.tsx +1 -1
- package/src/ui/collection_editor/AICollectionGeneratorPopover.tsx +242 -0
- package/src/ui/collection_editor/AIModifiedPathsContext.tsx +88 -0
- package/src/ui/collection_editor/CollectionDetailsForm.tsx +212 -259
- package/src/ui/collection_editor/CollectionEditorDialog.tsx +237 -169
- package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +133 -67
- package/src/ui/collection_editor/CollectionJsonImportDialog.tsx +171 -0
- package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +190 -91
- package/src/ui/collection_editor/DisplaySettingsForm.tsx +333 -0
- package/src/ui/collection_editor/EntityActionsEditTab.tsx +106 -96
- package/src/ui/collection_editor/EntityActionsSelectDialog.tsx +6 -7
- package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +1 -3
- package/src/ui/collection_editor/EnumForm.tsx +147 -100
- package/src/ui/collection_editor/ExtendSettingsForm.tsx +93 -0
- package/src/ui/collection_editor/GeneralSettingsForm.tsx +337 -0
- package/src/ui/collection_editor/GetCodeDialog.tsx +57 -36
- package/src/ui/collection_editor/KanbanConfigSection.tsx +207 -0
- package/src/ui/collection_editor/LayoutModeSwitch.tsx +22 -41
- package/src/ui/collection_editor/PropertyEditView.tsx +206 -142
- package/src/ui/collection_editor/PropertyFieldPreview.tsx +1 -1
- package/src/ui/collection_editor/PropertyTree.tsx +130 -58
- package/src/ui/collection_editor/SubcollectionsEditTab.tsx +171 -162
- package/src/ui/collection_editor/UnsavedChangesDialog.tsx +0 -2
- package/src/ui/collection_editor/ViewModeSwitch.tsx +41 -0
- package/src/ui/collection_editor/properties/BlockPropertyField.tsx +0 -2
- package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +1 -0
- package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +117 -35
- package/src/ui/collection_editor/properties/EnumPropertyField.tsx +28 -21
- package/src/ui/collection_editor/properties/MapPropertyField.tsx +0 -2
- package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +115 -39
- package/src/ui/collection_editor/properties/StoragePropertyField.tsx +1 -1
- package/src/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +861 -0
- package/src/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +28 -0
- package/src/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +599 -0
- package/src/ui/collection_editor/properties/conditions/index.ts +6 -0
- package/src/ui/collection_editor/properties/conditions/property_paths.ts +92 -0
- package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -1
- package/src/useCollectionEditorPlugin.tsx +32 -17
- package/src/utils/validateCollectionJson.ts +380 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { EntityCollection, FieldCaption, IconForView, SearchIconsView, singular, toSnakeCase, } from "@firecms/core";
|
|
1
|
+
import React, { useMemo, useState } from "react";
|
|
2
|
+
import { EntityCollection, FieldCaption, getFieldConfig, IconForView, Property, PropertyConfigBadge, resolveCollection, SearchIconsView, singular, toSnakeCase, unslugify, useAuthController, useCustomizationController } from "@firecms/core";
|
|
3
3
|
import {
|
|
4
4
|
BooleanSwitchWithLabel,
|
|
5
5
|
Chip,
|
|
@@ -8,11 +8,10 @@ import {
|
|
|
8
8
|
Container,
|
|
9
9
|
DebouncedTextField,
|
|
10
10
|
Dialog,
|
|
11
|
-
|
|
11
|
+
HistoryIcon,
|
|
12
12
|
IconButton,
|
|
13
13
|
Select,
|
|
14
14
|
SelectItem,
|
|
15
|
-
SettingsIcon,
|
|
16
15
|
TextField,
|
|
17
16
|
Tooltip,
|
|
18
17
|
Typography,
|
|
@@ -22,16 +21,19 @@ import {
|
|
|
22
21
|
import { Field, getIn, useFormex } from "@firecms/formex";
|
|
23
22
|
import { useCollectionEditorController } from "../../useCollectionEditorController";
|
|
24
23
|
import { LayoutModeSwitch } from "./LayoutModeSwitch";
|
|
24
|
+
import { ViewModeSwitch } from "./ViewModeSwitch";
|
|
25
|
+
import { KanbanConfigSection } from "./KanbanConfigSection";
|
|
26
|
+
import { PropertyFormDialog } from "./PropertyEditView";
|
|
25
27
|
|
|
26
28
|
export function CollectionDetailsForm({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
isNewCollection,
|
|
30
|
+
reservedGroups,
|
|
31
|
+
existingPaths,
|
|
32
|
+
existingIds,
|
|
33
|
+
groups,
|
|
34
|
+
parentCollection,
|
|
35
|
+
expandKanban
|
|
36
|
+
}: {
|
|
35
37
|
isNewCollection: boolean,
|
|
36
38
|
reservedGroups?: string[];
|
|
37
39
|
existingPaths?: string[];
|
|
@@ -39,7 +41,7 @@ export function CollectionDetailsForm({
|
|
|
39
41
|
groups: string[] | null;
|
|
40
42
|
parentCollection?: EntityCollection;
|
|
41
43
|
parentCollectionIds?: string[];
|
|
42
|
-
|
|
44
|
+
expandKanban?: boolean;
|
|
43
45
|
}) {
|
|
44
46
|
|
|
45
47
|
const groupRef = React.useRef<HTMLInputElement>(null);
|
|
@@ -57,7 +59,35 @@ export function CollectionDetailsForm({
|
|
|
57
59
|
const collectionEditor = useCollectionEditorController();
|
|
58
60
|
|
|
59
61
|
const [iconDialogOpen, setIconDialogOpen] = useState(false);
|
|
60
|
-
const [
|
|
62
|
+
const [orderPropertyDialogOpen, setOrderPropertyDialogOpen] = useState(false);
|
|
63
|
+
|
|
64
|
+
const authController = useAuthController();
|
|
65
|
+
const customizationController = useCustomizationController();
|
|
66
|
+
|
|
67
|
+
// Resolve collection to get properties for order property select
|
|
68
|
+
const resolvedCollection = useMemo(() => resolveCollection({
|
|
69
|
+
collection: values,
|
|
70
|
+
path: values.path,
|
|
71
|
+
propertyConfigs: customizationController.propertyConfigs,
|
|
72
|
+
authController
|
|
73
|
+
}), [values, customizationController.propertyConfigs, authController]);
|
|
74
|
+
|
|
75
|
+
// Get number properties (for orderProperty)
|
|
76
|
+
const numberProperties = useMemo(() => {
|
|
77
|
+
const result: { key: string; label: string; property: Property; }[] = [];
|
|
78
|
+
if (!resolvedCollection.properties) return result;
|
|
79
|
+
|
|
80
|
+
Object.entries(resolvedCollection.properties).forEach(([key, prop]) => {
|
|
81
|
+
if (prop && 'dataType' in prop && prop.dataType === 'number') {
|
|
82
|
+
result.push({
|
|
83
|
+
key,
|
|
84
|
+
label: (prop as Property).name || key,
|
|
85
|
+
property: prop as Property
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
return result;
|
|
90
|
+
}, [resolvedCollection.properties]);
|
|
61
91
|
|
|
62
92
|
const updateDatabaseId = (databaseId: string) => {
|
|
63
93
|
setFieldValue("databaseId", databaseId ?? undefined);
|
|
@@ -83,13 +113,7 @@ export function CollectionDetailsForm({
|
|
|
83
113
|
|
|
84
114
|
};
|
|
85
115
|
|
|
86
|
-
|
|
87
|
-
if (errors.id) {
|
|
88
|
-
setAdvancedPanelExpanded(true);
|
|
89
|
-
}
|
|
90
|
-
}, [errors.id]);
|
|
91
|
-
|
|
92
|
-
const collectionIcon = <IconForView collectionOrView={values}/>;
|
|
116
|
+
const collectionIcon = <IconForView collectionOrView={values} />;
|
|
93
117
|
|
|
94
118
|
const groupOptions = groups?.filter((group) => !reservedGroups?.includes(group));
|
|
95
119
|
|
|
@@ -103,17 +127,6 @@ export function CollectionDetailsForm({
|
|
|
103
127
|
|
|
104
128
|
const isSubcollection = !!parentCollection;
|
|
105
129
|
|
|
106
|
-
let customIdValue: "true" | "false" | "optional" | "code_defined" | undefined;
|
|
107
|
-
if (typeof values.customId === "object") {
|
|
108
|
-
customIdValue = "code_defined";
|
|
109
|
-
} else if (values.customId === true) {
|
|
110
|
-
customIdValue = "true";
|
|
111
|
-
} else if (values.customId === false) {
|
|
112
|
-
customIdValue = "false";
|
|
113
|
-
} else if (values.customId === "optional") {
|
|
114
|
-
customIdValue = "optional";
|
|
115
|
-
}
|
|
116
|
-
|
|
117
130
|
const showErrors = submitCount > 0;
|
|
118
131
|
|
|
119
132
|
return (
|
|
@@ -127,10 +140,10 @@ export function CollectionDetailsForm({
|
|
|
127
140
|
{isNewCollection ? "New collection" : `${values?.name} collection`}
|
|
128
141
|
</Typography>
|
|
129
142
|
<DefaultDatabaseField databaseId={values.databaseId}
|
|
130
|
-
|
|
143
|
+
onDatabaseIdUpdate={updateDatabaseId} />
|
|
131
144
|
|
|
132
145
|
<Tooltip title={"Change icon"}
|
|
133
|
-
|
|
146
|
+
asChild={true}>
|
|
134
147
|
<IconButton
|
|
135
148
|
shape={"square"}
|
|
136
149
|
onClick={() => setIconDialogOpen(true)}>
|
|
@@ -155,7 +168,7 @@ export function CollectionDetailsForm({
|
|
|
155
168
|
label={"Name"}
|
|
156
169
|
autoFocus={true}
|
|
157
170
|
required
|
|
158
|
-
error={showErrors && Boolean(errors.name)}/>
|
|
171
|
+
error={showErrors && Boolean(errors.name)} />
|
|
159
172
|
<FieldCaption error={touched.name && Boolean(errors.name)}>
|
|
160
173
|
{touched.name && Boolean(errors.name) ? errors.name : "Name of this collection, usually a plural name (e.g. Products)"}
|
|
161
174
|
</FieldCaption>
|
|
@@ -163,10 +176,10 @@ export function CollectionDetailsForm({
|
|
|
163
176
|
|
|
164
177
|
<div className={cls("col-span-12 ")}>
|
|
165
178
|
<Field name={"path"}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
179
|
+
as={DebouncedTextField}
|
|
180
|
+
label={"Path"}
|
|
181
|
+
required
|
|
182
|
+
error={showErrors && Boolean(errors.path)} />
|
|
170
183
|
|
|
171
184
|
<FieldCaption error={touched.path && Boolean(errors.path)}>
|
|
172
185
|
{touched.path && Boolean(errors.path)
|
|
@@ -214,16 +227,158 @@ export function CollectionDetailsForm({
|
|
|
214
227
|
<LayoutModeSwitch
|
|
215
228
|
className={"col-span-12"}
|
|
216
229
|
value={values.openEntityMode ?? "side_panel"}
|
|
217
|
-
onChange={(value) => setFieldValue("openEntityMode", value)}/>
|
|
230
|
+
onChange={(value) => setFieldValue("openEntityMode", value)} />
|
|
231
|
+
|
|
232
|
+
<ViewModeSwitch
|
|
233
|
+
className={"col-span-12"}
|
|
234
|
+
value={values.defaultViewMode ?? "table"}
|
|
235
|
+
onChange={(value) => setFieldValue("defaultViewMode", value)} />
|
|
236
|
+
|
|
237
|
+
<KanbanConfigSection className={"col-span-12"} forceExpanded={expandKanban} />
|
|
238
|
+
|
|
239
|
+
<div className={"col-span-12 mt-4"}>
|
|
240
|
+
{(() => {
|
|
241
|
+
// Check if orderProperty references a non-existent property
|
|
242
|
+
const orderPropertyMissing = Boolean(values.orderProperty) &&
|
|
243
|
+
!numberProperties.some(p => p.key === values.orderProperty);
|
|
244
|
+
|
|
245
|
+
return (
|
|
246
|
+
<>
|
|
247
|
+
<Select
|
|
248
|
+
key={`order-select-${numberProperties.length}`}
|
|
249
|
+
name="orderProperty"
|
|
250
|
+
label="Order Property"
|
|
251
|
+
size={"large"}
|
|
252
|
+
fullWidth={true}
|
|
253
|
+
position={"item-aligned"}
|
|
254
|
+
disabled={numberProperties.length === 0}
|
|
255
|
+
error={orderPropertyMissing}
|
|
256
|
+
value={values.orderProperty ?? ""}
|
|
257
|
+
onValueChange={(v) => {
|
|
258
|
+
setFieldValue("orderProperty", v || undefined);
|
|
259
|
+
}}
|
|
260
|
+
renderValue={(value) => {
|
|
261
|
+
if (orderPropertyMissing) {
|
|
262
|
+
return <span className="text-red-500">{value} (not found)</span>;
|
|
263
|
+
}
|
|
264
|
+
const prop = numberProperties.find(p => p.key === value);
|
|
265
|
+
if (!prop) return "Select a property";
|
|
266
|
+
const fieldConfig = getFieldConfig(prop.property, customizationController.propertyConfigs);
|
|
267
|
+
return (
|
|
268
|
+
<div className="flex items-center gap-2">
|
|
269
|
+
<PropertyConfigBadge propertyConfig={fieldConfig} />
|
|
270
|
+
<span>{prop.label}</span>
|
|
271
|
+
</div>
|
|
272
|
+
);
|
|
273
|
+
}}
|
|
274
|
+
endAdornment={values.orderProperty ? (
|
|
275
|
+
<IconButton
|
|
276
|
+
size="small"
|
|
277
|
+
onClick={(e) => {
|
|
278
|
+
e.stopPropagation();
|
|
279
|
+
setFieldValue("orderProperty", undefined);
|
|
280
|
+
}}
|
|
281
|
+
>
|
|
282
|
+
<CloseIcon size="small" />
|
|
283
|
+
</IconButton>
|
|
284
|
+
) : undefined}
|
|
285
|
+
>
|
|
286
|
+
{numberProperties.map((prop) => {
|
|
287
|
+
const fieldConfig = getFieldConfig(prop.property, customizationController.propertyConfigs);
|
|
288
|
+
return (
|
|
289
|
+
<SelectItem key={prop.key} value={prop.key}>
|
|
290
|
+
<div className="flex items-center gap-3">
|
|
291
|
+
<PropertyConfigBadge propertyConfig={fieldConfig} />
|
|
292
|
+
<div>
|
|
293
|
+
<div>{prop.label}</div>
|
|
294
|
+
<Typography variant="caption" color="secondary">
|
|
295
|
+
{fieldConfig?.name || "Number"}
|
|
296
|
+
</Typography>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
</SelectItem>
|
|
300
|
+
);
|
|
301
|
+
})}
|
|
302
|
+
</Select>
|
|
303
|
+
<FieldCaption error={orderPropertyMissing}>
|
|
304
|
+
{orderPropertyMissing
|
|
305
|
+
? `Property "${values.orderProperty}" does not exist or is not a number property. Please select a valid property or clear the selection.`
|
|
306
|
+
: numberProperties.length === 0
|
|
307
|
+
? "No number properties found. Add a number property to enable ordering."
|
|
308
|
+
: "Select a number property to persist the order of items"
|
|
309
|
+
}
|
|
310
|
+
</FieldCaption>
|
|
311
|
+
</>
|
|
312
|
+
);
|
|
313
|
+
})()}
|
|
314
|
+
{(() => {
|
|
315
|
+
// Check if orderProperty references a non-existent property
|
|
316
|
+
const orderPropertyMissing = Boolean(values.orderProperty) &&
|
|
317
|
+
!numberProperties.some(p => p.key === values.orderProperty);
|
|
318
|
+
const showCreateButton = !values.orderProperty || orderPropertyMissing;
|
|
319
|
+
|
|
320
|
+
// Pre-fill with missing property id or default "__order"
|
|
321
|
+
const dialogPropertyKey = orderPropertyMissing && values.orderProperty
|
|
322
|
+
? values.orderProperty
|
|
323
|
+
: "__order";
|
|
324
|
+
const dialogPropertyName = orderPropertyMissing && values.orderProperty
|
|
325
|
+
? unslugify(values.orderProperty)
|
|
326
|
+
: "Order";
|
|
327
|
+
|
|
328
|
+
if (!showCreateButton) return null;
|
|
329
|
+
|
|
330
|
+
return (
|
|
331
|
+
<>
|
|
332
|
+
<button
|
|
333
|
+
type="button"
|
|
334
|
+
className="ml-3.5 text-sm text-primary hover:text-primary-dark mt-2"
|
|
335
|
+
onClick={() => setOrderPropertyDialogOpen(true)}
|
|
336
|
+
>
|
|
337
|
+
+ Create "{dialogPropertyKey}" property
|
|
338
|
+
</button>
|
|
339
|
+
<PropertyFormDialog
|
|
340
|
+
open={orderPropertyDialogOpen}
|
|
341
|
+
onCancel={() => setOrderPropertyDialogOpen(false)}
|
|
342
|
+
property={{
|
|
343
|
+
dataType: "number",
|
|
344
|
+
name: dialogPropertyName,
|
|
345
|
+
disabled: true,
|
|
346
|
+
hideFromCollection: true
|
|
347
|
+
}}
|
|
348
|
+
propertyKey={dialogPropertyKey}
|
|
349
|
+
existingProperty={false}
|
|
350
|
+
autoOpenTypeSelect={false}
|
|
351
|
+
autoUpdateId={false}
|
|
352
|
+
inArray={false}
|
|
353
|
+
allowDataInference={false}
|
|
354
|
+
propertyConfigs={customizationController.propertyConfigs}
|
|
355
|
+
collectionEditable={true}
|
|
356
|
+
existingPropertyKeys={Object.keys(values.properties ?? {})}
|
|
357
|
+
onPropertyChanged={({ id, property }) => {
|
|
358
|
+
const newProperties = {
|
|
359
|
+
...values.properties,
|
|
360
|
+
[id!]: property
|
|
361
|
+
};
|
|
362
|
+
const newPropertiesOrder = [...(values.propertiesOrder ?? Object.keys(values.properties ?? {})), id];
|
|
363
|
+
setFieldValue("properties", newProperties);
|
|
364
|
+
setFieldValue("propertiesOrder", newPropertiesOrder);
|
|
365
|
+
setFieldValue("orderProperty", id);
|
|
366
|
+
setOrderPropertyDialogOpen(false);
|
|
367
|
+
}}
|
|
368
|
+
/>
|
|
369
|
+
</>
|
|
370
|
+
);
|
|
371
|
+
})()}
|
|
372
|
+
</div>
|
|
218
373
|
|
|
219
374
|
<div className={"col-span-12"}>
|
|
220
375
|
<BooleanSwitchWithLabel
|
|
221
376
|
position={"start"}
|
|
222
377
|
size={"large"}
|
|
223
378
|
allowIndeterminate={true}
|
|
224
|
-
label={values.history === null || values.history === undefined ? "Document history revisions enabled if enabled globally" : (
|
|
379
|
+
label={<span className="flex items-center gap-2"><HistoryIcon size={"smallest"} />{values.history === null || values.history === undefined ? "Document history revisions enabled if enabled globally" : (
|
|
225
380
|
values.history ? "Document history revisions ENABLED" : "Document history revisions NOT enabled"
|
|
226
|
-
)}
|
|
381
|
+
)}</span>}
|
|
227
382
|
onValueChange={(v) => setFieldValue("history", v)}
|
|
228
383
|
value={values.history === undefined ? null : values.history}
|
|
229
384
|
/>
|
|
@@ -236,214 +391,12 @@ export function CollectionDetailsForm({
|
|
|
236
391
|
|
|
237
392
|
|
|
238
393
|
<div className={"col-span-12 mt-8"}>
|
|
239
|
-
<ExpandablePanel
|
|
240
|
-
expanded={advancedPanelExpanded}
|
|
241
|
-
onExpandedChange={setAdvancedPanelExpanded}
|
|
242
|
-
title={
|
|
243
|
-
<div className="flex flex-row text-surface-500">
|
|
244
|
-
<SettingsIcon/>
|
|
245
|
-
<Typography variant={"subtitle2"}
|
|
246
|
-
className="ml-2">
|
|
247
|
-
Advanced
|
|
248
|
-
</Typography>
|
|
249
|
-
</div>}
|
|
250
|
-
initiallyExpanded={false}>
|
|
251
|
-
<div className={"grid grid-cols-12 gap-4 p-4"}>
|
|
252
|
-
|
|
253
|
-
<div className={"col-span-12"}>
|
|
254
|
-
<Field name={"id"}
|
|
255
|
-
as={DebouncedTextField}
|
|
256
|
-
disabled={!isNewCollection}
|
|
257
|
-
label={"Collection id"}
|
|
258
|
-
error={showErrors && Boolean(errors.id)}/>
|
|
259
|
-
<FieldCaption error={touched.id && Boolean(errors.id)}>
|
|
260
|
-
{touched.id && Boolean(errors.id) ? errors.id : "This id identifies this collection. Typically the same as the path."}
|
|
261
|
-
</FieldCaption>
|
|
262
|
-
</div>
|
|
263
|
-
|
|
264
|
-
<div className={"col-span-12"}>
|
|
265
|
-
<TextField
|
|
266
|
-
error={showErrors && Boolean(errors.singularName)}
|
|
267
|
-
name={"singularName"}
|
|
268
|
-
aria-describedby={"singularName-helper"}
|
|
269
|
-
onChange={(e) => {
|
|
270
|
-
setFieldTouched("singularName", true);
|
|
271
|
-
return handleChange(e);
|
|
272
|
-
}}
|
|
273
|
-
value={values.singularName ?? ""}
|
|
274
|
-
label={"Singular name"}/>
|
|
275
|
-
<FieldCaption error={showErrors && Boolean(errors.singularName)}>
|
|
276
|
-
{showErrors && Boolean(errors.singularName) ? errors.singularName : "Optionally define a singular name for your entities"}
|
|
277
|
-
</FieldCaption>
|
|
278
|
-
</div>
|
|
279
|
-
<div className={"col-span-12"}>
|
|
280
|
-
<TextField
|
|
281
|
-
error={showErrors && Boolean(errors.sideDialogWidth)}
|
|
282
|
-
name={"sideDialogWidth"}
|
|
283
|
-
type={"number"}
|
|
284
|
-
aria-describedby={"sideDialogWidth-helper"}
|
|
285
|
-
onChange={(e) => {
|
|
286
|
-
setFieldTouched("sideDialogWidth", true);
|
|
287
|
-
const value = e.target.value;
|
|
288
|
-
if (!value) {
|
|
289
|
-
setFieldValue("sideDialogWidth", null);
|
|
290
|
-
} else if (!isNaN(Number(value))) {
|
|
291
|
-
setFieldValue("sideDialogWidth", Number(value));
|
|
292
|
-
}
|
|
293
|
-
}}
|
|
294
|
-
endAdornment={<IconButton
|
|
295
|
-
size={"small"}
|
|
296
|
-
onClick={() => {
|
|
297
|
-
setFieldValue("sideDialogWidth", null);
|
|
298
|
-
}}
|
|
299
|
-
disabled={!values.sideDialogWidth}>
|
|
300
|
-
<CloseIcon size={"small"}/>
|
|
301
|
-
</IconButton>}
|
|
302
|
-
value={values.sideDialogWidth ?? ""}
|
|
303
|
-
label={"Side dialog width"}/>
|
|
304
|
-
<FieldCaption error={showErrors && Boolean(errors.singularName)}>
|
|
305
|
-
{showErrors && Boolean(errors.singularName) ? errors.singularName : "Optionally define the width (in pixels) of entities side dialog. Default is 768px"}
|
|
306
|
-
</FieldCaption>
|
|
307
|
-
</div>
|
|
308
|
-
<div className={"col-span-12"}>
|
|
309
|
-
<TextField
|
|
310
|
-
error={showErrors && Boolean(errors.description)}
|
|
311
|
-
name="description"
|
|
312
|
-
value={values.description ?? ""}
|
|
313
|
-
onChange={handleChange}
|
|
314
|
-
multiline
|
|
315
|
-
minRows={2}
|
|
316
|
-
aria-describedby="description-helper-text"
|
|
317
|
-
label="Description"
|
|
318
|
-
/>
|
|
319
|
-
<FieldCaption error={showErrors && Boolean(errors.description)}>
|
|
320
|
-
{showErrors && Boolean(errors.description) ? errors.description : "Description of the collection, you can use markdown"}
|
|
321
|
-
</FieldCaption>
|
|
322
|
-
</div>
|
|
323
|
-
|
|
324
|
-
<div className={"col-span-12"}>
|
|
325
|
-
<Select
|
|
326
|
-
name="defaultSize"
|
|
327
|
-
size={"large"}
|
|
328
|
-
fullWidth={true}
|
|
329
|
-
label="Default row size"
|
|
330
|
-
position={"item-aligned"}
|
|
331
|
-
onChange={handleChange}
|
|
332
|
-
value={values.defaultSize ?? ""}
|
|
333
|
-
renderValue={(value: any) => value.toUpperCase()}
|
|
334
|
-
>
|
|
335
|
-
{["xs", "s", "m", "l", "xl"].map((value) => (
|
|
336
|
-
<SelectItem
|
|
337
|
-
key={`size-select-${value}`}
|
|
338
|
-
value={value}>
|
|
339
|
-
{value.toUpperCase()}
|
|
340
|
-
</SelectItem>
|
|
341
|
-
))}
|
|
342
|
-
</Select>
|
|
343
|
-
</div>
|
|
344
|
-
|
|
345
|
-
<div className={"col-span-12"}>
|
|
346
|
-
<BooleanSwitchWithLabel
|
|
347
|
-
position={"start"}
|
|
348
|
-
size={"large"}
|
|
349
|
-
label={values.includeJsonView === undefined || values.includeJsonView ? "Include JSON view" : "Do not include JSON view"}
|
|
350
|
-
onValueChange={(v) => setFieldValue("includeJsonView", v)}
|
|
351
|
-
value={values.includeJsonView === undefined ? true : values.includeJsonView}
|
|
352
|
-
/>
|
|
353
|
-
<FieldCaption>
|
|
354
|
-
Include the JSON representation of the document.
|
|
355
|
-
</FieldCaption>
|
|
356
|
-
</div>
|
|
357
|
-
|
|
358
|
-
<div className={"col-span-12"}>
|
|
359
|
-
<BooleanSwitchWithLabel
|
|
360
|
-
position={"start"}
|
|
361
|
-
size={"large"}
|
|
362
|
-
label={values.inlineEditing === undefined || values.inlineEditing ? "Data can be edited directly in the table view" : "Data can be edited only in the form view"}
|
|
363
|
-
onValueChange={(v) => setFieldValue("inlineEditing", v)}
|
|
364
|
-
value={values.inlineEditing === undefined ? true : values.inlineEditing}
|
|
365
|
-
/>
|
|
366
|
-
<FieldCaption>
|
|
367
|
-
Allow editing data directly in the table view, without opening the form view.
|
|
368
|
-
</FieldCaption>
|
|
369
|
-
</div>
|
|
370
|
-
|
|
371
|
-
<div className={"col-span-12"}>
|
|
372
|
-
<Select
|
|
373
|
-
name="customId"
|
|
374
|
-
label="Document IDs generation"
|
|
375
|
-
position={"item-aligned"}
|
|
376
|
-
size={"large"}
|
|
377
|
-
fullWidth={true}
|
|
378
|
-
disabled={customIdValue === "code_defined"}
|
|
379
|
-
onValueChange={(v) => {
|
|
380
|
-
if (v === "code_defined")
|
|
381
|
-
throw new Error("This should not happen");
|
|
382
|
-
setFieldValue("customId", v);
|
|
383
|
-
}}
|
|
384
|
-
value={customIdValue ?? ""}
|
|
385
|
-
renderValue={(value: any) => {
|
|
386
|
-
if (value === "code_defined")
|
|
387
|
-
return "Code defined";
|
|
388
|
-
else if (value === "true")
|
|
389
|
-
return "Users must define an ID";
|
|
390
|
-
else if (value === "optional")
|
|
391
|
-
return "Users can define an ID, but it is not required";
|
|
392
|
-
else
|
|
393
|
-
return "Document ID is generated automatically";
|
|
394
|
-
}}
|
|
395
|
-
>
|
|
396
|
-
<SelectItem value={"false"}>
|
|
397
|
-
Document ID is generated automatically
|
|
398
|
-
</SelectItem>
|
|
399
|
-
<SelectItem value={"true"}>
|
|
400
|
-
Users must define an ID
|
|
401
|
-
</SelectItem>
|
|
402
|
-
<SelectItem value={"optional"}>
|
|
403
|
-
Users can define an ID, but it is not required
|
|
404
|
-
</SelectItem>
|
|
405
|
-
</Select>
|
|
406
|
-
</div>
|
|
407
|
-
<div className={"col-span-12 mt-4"}>
|
|
408
|
-
<BooleanSwitchWithLabel
|
|
409
|
-
position={"start"}
|
|
410
|
-
size={"large"}
|
|
411
|
-
label="Collection group"
|
|
412
|
-
onValueChange={(v) => setFieldValue("collectionGroup", v)}
|
|
413
|
-
value={values.collectionGroup ?? false}
|
|
414
|
-
/>
|
|
415
|
-
<FieldCaption>
|
|
416
|
-
A collection group consists of all collections with the same path. This allows
|
|
417
|
-
you
|
|
418
|
-
to query over multiple collections at once.
|
|
419
|
-
</FieldCaption>
|
|
420
|
-
</div>
|
|
421
|
-
<div className={"col-span-12"}>
|
|
422
|
-
<BooleanSwitchWithLabel
|
|
423
|
-
position={"start"}
|
|
424
|
-
size={"large"}
|
|
425
|
-
label="Enable text search for this collection"
|
|
426
|
-
onValueChange={(v) => setFieldValue("textSearchEnabled", v)}
|
|
427
|
-
value={values.textSearchEnabled ?? false}
|
|
428
|
-
/>
|
|
429
|
-
<FieldCaption>
|
|
430
|
-
Allow text search for this collection. If you have not specified a text search
|
|
431
|
-
delegate, this will use the built-in local text search. This is not recommended
|
|
432
|
-
for large collections, as it may incur in performance and cost issues.
|
|
433
|
-
</FieldCaption>
|
|
434
|
-
</div>
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
</div>
|
|
438
|
-
</ExpandablePanel>
|
|
439
|
-
|
|
440
|
-
{children}
|
|
441
394
|
|
|
442
395
|
</div>
|
|
443
396
|
|
|
444
397
|
</div>
|
|
445
398
|
|
|
446
|
-
<div style={{ height: "52px" }}/>
|
|
399
|
+
<div style={{ height: "52px" }} />
|
|
447
400
|
|
|
448
401
|
<Dialog
|
|
449
402
|
open={iconDialogOpen}
|
|
@@ -453,10 +406,10 @@ export function CollectionDetailsForm({
|
|
|
453
406
|
>
|
|
454
407
|
<div className={"p-4 overflow-auto min-h-[200px]"}>
|
|
455
408
|
<SearchIconsView selectedIcon={typeof values.icon === "string" ? values.icon : undefined}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
409
|
+
onIconSelected={(icon: string) => {
|
|
410
|
+
setIconDialogOpen(false);
|
|
411
|
+
setFieldValue("icon", icon);
|
|
412
|
+
}} />
|
|
460
413
|
</div>
|
|
461
414
|
|
|
462
415
|
</Dialog>
|
|
@@ -467,18 +420,18 @@ export function CollectionDetailsForm({
|
|
|
467
420
|
}
|
|
468
421
|
|
|
469
422
|
function DefaultDatabaseField({
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
423
|
+
databaseId,
|
|
424
|
+
onDatabaseIdUpdate
|
|
425
|
+
}: { databaseId?: string, onDatabaseIdUpdate: (databaseId: string) => void }) {
|
|
473
426
|
|
|
474
427
|
return <Tooltip title={"Database ID"}
|
|
475
|
-
|
|
476
|
-
|
|
428
|
+
side={"top"}
|
|
429
|
+
align={"start"}>
|
|
477
430
|
<TextField size={"small"}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
431
|
+
invisible={true}
|
|
432
|
+
inputClassName={"text-end"}
|
|
433
|
+
value={databaseId ?? ""}
|
|
434
|
+
onChange={(e: any) => onDatabaseIdUpdate(e.target.value)}
|
|
435
|
+
placeholder={"(default)"}></TextField>
|
|
483
436
|
</Tooltip>
|
|
484
437
|
}
|