@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firecms/collection_editor",
3
- "version": "3.0.0-alpha.5",
3
+ "version": "3.0.0-alpha.51",
4
4
  "main": "./dist/index.umd.js",
5
5
  "module": "./dist/index.es.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,13 +8,16 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "import": "./dist/index.es.js",
11
- "require": "./dist/index.umd.js"
12
- }
11
+ "require": "./dist/index.umd.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./package.json": "./package.json"
13
15
  },
14
16
  "dependencies": {
15
- "@firecms/data_import": "^3.0.0-alpha.5",
16
- "@firecms/schema_inference": "^3.0.0-alpha.5",
17
- "flexsearch": "0.7.31"
17
+ "@firecms/data_import_export": "^3.0.0-alpha.51",
18
+ "@firecms/schema_inference": "^3.0.0-alpha.51",
19
+ "json5": "^2.2.3",
20
+ "prism-react-renderer": "^2.3.0"
18
21
  },
19
22
  "peerDependencies": {
20
23
  "react": "^18.2.0",
@@ -25,7 +28,8 @@
25
28
  "scripts": {
26
29
  "dev": "vite",
27
30
  "test": "jest",
28
- "build": "vite build && tsc --emitDeclarationOnly"
31
+ "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
32
+ "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
29
33
  },
30
34
  "eslintConfig": {
31
35
  "extends": [
@@ -47,33 +51,32 @@
47
51
  },
48
52
  "devDependencies": {
49
53
  "@jest/globals": "^29.7.0",
50
- "@types/react": "^18.2.8",
51
- "@types/react-dom": "^18.2.4",
52
- "@typescript-eslint/eslint-plugin": "^5.59.9",
53
- "@typescript-eslint/parser": "^5.59.9",
54
- "@vitejs/plugin-react": "^4.0.0",
55
- "eslint": "^8.42.0",
54
+ "@types/react": "^18.2.45",
55
+ "@types/react-dom": "^18.2.17",
56
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
57
+ "@typescript-eslint/parser": "^5.62.0",
58
+ "@vitejs/plugin-react": "^4.2.1",
59
+ "eslint": "^8.55.0",
56
60
  "eslint-config-standard": "^17.1.0",
57
- "eslint-plugin-import": "^2.27.5",
61
+ "eslint-plugin-import": "^2.29.1",
58
62
  "eslint-plugin-n": "^15.7.0",
59
63
  "eslint-plugin-promise": "^6.1.1",
60
- "eslint-plugin-react": "^7.32.2",
64
+ "eslint-plugin-react": "^7.33.2",
61
65
  "eslint-plugin-react-hooks": "^4.6.0",
62
66
  "jest": "^29.7.0",
63
- "react": "^18.2.0",
64
- "react-dom": "^18.2.0",
65
- "react-router": "^6.12.0",
66
- "react-router-dom": "^6.12.0",
67
+ "react-router": "^6.21.0",
68
+ "react-router-dom": "^6.21.0",
67
69
  "ts-jest": "^29.1.1",
68
- "typescript": "^5.2.2",
69
- "vite": "^4.3.9",
70
+ "typescript": "^5.3.3",
71
+ "vite": "^4.5.1",
70
72
  "vite-plugin-fonts": "^0.7.0"
71
73
  },
72
74
  "files": [
73
- "dist"
75
+ "dist",
76
+ "src"
74
77
  ],
75
78
  "publishConfig": {
76
79
  "access": "public"
77
80
  },
78
- "gitHead": "f73e3367dc97cbea9c98408b3aafaa48454d440b"
81
+ "gitHead": "d47d8dad9356b48398b65559b7a59926f3d50373"
79
82
  }
@@ -0,0 +1,321 @@
1
+ import React, { PropsWithChildren, useCallback, useEffect } from "react";
2
+ import equal from "react-fast-compare"
3
+
4
+ import { CollectionsConfigController } from "./types/config_controller";
5
+ import { Property, useFireCMSContext, useNavigationController, User, useSnackbarController } from "@firecms/core";
6
+ import { CollectionEditorDialog } from "./ui/collection_editor/CollectionEditorDialog";
7
+ import { useNavigate } from "react-router";
8
+ import { CollectionEditorController } from "./types/collection_editor_controller";
9
+ import { CollectionEditorPermissionsBuilder } from "./types/config_permissions";
10
+ import { CollectionInference } from "./types/collection_inference";
11
+ import { PropertyFormDialog } from "./ui/collection_editor/PropertyEditView";
12
+ import { PersistedCollection } from "./types/persisted_collection";
13
+
14
+ export const ConfigControllerContext = React.createContext<CollectionsConfigController>({} as any);
15
+ export const CollectionEditorContext = React.createContext<CollectionEditorController>({} as any);
16
+
17
+ export interface ConfigControllerProviderProps {
18
+ /**
19
+ * Controller for managing the collections' config.
20
+ */
21
+ collectionConfigController: CollectionsConfigController;
22
+
23
+ /**
24
+ * Callback used to infer the schema from the data.
25
+ */
26
+ collectionInference?: CollectionInference;
27
+
28
+ /**
29
+ * Use this builder to define the permissions for the configuration per user.
30
+ */
31
+ configPermissions?: CollectionEditorPermissionsBuilder;
32
+
33
+ /**
34
+ * Groups that cannot be used to create new collections.
35
+ */
36
+ reservedGroups?: string[];
37
+
38
+ extraView?: {
39
+ View: React.ComponentType<{
40
+ path: string
41
+ }>,
42
+ icon: React.ReactNode
43
+ };
44
+
45
+ pathSuggestions?: (path?: string) => Promise<string[]>;
46
+
47
+ getUser: (uid: string) => User | null
48
+
49
+ getData?: (path: string) => Promise<object[]>;
50
+
51
+ }
52
+
53
+ export const ConfigControllerProvider = React.memo(
54
+ function ConfigControllerProvider({
55
+ children,
56
+ collectionConfigController,
57
+ configPermissions,
58
+ reservedGroups,
59
+ collectionInference,
60
+ extraView,
61
+ pathSuggestions,
62
+ getUser,
63
+ getData
64
+ }: PropsWithChildren<ConfigControllerProviderProps>) {
65
+
66
+ const navigation = useNavigationController();
67
+ const navigate = useNavigate();
68
+ const snackbarController = useSnackbarController();
69
+ const { propertyConfigs } = useFireCMSContext();
70
+
71
+ const {
72
+ collections
73
+ } = navigation;
74
+ const existingPaths = collections.map(col => col.path.trim().toLowerCase());
75
+
76
+ const [rootPathSuggestions, setRootPathSuggestions] = React.useState<string[] | undefined>();
77
+ useEffect(() => {
78
+ if (pathSuggestions) {
79
+ pathSuggestions().then((paths) => {
80
+ setRootPathSuggestions(paths.filter(p => !existingPaths.includes(p.trim().toLowerCase())));
81
+ });
82
+ }
83
+ }, [pathSuggestions]);
84
+
85
+ const [currentDialog, setCurrentDialog] = React.useState<{
86
+ isNewCollection: boolean,
87
+ parentCollection?: PersistedCollection,
88
+ editedCollectionPath?: string,
89
+ fullPath?: string,
90
+ parentCollectionIds: string[],
91
+ initialValues?: {
92
+ path?: string,
93
+ group?: string,
94
+ name?: string
95
+ },
96
+ redirect: boolean
97
+ }>();
98
+
99
+ const [currentPropertyDialog, setCurrentPropertyDialog] = React.useState<{
100
+ propertyKey?: string,
101
+ property?: Property,
102
+ namespace?: string,
103
+ parentCollection?: PersistedCollection,
104
+ currentPropertiesOrder?: string[],
105
+ editedCollectionPath: string,
106
+ fullPath?: string,
107
+ parentCollectionIds: string[],
108
+ collectionEditable: boolean;
109
+ }>();
110
+
111
+ const defaultConfigPermissions: CollectionEditorPermissionsBuilder = useCallback(() => ({
112
+ createCollections: true,
113
+ editCollections: true,
114
+ deleteCollections: true
115
+ }), []);
116
+
117
+ const editCollection = useCallback(({
118
+ path,
119
+ fullPath,
120
+ parentCollectionIds,
121
+ parentCollection
122
+ }: {
123
+ path?: string,
124
+ fullPath?: string,
125
+ parentCollectionIds: string[],
126
+ parentCollection?: PersistedCollection
127
+ }) => {
128
+ setCurrentDialog({
129
+ editedCollectionPath: path,
130
+ fullPath,
131
+ parentCollectionIds,
132
+ isNewCollection: false,
133
+ parentCollection,
134
+ redirect: false
135
+ });
136
+ }, []);
137
+
138
+ const editProperty = useCallback(({
139
+ propertyKey,
140
+ property,
141
+ editedCollectionPath,
142
+ currentPropertiesOrder,
143
+ parentCollectionIds,
144
+ collection
145
+ }: {
146
+ propertyKey?: string,
147
+ property?: Property,
148
+ currentPropertiesOrder?: string[],
149
+ editedCollectionPath: string,
150
+ parentCollectionIds: string[],
151
+ collection: PersistedCollection,
152
+ }) => {
153
+ // namespace is all the path until the last dot
154
+ const namespace = propertyKey && propertyKey.includes(".")
155
+ ? propertyKey.substring(0, propertyKey.lastIndexOf("."))
156
+ : undefined;
157
+ const propertyKeyWithoutNamespace = propertyKey && propertyKey.includes(".")
158
+ ? propertyKey.substring(propertyKey.lastIndexOf(".") + 1)
159
+ : propertyKey;
160
+ console.log("edit property", propertyKeyWithoutNamespace, collection)
161
+ setCurrentPropertyDialog({
162
+ propertyKey: propertyKeyWithoutNamespace,
163
+ property,
164
+ namespace,
165
+ currentPropertiesOrder,
166
+ editedCollectionPath,
167
+ parentCollectionIds,
168
+ collectionEditable: collection?.editable ?? false
169
+ });
170
+ }, []);
171
+
172
+ const createCollection = React.useCallback(({
173
+ parentCollectionIds,
174
+ parentCollection,
175
+ initialValues,
176
+ redirect
177
+ }: {
178
+ parentCollectionIds: string[],
179
+ parentCollection?: PersistedCollection
180
+ initialValues?: {
181
+ group?: string,
182
+ path?: string,
183
+ name?: string
184
+ },
185
+ redirect: boolean
186
+ }) => {
187
+ setCurrentDialog({
188
+ isNewCollection: true,
189
+ parentCollectionIds,
190
+ parentCollection,
191
+ initialValues,
192
+ redirect
193
+ });
194
+ }, []);
195
+
196
+ const getPathSuggestions = !pathSuggestions
197
+ ? undefined
198
+ : (path?: string) => {
199
+ if (!path && rootPathSuggestions)
200
+ return Promise.resolve(rootPathSuggestions);
201
+ else {
202
+ return pathSuggestions?.(path);
203
+ }
204
+ }
205
+
206
+ return (
207
+ <ConfigControllerContext.Provider value={collectionConfigController}>
208
+ <CollectionEditorContext.Provider
209
+ value={{
210
+ editCollection,
211
+ createCollection,
212
+ editProperty,
213
+ configPermissions: configPermissions ?? defaultConfigPermissions,
214
+ rootPathSuggestions
215
+ }}>
216
+
217
+ {children}
218
+
219
+ <CollectionEditorDialog
220
+ open={Boolean(currentDialog)}
221
+ configController={collectionConfigController}
222
+ isNewCollection={false}
223
+ collectionInference={collectionInference}
224
+ {...currentDialog}
225
+ getData={getData}
226
+ reservedGroups={reservedGroups}
227
+ extraView={extraView}
228
+ pathSuggestions={getPathSuggestions}
229
+ getUser={getUser}
230
+ handleClose={(collection) => {
231
+ if (currentDialog?.redirect) {
232
+ if (collection && currentDialog?.isNewCollection && !currentDialog.parentCollectionIds.length) {
233
+ const url = navigation.buildUrlCollectionPath(collection.id ?? collection.path);
234
+ navigate(url);
235
+ }
236
+ }
237
+ setCurrentDialog(undefined);
238
+ }}/>
239
+
240
+ {/* Used for editing properties*/}
241
+ <PropertyFormDialog
242
+ open={Boolean(currentPropertyDialog)}
243
+ includeIdAndName={true}
244
+ existingProperty={Boolean(currentPropertyDialog?.propertyKey)}
245
+ autoUpdateId={!currentPropertyDialog ? false : !currentPropertyDialog?.propertyKey}
246
+ autoOpenTypeSelect={!currentPropertyDialog ? false : !currentPropertyDialog?.propertyKey}
247
+ inArray={false}
248
+ collectionEditable={currentPropertyDialog?.collectionEditable ?? false}
249
+ getData={getData && currentPropertyDialog?.editedCollectionPath
250
+ ? () => {
251
+ const resolvedPath = navigation.resolveAliasesFrom(currentPropertyDialog.editedCollectionPath!)
252
+ return getData(resolvedPath);
253
+ }
254
+ : undefined}
255
+ onPropertyChanged={({
256
+ id,
257
+ property
258
+ }) => {
259
+ if (!currentPropertyDialog) return;
260
+ if (!id) return;
261
+ const newProperty = !(currentPropertyDialog.propertyKey);
262
+ return collectionConfigController.saveProperty({
263
+ path: currentPropertyDialog?.editedCollectionPath,
264
+ property,
265
+ propertyKey: id,
266
+ newPropertiesOrder: newProperty && currentPropertyDialog.currentPropertiesOrder ? [...currentPropertyDialog.currentPropertiesOrder, id] : undefined,
267
+ namespace: currentPropertyDialog.namespace,
268
+ parentCollectionIds: currentPropertyDialog.parentCollectionIds
269
+ })
270
+ .catch((e) => {
271
+ console.error(e);
272
+ snackbarController.open({
273
+ type: "error",
274
+ message: "Error persisting property: " + (e.message ?? "Details in the console")
275
+ });
276
+ return false;
277
+ });
278
+ }}
279
+ onPropertyChangedImmediate={false}
280
+ onDelete={() => {
281
+ if (!currentPropertyDialog?.propertyKey) return;
282
+ const newPropertiesOrder = currentPropertyDialog?.currentPropertiesOrder?.filter(p => p !== currentPropertyDialog?.propertyKey);
283
+ return collectionConfigController.deleteProperty({
284
+ path: currentPropertyDialog?.editedCollectionPath,
285
+ propertyKey: currentPropertyDialog?.propertyKey,
286
+ namespace: currentPropertyDialog?.namespace,
287
+ newPropertiesOrder,
288
+ parentCollectionIds: currentPropertyDialog?.parentCollectionIds
289
+ })
290
+ .then(() => {
291
+ setCurrentPropertyDialog(undefined);
292
+ }).catch((e) => {
293
+ console.error(e);
294
+ snackbarController.open({
295
+ type: "error",
296
+ message: "Error deleting property: " + (e.message ?? "Details in the console")
297
+ });
298
+ return false;
299
+ });
300
+ }}
301
+ onError={() => {
302
+ }}
303
+ onOkClicked={() => {
304
+ setCurrentPropertyDialog(undefined);
305
+ }}
306
+ onCancel={() => {
307
+ setCurrentPropertyDialog(undefined);
308
+ }}
309
+ initialErrors={{}}
310
+ forceShowErrors={false}
311
+ existingPropertyKeys={[]}
312
+ allowDataInference={true}
313
+ propertyConfigs={propertyConfigs}
314
+ property={currentPropertyDialog?.property}
315
+ propertyKey={currentPropertyDialog?.propertyKey}/>
316
+
317
+ </CollectionEditorContext.Provider>
318
+
319
+ </ConfigControllerContext.Provider>
320
+ );
321
+ }, equal);
package/src/index.ts ADDED
@@ -0,0 +1,35 @@
1
+ export {
2
+ useCollectionEditorPlugin
3
+ } from "./useCollectionEditorPlugin";
4
+
5
+ export {
6
+ useCollectionEditorController
7
+ } from "./useCollectionEditorController";
8
+ export {
9
+ useCollectionsConfigController
10
+ } from "./useCollectionsConfigController";
11
+
12
+ export {
13
+ editableProperty, removeNonEditableProperties
14
+ } from "./utils/entities";
15
+
16
+ export type {
17
+ CollectionsConfigController, DeleteCollectionParams, SaveCollectionParams
18
+ } from "./types/config_controller";
19
+ export type {
20
+ CollectionEditorController
21
+ } from "./types/collection_editor_controller";
22
+ export type {
23
+ CollectionEditorPermissions, CollectionEditorPermissionsBuilder
24
+ } from "./types/config_permissions";
25
+ export type {
26
+ PersistedCollection
27
+ } from "./types/persisted_collection";
28
+
29
+ export type {
30
+ CollectionInference
31
+ } from "./types/collection_inference";
32
+
33
+ export { MissingReferenceWidget } from "./ui/MissingReferenceWidget";
34
+
35
+ export * from "./ui/collection_editor/util";
@@ -0,0 +1,42 @@
1
+ import { CollectionEditorPermissionsBuilder } from "./config_permissions";
2
+ import { Property } from "@firecms/core";
3
+ import { PersistedCollection } from "./persisted_collection";
4
+
5
+ /**
6
+ * Controller to open the collection editor dialog.
7
+ * @group Hooks and utilities
8
+ */
9
+ export interface CollectionEditorController {
10
+
11
+ editCollection: (props: {
12
+ path?: string,
13
+ fullPath?: string,
14
+ parentCollectionIds: string[],
15
+ parentCollection?: PersistedCollection
16
+ }) => void;
17
+
18
+ createCollection: (props: {
19
+ initialValues?: {
20
+ group?: string,
21
+ path?: string,
22
+ name?: string
23
+ },
24
+ parentCollectionIds: string[],
25
+ parentCollection?: PersistedCollection,
26
+ redirect: boolean
27
+ }) => void;
28
+
29
+ editProperty: (props: {
30
+ propertyKey?: string,
31
+ property?: Property,
32
+ currentPropertiesOrder?: string[],
33
+ editedCollectionPath: string,
34
+ parentCollectionIds: string[],
35
+ collection: PersistedCollection
36
+ }) => void;
37
+
38
+ configPermissions: CollectionEditorPermissionsBuilder;
39
+
40
+ rootPathSuggestions?: string[];
41
+
42
+ }
@@ -0,0 +1,3 @@
1
+ import { EntityCollection } from "@firecms/core";
2
+
3
+ export type CollectionInference = (path: string, collectionGroup: boolean, parentCollectionIds: string[]) => Promise<Partial<EntityCollection> | null>;
@@ -0,0 +1,50 @@
1
+ import { CMSType, Property } from "@firecms/core";
2
+ import { PersistedCollection } from "./persisted_collection";
3
+
4
+ /**
5
+ * Use this controller to access the configuration that is stored externally,
6
+ * and not defined in code.
7
+ */
8
+ export interface CollectionsConfigController {
9
+
10
+ loading: boolean;
11
+
12
+ collections?: PersistedCollection[];
13
+
14
+ saveCollection: <M extends { [Key: string]: CMSType }>(params: SaveCollectionParams<M>) => Promise<void>;
15
+
16
+ saveProperty: (params: SavePropertyParams) => Promise<void>;
17
+ deleteProperty: (params: DeletePropertyParams) => Promise<void>;
18
+
19
+ deleteCollection: (props: DeleteCollectionParams) => Promise<void>;
20
+
21
+ }
22
+
23
+ export type SaveCollectionParams<M extends Record<string, any>> = {
24
+ id: string,
25
+ collectionData: PersistedCollection<M>,
26
+ previousPath?: string,
27
+ parentCollectionIds?: string[]
28
+ }
29
+
30
+ export type SavePropertyParams = {
31
+ path: string,
32
+ propertyKey: string,
33
+ namespace?: string,
34
+ newPropertiesOrder?: string[],
35
+ property: Property,
36
+ parentCollectionIds?: string[]
37
+ }
38
+
39
+ export type DeletePropertyParams = {
40
+ path: string,
41
+ propertyKey: string,
42
+ namespace?: string,
43
+ newPropertiesOrder?: string[],
44
+ parentCollectionIds?: string[]
45
+ }
46
+
47
+ export type DeleteCollectionParams = {
48
+ path: string,
49
+ parentCollectionIds?: string[]
50
+ }
@@ -0,0 +1,20 @@
1
+ import { EntityCollection } from "@firecms/core";
2
+
3
+ export type CollectionEditorPermissionsBuilder<UserType = any, EC extends EntityCollection = EntityCollection> = (params: { user: UserType | null, collection?: EC }) => CollectionEditorPermissions;
4
+
5
+ export type CollectionEditorPermissions = {
6
+ /**
7
+ * Is the user allowed to create new collections.
8
+ */
9
+ createCollections: boolean;
10
+
11
+ /**
12
+ * Is the user allowed to modify this collection
13
+ */
14
+ editCollections: boolean;
15
+
16
+ /**
17
+ * Is the user allowed to delete this collection
18
+ */
19
+ deleteCollections: boolean;
20
+ }
@@ -0,0 +1,9 @@
1
+ import { EntityCollection, User } from "@firecms/core";
2
+
3
+ export type PersistedCollection<M extends Record<string, any> = any, UserType extends User = User>
4
+ = Omit<EntityCollection<M, UserType>, "subcollections"> & {
5
+ // properties: Properties<M>;
6
+ ownerId: string;
7
+ subcollections?: PersistedCollection<any, any>[];
8
+ editable?: boolean;
9
+ }
@@ -0,0 +1,42 @@
1
+ import { IconButton, ResolvedProperty, SettingsIcon, Tooltip } from "@firecms/core";
2
+ import React from "react";
3
+ import { useCollectionEditorController } from "../useCollectionEditorController";
4
+ import { PersistedCollection } from "../types/persisted_collection";
5
+
6
+ export function CollectionViewHeaderAction({
7
+ propertyKey,
8
+ onHover,
9
+ property,
10
+ fullPath,
11
+ parentCollectionIds,
12
+ collection
13
+ }: {
14
+ property: ResolvedProperty,
15
+ propertyKey: string,
16
+ onHover: boolean,
17
+ fullPath: string,
18
+ parentCollectionIds: string[],
19
+ collection: PersistedCollection;
20
+ }) {
21
+
22
+ const collectionEditorController = useCollectionEditorController();
23
+
24
+ return (
25
+ <Tooltip title={"Edit"}>
26
+ <IconButton
27
+ className={onHover ? "bg-white dark:bg-gray-950" : "hidden"}
28
+ onClick={() => {
29
+ collectionEditorController.editProperty({
30
+ propertyKey,
31
+ property,
32
+ editedCollectionPath: fullPath,
33
+ parentCollectionIds,
34
+ collection
35
+ });
36
+ }}
37
+ size={"small"}>
38
+ <SettingsIcon size={"small"}/>
39
+ </IconButton>
40
+ </Tooltip>
41
+ )
42
+ }