@firecms/collection_editor 3.0.0-alpha.8 → 3.0.0-alpha.80

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 (138) hide show
  1. package/dist/ConfigControllerProvider.d.ts +37 -0
  2. package/dist/index.d.ts +11 -0
  3. package/dist/index.es.js +5257 -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 +51 -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/NewCollectionButton.d.ts +1 -0
  17. package/dist/ui/NewCollectionCard.d.ts +2 -0
  18. package/dist/ui/PropertyAddColumnComponent.d.ts +6 -0
  19. package/dist/ui/RootCollectionSuggestions.d.ts +1 -0
  20. package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +10 -0
  21. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +38 -0
  22. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +15 -0
  23. package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +20 -0
  24. package/dist/ui/collection_editor/CollectionYupValidation.d.ts +14 -0
  25. package/dist/ui/collection_editor/EntityCustomViewsSelectDialog.d.ts +4 -0
  26. package/dist/ui/collection_editor/EnumForm.d.ts +13 -0
  27. package/dist/ui/collection_editor/GetCodeDialog.d.ts +5 -0
  28. package/dist/ui/collection_editor/PropertyEditView.d.ts +40 -0
  29. package/dist/ui/collection_editor/PropertyFieldPreview.d.ts +15 -0
  30. package/dist/ui/collection_editor/PropertySelectItem.d.ts +8 -0
  31. package/dist/ui/collection_editor/PropertyTree.d.ts +32 -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 +11 -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/pages_template.d.ts +2 -0
  59. package/dist/ui/collection_editor/templates/products_template.d.ts +2 -0
  60. package/dist/ui/collection_editor/templates/users_template.d.ts +2 -0
  61. package/dist/ui/collection_editor/util.d.ts +4 -0
  62. package/dist/ui/collection_editor/utils/strings.d.ts +1 -0
  63. package/dist/ui/collection_editor/utils/supported_fields.d.ts +3 -0
  64. package/dist/ui/collection_editor/utils/update_property_for_widget.d.ts +2 -0
  65. package/dist/ui/collection_editor/utils/useTraceUpdate.d.ts +1 -0
  66. package/dist/useCollectionEditorController.d.ts +6 -0
  67. package/dist/useCollectionEditorPlugin.d.ts +46 -0
  68. package/dist/useCollectionsConfigController.d.ts +6 -0
  69. package/dist/utils/arrays.d.ts +1 -0
  70. package/dist/utils/entities.d.ts +3 -0
  71. package/package.json +24 -27
  72. package/src/ConfigControllerProvider.tsx +330 -0
  73. package/src/index.ts +35 -0
  74. package/src/types/collection_editor_controller.tsx +42 -0
  75. package/src/types/collection_inference.ts +3 -0
  76. package/src/types/config_controller.tsx +60 -0
  77. package/src/types/config_permissions.ts +20 -0
  78. package/src/types/persisted_collection.ts +9 -0
  79. package/src/ui/CollectionViewHeaderAction.tsx +43 -0
  80. package/src/ui/EditorCollectionAction.tsx +109 -0
  81. package/src/ui/HomePageEditorCollectionAction.tsx +84 -0
  82. package/src/ui/MissingReferenceWidget.tsx +35 -0
  83. package/src/ui/NewCollectionButton.tsx +16 -0
  84. package/src/ui/NewCollectionCard.tsx +47 -0
  85. package/src/ui/PropertyAddColumnComponent.tsx +42 -0
  86. package/src/ui/RootCollectionSuggestions.tsx +55 -0
  87. package/src/ui/collection_editor/CollectionDetailsForm.tsx +366 -0
  88. package/src/ui/collection_editor/CollectionEditorDialog.tsx +754 -0
  89. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +206 -0
  90. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +481 -0
  91. package/src/ui/collection_editor/CollectionYupValidation.tsx +7 -0
  92. package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +37 -0
  93. package/src/ui/collection_editor/EnumForm.tsx +358 -0
  94. package/src/ui/collection_editor/GetCodeDialog.tsx +120 -0
  95. package/src/ui/collection_editor/PropertyEditView.tsx +558 -0
  96. package/src/ui/collection_editor/PropertyFieldPreview.tsx +204 -0
  97. package/src/ui/collection_editor/PropertySelectItem.tsx +32 -0
  98. package/src/ui/collection_editor/PropertyTree.tsx +233 -0
  99. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +253 -0
  100. package/src/ui/collection_editor/UnsavedChangesDialog.tsx +47 -0
  101. package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +37 -0
  102. package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +272 -0
  103. package/src/ui/collection_editor/import/clean_import_data.ts +53 -0
  104. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +135 -0
  105. package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +36 -0
  106. package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +137 -0
  107. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +87 -0
  108. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +117 -0
  109. package/src/ui/collection_editor/properties/FieldHelperView.tsx +13 -0
  110. package/src/ui/collection_editor/properties/KeyValuePropertyField.tsx +20 -0
  111. package/src/ui/collection_editor/properties/MapPropertyField.tsx +149 -0
  112. package/src/ui/collection_editor/properties/NumberPropertyField.tsx +38 -0
  113. package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +182 -0
  114. package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +108 -0
  115. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +194 -0
  116. package/src/ui/collection_editor/properties/StringPropertyField.tsx +79 -0
  117. package/src/ui/collection_editor/properties/UrlPropertyField.tsx +89 -0
  118. package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +36 -0
  119. package/src/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +50 -0
  120. package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +50 -0
  121. package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +100 -0
  122. package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +132 -0
  123. package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +28 -0
  124. package/src/ui/collection_editor/templates/blog_template.ts +115 -0
  125. package/src/ui/collection_editor/templates/pages_template.ts +188 -0
  126. package/src/ui/collection_editor/templates/products_template.ts +88 -0
  127. package/src/ui/collection_editor/templates/users_template.ts +42 -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 +137 -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/vite-env.d.ts +1 -0
@@ -0,0 +1,4 @@
1
+ export declare function idToPropertiesPath(id: string): string;
2
+ export declare function namespaceToPropertiesPath(namespace?: string): string;
3
+ export declare function namespaceToPropertiesOrderPath(namespace?: string): string;
4
+ export declare function getFullId(propertyKey: string, propertyNamespace?: string): string;
@@ -0,0 +1 @@
1
+ export declare function camelCase(str: string): string;
@@ -0,0 +1,3 @@
1
+ import { FieldConfigId, PropertyConfig } from "@firecms/core";
2
+ export declare const supportedFieldsIds: FieldConfigId[];
3
+ export declare const supportedFields: Record<string, PropertyConfig>;
@@ -0,0 +1,2 @@
1
+ import { Property, PropertyConfig } from "@firecms/core";
2
+ export declare function updatePropertyFromWidget(propertyData: any, selectedWidgetId: string | undefined, propertyConfigs: Record<string, PropertyConfig>): Property;
@@ -0,0 +1 @@
1
+ export declare function useTraceUpdate(props: any): void;
@@ -0,0 +1,6 @@
1
+ import { CollectionEditorController } from "./types/collection_editor_controller";
2
+ /**
3
+ * Hook to access the collection editor controller.
4
+ * The methods in this controller can be used to open the collection editor dialog.
5
+ */
6
+ export declare const useCollectionEditorController: () => CollectionEditorController;
@@ -0,0 +1,46 @@
1
+ import React from "react";
2
+ import { EntityCollection, FireCMSPlugin, ModifyCollectionProps, User } from "@firecms/core";
3
+ import { CollectionEditorPermissionsBuilder } from "./types/config_permissions";
4
+ import { PersistedCollection } from "./types/persisted_collection";
5
+ import { CollectionInference } from "./types/collection_inference";
6
+ import { CollectionsConfigController } from "./types/config_controller";
7
+ export interface CollectionConfigControllerProps<EC extends PersistedCollection = PersistedCollection, UserType extends User = User> {
8
+ /**
9
+ * Firebase app where the configuration is saved.
10
+ */
11
+ collectionConfigController: CollectionsConfigController;
12
+ modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | void;
13
+ /**
14
+ * Define what actions can be performed on the configuration.
15
+ */
16
+ configPermissions?: CollectionEditorPermissionsBuilder<UserType, EC>;
17
+ /**
18
+ * The words you define here will not be allowed to be used as group
19
+ * names when creating collections.
20
+ * e.g. ["admin"]
21
+ */
22
+ reservedGroups: string[];
23
+ extraView?: {
24
+ View: React.ComponentType<{
25
+ path: string;
26
+ }>;
27
+ icon: React.ReactNode;
28
+ };
29
+ pathSuggestions?: (path: string) => Promise<string[]>;
30
+ collectionInference?: CollectionInference;
31
+ getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
32
+ getUser: (uid: string) => UserType | null;
33
+ onAnalyticsEvent?: (event: string, params?: object) => void;
34
+ }
35
+ /**
36
+ * Use this hook to initialise the Collection Editor plugin.
37
+ * This is likely the only hook you will need to use.
38
+ * @param firebaseApp Firebase app where your project data lives.
39
+ * @param configPermissions
40
+ * @param reservedGroups
41
+ * @param extraView
42
+ * @param pathSuggestions
43
+ * @param getUser
44
+ * @param collectionInference
45
+ */
46
+ export declare function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, UserType extends User = User>({ collectionConfigController, modifyCollection, configPermissions, reservedGroups, extraView, pathSuggestions, getUser, collectionInference, getData, onAnalyticsEvent }: CollectionConfigControllerProps<EC, UserType>): FireCMSPlugin<any, any, PersistedCollection>;
@@ -0,0 +1,6 @@
1
+ import { CollectionsConfigController } from "./types/config_controller";
2
+ /**
3
+ * Use this hook to access the configuration controller.
4
+ * You can use it to get the list of collections, and to save/delete collections.
5
+ */
6
+ export declare const useCollectionsConfigController: () => CollectionsConfigController;
@@ -0,0 +1 @@
1
+ export declare function toArray<T>(input?: T | T[]): T[];
@@ -0,0 +1,3 @@
1
+ import { Properties, PropertiesOrBuilders, PropertyOrBuilder } from "@firecms/core";
2
+ export declare function editableProperty(property: PropertyOrBuilder | PropertyOrBuilder): boolean;
3
+ export declare function removeNonEditableProperties(properties: PropertiesOrBuilders<any>): Properties;
package/package.json CHANGED
@@ -1,20 +1,17 @@
1
1
  {
2
2
  "name": "@firecms/collection_editor",
3
- "version": "3.0.0-alpha.8",
3
+ "type": "module",
4
+ "version": "3.0.0-alpha.80",
4
5
  "main": "./dist/index.umd.js",
5
6
  "module": "./dist/index.es.js",
6
7
  "types": "dist/index.d.ts",
7
8
  "source": "src/index.ts",
8
- "exports": {
9
- ".": {
10
- "import": "./dist/index.es.js",
11
- "require": "./dist/index.umd.js"
12
- }
13
- },
14
9
  "dependencies": {
15
- "@firecms/data_import": "^3.0.0-alpha.8",
16
- "@firecms/schema_inference": "^3.0.0-alpha.8",
17
- "flexsearch": "0.7.31"
10
+ "@firecms/data_import_export": "^3.0.0-alpha.80",
11
+ "@firecms/schema_inference": "^3.0.0-alpha.80",
12
+ "@firecms/ui": "^3.0.0-alpha.80",
13
+ "json5": "^2.2.3",
14
+ "prism-react-renderer": "^2.3.0"
18
15
  },
19
16
  "peerDependencies": {
20
17
  "react": "^18.2.0",
@@ -25,7 +22,8 @@
25
22
  "scripts": {
26
23
  "dev": "vite",
27
24
  "test": "jest",
28
- "build": "vite build && tsc --emitDeclarationOnly"
25
+ "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
26
+ "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
29
27
  },
30
28
  "eslintConfig": {
31
29
  "extends": [
@@ -47,33 +45,32 @@
47
45
  },
48
46
  "devDependencies": {
49
47
  "@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",
48
+ "@types/react": "^18.2.45",
49
+ "@types/react-dom": "^18.2.17",
50
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
51
+ "@typescript-eslint/parser": "^5.62.0",
52
+ "@vitejs/plugin-react": "^4.2.1",
53
+ "eslint": "^8.55.0",
56
54
  "eslint-config-standard": "^17.1.0",
57
- "eslint-plugin-import": "^2.27.5",
55
+ "eslint-plugin-import": "^2.29.1",
58
56
  "eslint-plugin-n": "^15.7.0",
59
57
  "eslint-plugin-promise": "^6.1.1",
60
- "eslint-plugin-react": "^7.32.2",
58
+ "eslint-plugin-react": "^7.33.2",
61
59
  "eslint-plugin-react-hooks": "^4.6.0",
62
60
  "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",
61
+ "react-router": "^6.21.0",
62
+ "react-router-dom": "^6.21.0",
67
63
  "ts-jest": "^29.1.1",
68
- "typescript": "^5.2.2",
69
- "vite": "^4.3.9",
64
+ "typescript": "^5.3.3",
65
+ "vite": "^4.5.1",
70
66
  "vite-plugin-fonts": "^0.7.0"
71
67
  },
72
68
  "files": [
73
- "dist"
69
+ "dist",
70
+ "src"
74
71
  ],
75
72
  "publishConfig": {
76
73
  "access": "public"
77
74
  },
78
- "gitHead": "85611c918afa8321f1710b05ddc15f7a5354d077"
75
+ "gitHead": "60fbe594a5ad36fa5a47ba279ef3f55014fe823f"
79
76
  }
@@ -0,0 +1,330 @@
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, parentPaths: string[]) => Promise<object[]>;
50
+
51
+ onAnalyticsEvent?: (event: string, params?: object) => void;
52
+
53
+ }
54
+
55
+ export const ConfigControllerProvider = React.memo(
56
+ function ConfigControllerProvider({
57
+ children,
58
+ collectionConfigController,
59
+ configPermissions,
60
+ reservedGroups,
61
+ collectionInference,
62
+ extraView,
63
+ pathSuggestions,
64
+ getUser,
65
+ getData,
66
+ onAnalyticsEvent
67
+ }: PropsWithChildren<ConfigControllerProviderProps>) {
68
+
69
+ const navigation = useNavigationController();
70
+ const navigate = useNavigate();
71
+ const snackbarController = useSnackbarController();
72
+ const { propertyConfigs } = useFireCMSContext();
73
+
74
+ const {
75
+ collections
76
+ } = navigation;
77
+ const existingPaths = collections.map(col => col.path.trim().toLowerCase());
78
+
79
+ const [rootPathSuggestions, setRootPathSuggestions] = React.useState<string[] | undefined>();
80
+ useEffect(() => {
81
+ if (pathSuggestions) {
82
+ pathSuggestions().then((paths) => {
83
+ setRootPathSuggestions(paths.filter(p => !existingPaths.includes(p.trim().toLowerCase())));
84
+ });
85
+ }
86
+ }, [pathSuggestions]);
87
+
88
+ const [currentDialog, setCurrentDialog] = React.useState<{
89
+ isNewCollection: boolean,
90
+ parentCollection?: PersistedCollection,
91
+ editedCollectionPath?: string,
92
+ fullPath?: string,
93
+ parentCollectionIds: string[],
94
+ initialValues?: {
95
+ path?: string,
96
+ group?: string,
97
+ name?: string
98
+ },
99
+ redirect: boolean
100
+ }>();
101
+
102
+ const [currentPropertyDialog, setCurrentPropertyDialog] = React.useState<{
103
+ propertyKey?: string,
104
+ property?: Property,
105
+ namespace?: string,
106
+ parentCollection?: PersistedCollection,
107
+ currentPropertiesOrder?: string[],
108
+ editedCollectionPath: string,
109
+ fullPath?: string,
110
+ parentCollectionIds: string[],
111
+ collectionEditable: boolean;
112
+ }>();
113
+
114
+ const defaultConfigPermissions: CollectionEditorPermissionsBuilder = useCallback(() => ({
115
+ createCollections: true,
116
+ editCollections: true,
117
+ deleteCollections: true
118
+ }), []);
119
+
120
+ const editCollection = useCallback(({
121
+ path,
122
+ fullPath,
123
+ parentCollectionIds,
124
+ parentCollection
125
+ }: {
126
+ path?: string,
127
+ fullPath?: string,
128
+ parentCollectionIds: string[],
129
+ parentCollection?: PersistedCollection
130
+ }) => {
131
+ console.debug("edit collection", path, fullPath, parentCollectionIds, parentCollection);
132
+ onAnalyticsEvent?.("edit_collection", { path, fullPath });
133
+ setCurrentDialog({
134
+ editedCollectionPath: path,
135
+ fullPath,
136
+ parentCollectionIds,
137
+ isNewCollection: false,
138
+ parentCollection,
139
+ redirect: false
140
+ });
141
+ }, []);
142
+
143
+ const editProperty = useCallback(({
144
+ propertyKey,
145
+ property,
146
+ editedCollectionPath,
147
+ currentPropertiesOrder,
148
+ parentCollectionIds,
149
+ collection
150
+ }: {
151
+ propertyKey?: string,
152
+ property?: Property,
153
+ currentPropertiesOrder?: string[],
154
+ editedCollectionPath: string,
155
+ parentCollectionIds: string[],
156
+ collection: PersistedCollection,
157
+ }) => {
158
+ console.debug("edit property", propertyKey, property, editedCollectionPath, currentPropertiesOrder, parentCollectionIds, collection);
159
+ onAnalyticsEvent?.("edit_property", { propertyKey, editedCollectionPath });
160
+ // namespace is all the path until the last dot
161
+ const namespace = propertyKey && propertyKey.includes(".")
162
+ ? propertyKey.substring(0, propertyKey.lastIndexOf("."))
163
+ : undefined;
164
+ const propertyKeyWithoutNamespace = propertyKey && propertyKey.includes(".")
165
+ ? propertyKey.substring(propertyKey.lastIndexOf(".") + 1)
166
+ : propertyKey;
167
+ setCurrentPropertyDialog({
168
+ propertyKey: propertyKeyWithoutNamespace,
169
+ property,
170
+ namespace,
171
+ currentPropertiesOrder,
172
+ editedCollectionPath,
173
+ parentCollectionIds,
174
+ collectionEditable: collection?.editable ?? false
175
+ });
176
+ }, []);
177
+
178
+ const createCollection = React.useCallback(({
179
+ parentCollectionIds,
180
+ parentCollection,
181
+ initialValues,
182
+ redirect
183
+ }: {
184
+ parentCollectionIds: string[],
185
+ parentCollection?: PersistedCollection
186
+ initialValues?: {
187
+ group?: string,
188
+ path?: string,
189
+ name?: string
190
+ },
191
+ redirect: boolean
192
+ }) => {
193
+ console.debug("create collection", parentCollectionIds, parentCollection, initialValues, redirect);
194
+ onAnalyticsEvent?.("create_collection", { parentCollectionIds, parentCollection, initialValues, redirect });
195
+ setCurrentDialog({
196
+ isNewCollection: true,
197
+ parentCollectionIds,
198
+ parentCollection,
199
+ initialValues,
200
+ redirect
201
+ });
202
+ }, []);
203
+
204
+ const getPathSuggestions = !pathSuggestions
205
+ ? undefined
206
+ : (path?: string) => {
207
+ if (!path && rootPathSuggestions)
208
+ return Promise.resolve(rootPathSuggestions);
209
+ else {
210
+ return pathSuggestions?.(path);
211
+ }
212
+ }
213
+
214
+ return (
215
+ <ConfigControllerContext.Provider value={collectionConfigController}>
216
+ <CollectionEditorContext.Provider
217
+ value={{
218
+ editCollection,
219
+ createCollection,
220
+ editProperty,
221
+ configPermissions: configPermissions ?? defaultConfigPermissions,
222
+ rootPathSuggestions
223
+ }}>
224
+
225
+ {children}
226
+
227
+ <CollectionEditorDialog
228
+ open={Boolean(currentDialog)}
229
+ configController={collectionConfigController}
230
+ isNewCollection={false}
231
+ collectionInference={collectionInference}
232
+ {...currentDialog}
233
+ getData={getData}
234
+ reservedGroups={reservedGroups}
235
+ extraView={extraView}
236
+ pathSuggestions={getPathSuggestions}
237
+ getUser={getUser}
238
+ handleClose={(collection) => {
239
+ if (currentDialog?.redirect) {
240
+ if (collection && currentDialog?.isNewCollection && !currentDialog.parentCollectionIds.length) {
241
+ const url = navigation.buildUrlCollectionPath(collection.id ?? collection.path);
242
+ navigate(url);
243
+ }
244
+ }
245
+ setCurrentDialog(undefined);
246
+ }}/>
247
+
248
+ {/* Used for editing properties*/}
249
+ <PropertyFormDialog
250
+ open={Boolean(currentPropertyDialog)}
251
+ includeIdAndName={true}
252
+ existingProperty={Boolean(currentPropertyDialog?.propertyKey)}
253
+ autoUpdateId={!currentPropertyDialog ? false : !currentPropertyDialog?.propertyKey}
254
+ autoOpenTypeSelect={!currentPropertyDialog ? false : !currentPropertyDialog?.propertyKey}
255
+ inArray={false}
256
+ collectionEditable={currentPropertyDialog?.collectionEditable ?? false}
257
+ getData={getData && currentPropertyDialog?.editedCollectionPath
258
+ ? () => {
259
+ console.debug("get data for property", currentPropertyDialog?.editedCollectionPath);
260
+ const resolvedPath = navigation.resolveAliasesFrom(currentPropertyDialog.editedCollectionPath!)
261
+ return getData(resolvedPath, []);
262
+ }
263
+ : undefined}
264
+ onPropertyChanged={({
265
+ id,
266
+ property
267
+ }) => {
268
+ if (!currentPropertyDialog) return;
269
+ if (!id) return;
270
+ const newProperty = !(currentPropertyDialog.propertyKey);
271
+ return collectionConfigController.saveProperty({
272
+ path: currentPropertyDialog?.editedCollectionPath,
273
+ property,
274
+ propertyKey: id,
275
+ newPropertiesOrder: newProperty && currentPropertyDialog.currentPropertiesOrder ? [...currentPropertyDialog.currentPropertiesOrder, id] : undefined,
276
+ namespace: currentPropertyDialog.namespace,
277
+ parentCollectionIds: currentPropertyDialog.parentCollectionIds
278
+ })
279
+ .catch((e) => {
280
+ console.error(e);
281
+ snackbarController.open({
282
+ type: "error",
283
+ message: "Error persisting property: " + (e.message ?? "Details in the console")
284
+ });
285
+ return false;
286
+ });
287
+ }}
288
+ onPropertyChangedImmediate={false}
289
+ onDelete={() => {
290
+ if (!currentPropertyDialog?.propertyKey) return;
291
+ const newPropertiesOrder = currentPropertyDialog?.currentPropertiesOrder?.filter(p => p !== currentPropertyDialog?.propertyKey);
292
+ return collectionConfigController.deleteProperty({
293
+ path: currentPropertyDialog?.editedCollectionPath,
294
+ propertyKey: currentPropertyDialog?.propertyKey,
295
+ namespace: currentPropertyDialog?.namespace,
296
+ newPropertiesOrder,
297
+ parentCollectionIds: currentPropertyDialog?.parentCollectionIds
298
+ })
299
+ .then(() => {
300
+ setCurrentPropertyDialog(undefined);
301
+ }).catch((e) => {
302
+ console.error(e);
303
+ snackbarController.open({
304
+ type: "error",
305
+ message: "Error deleting property: " + (e.message ?? "Details in the console")
306
+ });
307
+ return false;
308
+ });
309
+ }}
310
+ onError={() => {
311
+ }}
312
+ onOkClicked={() => {
313
+ setCurrentPropertyDialog(undefined);
314
+ }}
315
+ onCancel={() => {
316
+ setCurrentPropertyDialog(undefined);
317
+ }}
318
+ initialErrors={{}}
319
+ forceShowErrors={false}
320
+ existingPropertyKeys={[]}
321
+ allowDataInference={true}
322
+ propertyConfigs={propertyConfigs}
323
+ property={currentPropertyDialog?.property}
324
+ propertyKey={currentPropertyDialog?.propertyKey}/>
325
+
326
+ </CollectionEditorContext.Provider>
327
+
328
+ </ConfigControllerContext.Provider>
329
+ );
330
+ }, 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, UpdateCollectionParams
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,60 @@
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
+ getCollection: (id: string) => PersistedCollection;
15
+
16
+ saveCollection: <M extends { [Key: string]: CMSType }>(params: SaveCollectionParams<M>) => Promise<void>;
17
+ updateCollection: <M extends { [Key: string]: CMSType }>(params: UpdateCollectionParams<M>) => Promise<void>;
18
+
19
+ saveProperty: (params: SavePropertyParams) => Promise<void>;
20
+ deleteProperty: (params: DeletePropertyParams) => Promise<void>;
21
+
22
+ deleteCollection: (props: DeleteCollectionParams) => Promise<void>;
23
+
24
+ }
25
+
26
+ export type UpdateCollectionParams<M extends Record<string, any>> = {
27
+ id: string,
28
+ collectionData: Partial<PersistedCollection<M>>,
29
+ previousPath?: string,
30
+ parentCollectionIds?: string[]
31
+ }
32
+
33
+ export type SaveCollectionParams<M extends Record<string, any>> = {
34
+ id: string,
35
+ collectionData: PersistedCollection<M>,
36
+ previousPath?: string,
37
+ parentCollectionIds?: string[]
38
+ }
39
+
40
+ export type SavePropertyParams = {
41
+ path: string,
42
+ propertyKey: string,
43
+ namespace?: string,
44
+ newPropertiesOrder?: string[],
45
+ property: Property,
46
+ parentCollectionIds?: string[]
47
+ }
48
+
49
+ export type DeletePropertyParams = {
50
+ path: string,
51
+ propertyKey: string,
52
+ namespace?: string,
53
+ newPropertiesOrder?: string[],
54
+ parentCollectionIds?: string[]
55
+ }
56
+
57
+ export type DeleteCollectionParams = {
58
+ path: string,
59
+ parentCollectionIds?: string[]
60
+ }