@firecms/collection_editor 3.0.1 → 3.1.0-canary.7d91b7c

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 +9466 -5588
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +9461 -5583
  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 +37 -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 +24 -0
  18. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +4 -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 +15 -15
  39. package/src/ConfigControllerProvider.tsx +82 -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 +242 -0
  54. package/src/ui/collection_editor/AIModifiedPathsContext.tsx +88 -0
  55. package/src/ui/collection_editor/CollectionDetailsForm.tsx +212 -259
  56. package/src/ui/collection_editor/CollectionEditorDialog.tsx +237 -169
  57. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +133 -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 +337 -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 +206 -142
  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
@@ -0,0 +1,207 @@
1
+ import React, { useMemo, useRef, useState } from "react";
2
+ import {
3
+ EntityCollection,
4
+ FieldCaption,
5
+ getFieldConfig,
6
+ Property,
7
+ PropertyConfigBadge,
8
+ resolveCollection,
9
+ unslugify,
10
+ useAuthController,
11
+ useCustomizationController
12
+ } from "@firecms/core";
13
+ import {
14
+ CloseIcon,
15
+ IconButton,
16
+ Select,
17
+ SelectItem,
18
+ Typography
19
+ } from "@firecms/ui";
20
+ import { useFormex } from "@firecms/formex";
21
+ import { PropertyFormDialog } from "./PropertyEditView";
22
+
23
+ export function KanbanConfigSection({
24
+ className,
25
+ forceExpanded
26
+ }: {
27
+ className?: string;
28
+ forceExpanded?: boolean;
29
+ }) {
30
+ const authController = useAuthController();
31
+ const customizationController = useCustomizationController();
32
+ const { values, setFieldValue } = useFormex<EntityCollection>();
33
+ const panelRef = useRef<HTMLDivElement>(null);
34
+ const [columnPropertyDialogOpen, setColumnPropertyDialogOpen] = useState(false);
35
+
36
+ // Resolve collection to get properties
37
+ const resolvedCollection = useMemo(() => resolveCollection({
38
+ collection: values,
39
+ path: values.path,
40
+ propertyConfigs: customizationController.propertyConfigs,
41
+ authController
42
+ }), [values, customizationController.propertyConfigs, authController]);
43
+
44
+ // Get enum string properties (for columnProperty)
45
+ const enumStringProperties = useMemo(() => {
46
+ const result: { key: string; label: string; property: Property }[] = [];
47
+ if (!resolvedCollection.properties) return result;
48
+
49
+ Object.entries(resolvedCollection.properties).forEach(([key, prop]) => {
50
+ if (prop && 'dataType' in prop && prop.dataType === 'string' && prop.enumValues) {
51
+ result.push({
52
+ key,
53
+ label: (prop as Property).name || key,
54
+ property: prop as Property
55
+ });
56
+ }
57
+ });
58
+ return result;
59
+ }, [resolvedCollection.properties]);
60
+
61
+ const kanbanConfig = values.kanban;
62
+
63
+ // Check if columnProperty references a non-existent property
64
+ const columnPropertyMissing = Boolean(kanbanConfig?.columnProperty) &&
65
+ !enumStringProperties.some(p => p.key === kanbanConfig?.columnProperty);
66
+
67
+ // Scroll to section when forceExpanded
68
+ React.useEffect(() => {
69
+ if (forceExpanded && panelRef.current) {
70
+ setTimeout(() => {
71
+ panelRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
72
+ }, 100);
73
+ }
74
+ }, [forceExpanded]);
75
+
76
+ const showCreateButton = !kanbanConfig?.columnProperty || columnPropertyMissing;
77
+ const dialogPropertyKey = columnPropertyMissing && kanbanConfig?.columnProperty
78
+ ? kanbanConfig.columnProperty
79
+ : "status";
80
+ const dialogPropertyName = columnPropertyMissing && kanbanConfig?.columnProperty
81
+ ? unslugify(kanbanConfig.columnProperty)
82
+ : "Status";
83
+
84
+ return (
85
+ <div className={className} ref={panelRef}>
86
+ <Select
87
+ key={`column-select-${enumStringProperties.length}`}
88
+ name="kanban.columnProperty"
89
+ label="Kanban Column Property"
90
+ size={"large"}
91
+ fullWidth={true}
92
+ position={"item-aligned"}
93
+ disabled={enumStringProperties.length === 0}
94
+ error={columnPropertyMissing}
95
+ value={kanbanConfig?.columnProperty ?? ""}
96
+ onValueChange={(v) => {
97
+ if (v) {
98
+ setFieldValue("kanban", {
99
+ ...kanbanConfig,
100
+ columnProperty: v
101
+ });
102
+ } else {
103
+ setFieldValue("kanban", undefined);
104
+ }
105
+ }}
106
+ renderValue={(value) => {
107
+ if (columnPropertyMissing) {
108
+ return <span className="text-red-500">{value} (not found)</span>;
109
+ }
110
+ const prop = enumStringProperties.find(p => p.key === value);
111
+ if (!prop) return "Select a property";
112
+ const fieldConfig = getFieldConfig(prop.property, customizationController.propertyConfigs);
113
+ return (
114
+ <div className="flex items-center gap-2">
115
+ <PropertyConfigBadge propertyConfig={fieldConfig} />
116
+ <span>{prop.label}</span>
117
+ </div>
118
+ );
119
+ }}
120
+ endAdornment={kanbanConfig?.columnProperty ? (
121
+ <IconButton
122
+ size="small"
123
+ onClick={(e) => {
124
+ e.stopPropagation();
125
+ setFieldValue("kanban", undefined);
126
+ }}
127
+ >
128
+ <CloseIcon size="small" />
129
+ </IconButton>
130
+ ) : undefined}
131
+ >
132
+ {enumStringProperties.map((prop) => {
133
+ const fieldConfig = getFieldConfig(prop.property, customizationController.propertyConfigs);
134
+ return (
135
+ <SelectItem key={prop.key} value={prop.key}>
136
+ <div className="flex items-center gap-3">
137
+ <PropertyConfigBadge propertyConfig={fieldConfig} />
138
+ <div>
139
+ <div>{prop.label}</div>
140
+ <Typography variant="caption" color="secondary">
141
+ {fieldConfig?.name || "Enum"}
142
+ </Typography>
143
+ </div>
144
+ </div>
145
+ </SelectItem>
146
+ );
147
+ })}
148
+ </Select>
149
+ <FieldCaption error={columnPropertyMissing}>
150
+ {columnPropertyMissing
151
+ ? `Property "${kanbanConfig?.columnProperty}" does not exist or is not an enum string property. Please select a valid property or clear the selection.`
152
+ : enumStringProperties.length === 0
153
+ ? "No enum string properties found. Add a string property with enumValues to use Kanban view."
154
+ : "Select a string property with enum values to group entities into columns"
155
+ }
156
+ </FieldCaption>
157
+
158
+ {showCreateButton && (
159
+ <>
160
+ <button
161
+ type="button"
162
+ className="ml-3.5 text-sm text-primary hover:text-primary-dark mt-2"
163
+ onClick={() => setColumnPropertyDialogOpen(true)}
164
+ >
165
+ + Create "{dialogPropertyKey}" property
166
+ </button>
167
+ <PropertyFormDialog
168
+ open={columnPropertyDialogOpen}
169
+ onCancel={() => setColumnPropertyDialogOpen(false)}
170
+ property={{
171
+ dataType: "string",
172
+ name: dialogPropertyName,
173
+ enumValues: [
174
+ { id: "todo", label: "To Do" },
175
+ { id: "in_progress", label: "In Progress" },
176
+ { id: "done", label: "Done" }
177
+ ]
178
+ }}
179
+ propertyKey={dialogPropertyKey}
180
+ existingProperty={false}
181
+ autoOpenTypeSelect={false}
182
+ autoUpdateId={false}
183
+ inArray={false}
184
+ allowDataInference={false}
185
+ propertyConfigs={customizationController.propertyConfigs}
186
+ collectionEditable={true}
187
+ existingPropertyKeys={Object.keys(values.properties ?? {})}
188
+ onPropertyChanged={({ id, property }) => {
189
+ const newProperties = {
190
+ ...values.properties,
191
+ [id!]: property
192
+ };
193
+ const newPropertiesOrder = [...(values.propertiesOrder ?? Object.keys(values.properties ?? {})), id];
194
+ setFieldValue("properties", newProperties);
195
+ setFieldValue("propertiesOrder", newPropertiesOrder);
196
+ setFieldValue("kanban", {
197
+ ...kanbanConfig,
198
+ columnProperty: id
199
+ });
200
+ setColumnPropertyDialogOpen(false);
201
+ }}
202
+ />
203
+ </>
204
+ )}
205
+ </div>
206
+ );
207
+ }
@@ -1,10 +1,10 @@
1
- import { Card, cls, SquareIcon, Tooltip, Typography, VerticalSplitIcon } from "@firecms/ui";
1
+ import { cls, SquareIcon, ToggleButtonGroup, Typography, VerticalSplitIcon } from "@firecms/ui";
2
2
 
3
3
  export function LayoutModeSwitch({
4
- value,
5
- onChange,
6
- className
7
- }: {
4
+ value,
5
+ onChange,
6
+ className
7
+ }: {
8
8
  value: "side_panel" | "full_screen";
9
9
  onChange: (value: "side_panel" | "full_screen") => void;
10
10
  className?: string;
@@ -12,42 +12,23 @@ export function LayoutModeSwitch({
12
12
 
13
13
  return <div className={cls(className)}>
14
14
  <Typography variant={"label"} color={"secondary"} className={"ml-3.5"}>Document view</Typography>
15
- <div className={cls("flex flex-row gap-4")}>
16
-
17
- <Tooltip title={"Documents are open in a side panel"}>
18
- <Card
19
- onClick={() => onChange("side_panel")}
20
- className={cls(
21
- "my-2 rounded-md mx-0 p-4 focus:outline-none transition ease-in-out duration-150 flex flex-row gap-4 items-center",
22
- "text-surface-700 dark:text-surface-accent-300",
23
- "hover:text-primary-dark dark:hover:text-primary focus:ring-primary hover:ring-1 hover:ring-primary",
24
- value === "side_panel" ? "border-primary dark:border-primary" : "border-surface-400 dark:border-surface-600",
25
- )}
26
- >
27
- <VerticalSplitIcon/>
28
- <Typography variant={"label"}>
29
- Side panel
30
- </Typography>
31
- </Card>
32
- </Tooltip>
33
-
34
- <Tooltip title={"Documents are open full-screen"}>
35
- <Card
36
- onClick={() => onChange("full_screen")}
37
- className={cls(
38
- "my-2 rounded-md mx-0 p-4 focus:outline-none transition ease-in-out duration-150 flex flex-row gap-4 items-center",
39
- "text-surface-700 dark:text-surface-accent-300",
40
- "hover:text-primary-dark dark:hover:text-primary focus:ring-primary hover:ring-1 hover:ring-primary",
41
- value === "full_screen" ? "border-primary dark:border-primary" : "border-surface-400 dark:border-surface-600",
42
- )}
43
- >
44
- <SquareIcon/>
45
- <Typography variant={"label"}>
46
- Full screen
47
- </Typography>
48
- </Card>
49
- </Tooltip>
50
-
15
+ <div className={"my-2"}>
16
+ <ToggleButtonGroup
17
+ value={value}
18
+ onValueChange={onChange}
19
+ options={[
20
+ {
21
+ value: "side_panel",
22
+ label: "Side panel",
23
+ icon: <VerticalSplitIcon />
24
+ },
25
+ {
26
+ value: "full_screen",
27
+ label: "Full screen",
28
+ icon: <SquareIcon />
29
+ }
30
+ ]}
31
+ />
51
32
  </div>
52
33
  <Typography variant={"caption"} color={"secondary"} className={"ml-3.5"}>Should documents be opened full screen or in an inline side dialog</Typography>
53
34
  </div>