@firecms/collection_editor 3.0.0-canary.13 → 3.0.0-canary.131

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 (58) hide show
  1. package/LICENSE +114 -21
  2. package/dist/ConfigControllerProvider.d.ts +11 -2
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.es.js +4715 -3491
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/index.umd.js +6685 -3
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/types/collection_editor_controller.d.ts +14 -2
  9. package/dist/types/collection_inference.d.ts +1 -1
  10. package/dist/ui/CollectionViewHeaderAction.d.ts +3 -2
  11. package/dist/ui/EditorCollectionActionStart.d.ts +2 -0
  12. package/dist/ui/PropertyAddColumnComponent.d.ts +3 -1
  13. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +4 -3
  14. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +1 -1
  15. package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +1 -1
  16. package/dist/ui/collection_editor/PropertyTree.d.ts +9 -9
  17. package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +1 -1
  18. package/dist/ui/collection_editor/properties/MarkdownPropertyField.d.ts +4 -0
  19. package/dist/ui/collection_editor/properties/StringPropertyField.d.ts +1 -1
  20. package/dist/useCollectionEditorPlugin.d.ts +15 -9
  21. package/dist/utils/collections.d.ts +6 -0
  22. package/package.json +20 -34
  23. package/src/ConfigControllerProvider.tsx +75 -63
  24. package/src/index.ts +1 -0
  25. package/src/types/collection_editor_controller.tsx +14 -4
  26. package/src/types/collection_inference.ts +1 -1
  27. package/src/ui/CollectionViewHeaderAction.tsx +9 -4
  28. package/src/ui/EditorCollectionAction.tsx +10 -63
  29. package/src/ui/EditorCollectionActionStart.tsx +88 -0
  30. package/src/ui/HomePageEditorCollectionAction.tsx +18 -13
  31. package/src/ui/NewCollectionButton.tsx +12 -10
  32. package/src/ui/NewCollectionCard.tsx +3 -3
  33. package/src/ui/PropertyAddColumnComponent.tsx +9 -4
  34. package/src/ui/collection_editor/CollectionDetailsForm.tsx +69 -8
  35. package/src/ui/collection_editor/CollectionEditorDialog.tsx +57 -32
  36. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +6 -5
  37. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +33 -27
  38. package/src/ui/collection_editor/GetCodeDialog.tsx +15 -3
  39. package/src/ui/collection_editor/PropertyEditView.tsx +21 -13
  40. package/src/ui/collection_editor/PropertyFieldPreview.tsx +3 -6
  41. package/src/ui/collection_editor/PropertySelectItem.tsx +3 -3
  42. package/src/ui/collection_editor/PropertyTree.tsx +7 -5
  43. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +26 -19
  44. package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +25 -9
  45. package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +9 -7
  46. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +14 -8
  47. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +50 -47
  48. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +1 -1
  49. package/src/ui/collection_editor/properties/MapPropertyField.tsx +5 -5
  50. package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +139 -0
  51. package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +0 -1
  52. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +31 -16
  53. package/src/ui/collection_editor/properties/StringPropertyField.tsx +1 -10
  54. package/src/ui/collection_editor/templates/pages_template.ts +1 -6
  55. package/src/useCollectionEditorPlugin.tsx +37 -27
  56. package/src/utils/collections.ts +30 -0
  57. package/dist/ui/RootCollectionSuggestions.d.ts +0 -3
  58. package/src/ui/RootCollectionSuggestions.tsx +0 -63
@@ -1,5 +1,6 @@
1
+ import React from "react";
1
2
  import { CollectionEditorPermissionsBuilder } from "./config_permissions";
2
- import { Property } from "@firecms/core";
3
+ import { Entity, Property } from "@firecms/core";
3
4
  import { PersistedCollection } from "./persisted_collection";
4
5
  /**
5
6
  * Controller to open the collection editor dialog.
@@ -11,6 +12,7 @@ export interface CollectionEditorController {
11
12
  fullPath?: string;
12
13
  parentCollectionIds: string[];
13
14
  parentCollection?: PersistedCollection;
15
+ existingEntities?: Entity<any>[];
14
16
  }) => void;
15
17
  createCollection: (props: {
16
18
  initialValues?: {
@@ -30,7 +32,17 @@ export interface CollectionEditorController {
30
32
  editedCollectionId: string;
31
33
  parentCollectionIds: string[];
32
34
  collection: PersistedCollection;
35
+ existingEntities: Entity<any>[];
33
36
  }) => void;
34
37
  configPermissions: CollectionEditorPermissionsBuilder;
35
- rootPathSuggestions?: string[];
38
+ getPathSuggestions?: (path: string) => Promise<string[]>;
39
+ components?: {
40
+ /**
41
+ * Custom component to render the database field
42
+ */
43
+ DatabaseField?: React.ComponentType<{
44
+ databaseId?: string;
45
+ onDatabaseIdUpdate: (databaseId: string) => void;
46
+ }>;
47
+ };
36
48
  }
@@ -1,2 +1,2 @@
1
1
  import { EntityCollection } from "@firecms/core";
2
- export type CollectionInference = (path: string, collectionGroup: boolean, parentCollectionIds: string[]) => Promise<Partial<EntityCollection> | null>;
2
+ export type CollectionInference = (path: string, collectionGroup: boolean, parentCollectionPaths: string[]) => Promise<Partial<EntityCollection> | null>;
@@ -1,10 +1,11 @@
1
- import { ResolvedProperty } from "@firecms/core";
1
+ import { EntityTableController, ResolvedProperty } from "@firecms/core";
2
2
  import { PersistedCollection } from "../types/persisted_collection";
3
- export declare function CollectionViewHeaderAction({ propertyKey, onHover, property, fullPath, parentCollectionIds, collection }: {
3
+ export declare function CollectionViewHeaderAction({ propertyKey, onHover, property, fullPath, parentCollectionIds, collection, tableController }: {
4
4
  property: ResolvedProperty;
5
5
  propertyKey: string;
6
6
  onHover: boolean;
7
7
  fullPath: string;
8
8
  parentCollectionIds: string[];
9
9
  collection: PersistedCollection;
10
+ tableController: EntityTableController;
10
11
  }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ import { CollectionActionsProps } from "@firecms/core";
2
+ export declare function EditorCollectionActionStart({ path: fullPath, parentCollectionIds, collection, tableController }: CollectionActionsProps): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,8 @@
1
+ import { EntityTableController } from "@firecms/core";
1
2
  import { PersistedCollection } from "../types/persisted_collection";
2
- export declare function PropertyAddColumnComponent({ fullPath, parentCollectionIds, collection }: {
3
+ export declare function PropertyAddColumnComponent({ fullPath, parentCollectionIds, collection, tableController }: {
3
4
  fullPath: string;
4
5
  parentCollectionIds: string[];
5
6
  collection: PersistedCollection;
7
+ tableController: EntityTableController;
6
8
  }): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { EntityCollection, User } from "@firecms/core";
2
+ import { Entity, EntityCollection, User } from "@firecms/core";
3
3
  import { CollectionsConfigController } from "../../types/config_controller";
4
4
  import { CollectionInference } from "../../types/collection_inference";
5
5
  import { PersistedCollection } from "../../types/persisted_collection";
@@ -25,12 +25,13 @@ export interface CollectionEditorDialogProps {
25
25
  icon: React.ReactNode;
26
26
  };
27
27
  pathSuggestions?: (path?: string) => Promise<string[]>;
28
- getUser: (uid: string) => User | null;
28
+ getUser?: (uid: string) => User | null;
29
29
  getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
30
30
  parentCollection?: PersistedCollection;
31
+ existingEntities?: Entity<any>[];
31
32
  }
32
33
  export declare function CollectionEditorDialog(props: CollectionEditorDialogProps): import("react/jsx-runtime").JSX.Element;
33
- export declare function CollectionEditor<M extends Record<string, any>>(props: CollectionEditorDialogProps & {
34
+ export declare function CollectionEditor(props: CollectionEditorDialogProps & {
34
35
  handleCancel: () => void;
35
36
  setFormDirty: (dirty: boolean) => void;
36
37
  }): import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,7 @@ export declare function CollectionEditorWelcomeView({ path, pathSuggestions, par
4
4
  path: string;
5
5
  pathSuggestions?: (path: string) => Promise<string[]>;
6
6
  parentCollection?: EntityCollection;
7
- onContinue: (importData?: object[]) => void;
7
+ onContinue: (importData?: object[], propertiesOrder?: string[]) => void;
8
8
  existingCollectionPaths?: string[];
9
9
  }): import("react/jsx-runtime").JSX.Element;
10
10
  export declare function TemplateButton({ title, subtitle, icon, onClick }: {
@@ -9,7 +9,7 @@ type CollectionEditorFormProps = {
9
9
  setDirty?: (dirty: boolean) => void;
10
10
  reservedGroups?: string[];
11
11
  extraIcon: React.ReactNode;
12
- getUser: (uid: string) => User | null;
12
+ getUser?: (uid: string) => User | null;
13
13
  getData?: () => Promise<object[]>;
14
14
  doCollectionInference: (collection: PersistedCollection) => Promise<Partial<EntityCollection> | null> | undefined;
15
15
  propertyConfigs: Record<string, PropertyConfig>;
@@ -4,17 +4,17 @@ import { DraggableProvided } from "@hello-pangea/dnd";
4
4
  export declare const PropertyTree: React.MemoExoticComponent<(<M extends {
5
5
  [Key: string]: CMSType;
6
6
  }>({ namespace, selectedPropertyKey, onPropertyClick, properties, propertiesOrder: propertiesOrderProp, additionalFields, errors, onPropertyMove, onPropertyRemove, className, inferredPropertyKeys, collectionEditable }: {
7
- namespace?: string | undefined;
8
- selectedPropertyKey?: string | undefined;
9
- onPropertyClick?: ((propertyKey: string, namespace?: string) => void) | undefined;
7
+ namespace?: string;
8
+ selectedPropertyKey?: string;
9
+ onPropertyClick?: (propertyKey: string, namespace?: string) => void;
10
10
  properties: PropertiesOrBuilders<M>;
11
- propertiesOrder?: string[] | undefined;
12
- additionalFields?: AdditionalFieldDelegate<M, import("@firecms/core").User>[] | undefined;
11
+ propertiesOrder?: string[];
12
+ additionalFields?: AdditionalFieldDelegate<M>[];
13
13
  errors: Record<string, any>;
14
- onPropertyMove?: ((propertiesOrder: string[], namespace?: string) => void) | undefined;
15
- onPropertyRemove?: ((propertyKey: string, namespace?: string) => void) | undefined;
16
- className?: string | undefined;
17
- inferredPropertyKeys?: string[] | undefined;
14
+ onPropertyMove?: (propertiesOrder: string[], namespace?: string) => void;
15
+ onPropertyRemove?: (propertyKey: string, namespace?: string) => void;
16
+ className?: string;
17
+ inferredPropertyKeys?: string[];
18
18
  collectionEditable: boolean;
19
19
  }) => import("react/jsx-runtime").JSX.Element)>;
20
20
  export declare function PropertyTreeEntry({ propertyKey, namespace, propertyOrBuilder, additionalField, provided, selectedPropertyKey, errors, onPropertyClick, onPropertyMove, onPropertyRemove, inferredPropertyKeys, collectionEditable }: {
@@ -7,6 +7,6 @@ export declare function SubcollectionsEditTab({ collection, parentCollection, co
7
7
  parentCollection?: EntityCollection;
8
8
  configController: CollectionsConfigController;
9
9
  collectionInference?: CollectionInference;
10
- getUser: (uid: string) => User | null;
10
+ getUser?: (uid: string) => User | null;
11
11
  parentCollectionIds?: string[];
12
12
  }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare function MarkdownPropertyField({ disabled, showErrors }: {
2
+ disabled: boolean;
3
+ showErrors: boolean;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  export declare function StringPropertyField({ widgetId, disabled, showErrors }: {
2
- widgetId: "text_field" | "multiline" | "markdown" | "email";
2
+ widgetId: "text_field" | "multiline" | "email";
3
3
  disabled: boolean;
4
4
  showErrors: boolean;
5
5
  }): import("react/jsx-runtime").JSX.Element;
@@ -18,19 +18,27 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
18
18
  * names when creating collections.
19
19
  * e.g. ["admin"]
20
20
  */
21
- reservedGroups: string[];
21
+ reservedGroups?: string[];
22
22
  extraView?: {
23
23
  View: React.ComponentType<{
24
24
  path: string;
25
25
  }>;
26
26
  icon: React.ReactNode;
27
27
  };
28
- pathSuggestions?: (path: string) => Promise<string[]>;
28
+ getPathSuggestions?: (path?: string) => Promise<string[]>;
29
29
  collectionInference?: CollectionInference;
30
30
  getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
31
- getUser: (uid: string) => UserType | null;
31
+ getUser?: (uid: string) => UserType | null;
32
32
  onAnalyticsEvent?: (event: string, params?: object) => void;
33
- introMode?: "new_project" | "existing_project";
33
+ components?: {
34
+ /**
35
+ * Custom component to render the database field
36
+ */
37
+ DatabaseField?: React.ComponentType<{
38
+ databaseId?: string;
39
+ onDatabaseIdUpdate: (databaseId: string) => void;
40
+ }>;
41
+ };
34
42
  }
35
43
  /**
36
44
  * Use this hook to initialise the Collection Editor plugin.
@@ -39,11 +47,9 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
39
47
  * @param configPermissions
40
48
  * @param reservedGroups
41
49
  * @param extraView
42
- * @param pathSuggestions
50
+ * @param getData
43
51
  * @param getUser
44
52
  * @param collectionInference
45
53
  */
46
- export declare function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, UserType extends User = User>({ collectionConfigController, introMode, configPermissions, reservedGroups, extraView, pathSuggestions, getUser, collectionInference, getData, onAnalyticsEvent }: CollectionConfigControllerProps<EC, UserType>): FireCMSPlugin<any, any, PersistedCollection>;
47
- export declare function IntroWidget({ introMode }: {
48
- introMode?: "new_project" | "existing_project";
49
- }): import("react/jsx-runtime").JSX.Element;
54
+ export declare function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, UserType extends User = User>({ collectionConfigController, configPermissions, reservedGroups, extraView, getPathSuggestions, getUser, collectionInference, getData, onAnalyticsEvent, components }: CollectionConfigControllerProps<EC, UserType>): FireCMSPlugin<any, any, PersistedCollection>;
55
+ export declare function IntroWidget({}: {}): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,6 @@
1
+ import { EntityCollection, ModifyCollectionProps } from "@firecms/core";
2
+ import { PersistedCollection } from "../types/persisted_collection";
3
+ /**
4
+ * Function in charge of merging collections defined in code with those stored in the backend.
5
+ */
6
+ export declare const mergeCollections: (baseCollections: EntityCollection[], backendCollections: PersistedCollection[], modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | void) => EntityCollection<any, any>[];
package/package.json CHANGED
@@ -1,24 +1,26 @@
1
1
  {
2
2
  "name": "@firecms/collection_editor",
3
3
  "type": "module",
4
- "version": "3.0.0-canary.13",
4
+ "version": "3.0.0-canary.131",
5
5
  "main": "./dist/index.umd.js",
6
6
  "module": "./dist/index.es.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "source": "src/index.ts",
9
9
  "dependencies": {
10
- "@firecms/data_import_export": "^3.0.0-canary.13",
11
- "@firecms/formex": "^3.0.0-canary.13",
12
- "@firecms/schema_inference": "^3.0.0-canary.13",
13
- "@firecms/ui": "^3.0.0-canary.13",
10
+ "@firecms/data_export": "^3.0.0-canary.131",
11
+ "@firecms/data_import": "^3.0.0-canary.131",
12
+ "@firecms/data_import_export": "^3.0.0-canary.131",
13
+ "@firecms/formex": "^3.0.0-canary.131",
14
+ "@firecms/schema_inference": "^3.0.0-canary.131",
15
+ "@firecms/ui": "^3.0.0-canary.131",
14
16
  "json5": "^2.2.3",
15
17
  "prism-react-renderer": "^2.3.1"
16
18
  },
17
19
  "peerDependencies": {
18
- "react": "^18.2.0",
19
- "react-dom": "^18.2.0",
20
- "react-router": "^6.22.0",
21
- "react-router-dom": "^6.22.0"
20
+ "react": "^18.3.1",
21
+ "react-dom": "^18.3.1",
22
+ "react-router": "^6.25.1",
23
+ "react-router-dom": "^6.25.1"
22
24
  },
23
25
  "exports": {
24
26
  ".": {
@@ -34,12 +36,6 @@
34
36
  "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
35
37
  "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
36
38
  },
37
- "eslintConfig": {
38
- "extends": [
39
- "react-app",
40
- "react-app/jest"
41
- ]
42
- },
43
39
  "browserslist": {
44
40
  "production": [
45
41
  ">0.2%",
@@ -54,25 +50,15 @@
54
50
  },
55
51
  "devDependencies": {
56
52
  "@jest/globals": "^29.7.0",
57
- "@types/react": "^18.2.67",
58
- "@types/react-dom": "^18.2.22",
59
- "@typescript-eslint/eslint-plugin": "^7.3.1",
60
- "@typescript-eslint/parser": "^7.3.1",
61
- "@vitejs/plugin-react": "^4.2.1",
62
- "eslint": "^8.57.0",
63
- "eslint-config-standard": "^17.1.0",
64
- "eslint-plugin-import": "^2.29.1",
65
- "eslint-plugin-n": "^16.6.2",
66
- "eslint-plugin-promise": "^6.1.1",
67
- "eslint-plugin-react": "^7.34.1",
68
- "eslint-plugin-react-hooks": "^4.6.0",
53
+ "@types/react": "^18.3.3",
54
+ "@types/react-dom": "^18.3.0",
55
+ "@vitejs/plugin-react": "^4.3.1",
69
56
  "jest": "^29.7.0",
70
- "react-router": "^6.22.0",
71
- "react-router-dom": "^6.22.0",
72
- "ts-jest": "^29.1.2",
73
- "typescript": "^5.4.2",
74
- "vite": "^5.2.3",
75
- "vite-plugin-fonts": "^0.7.0"
57
+ "react-router": "^6.25.1",
58
+ "react-router-dom": "^6.25.1",
59
+ "ts-jest": "^29.2.3",
60
+ "typescript": "^5.5.4",
61
+ "vite": "^5.3.4"
76
62
  },
77
63
  "files": [
78
64
  "dist",
@@ -81,5 +67,5 @@
81
67
  "publishConfig": {
82
68
  "access": "public"
83
69
  },
84
- "gitHead": "ebc711a9f8a034d71e2b1e54bd7f06d94ce448ef"
70
+ "gitHead": "4ed84e51a0d5d3409f8ea7371c41af4377128110"
85
71
  }
@@ -1,8 +1,9 @@
1
- import React, { PropsWithChildren, useCallback, useEffect } from "react";
1
+ import React, { PropsWithChildren, useCallback } from "react";
2
2
  import equal from "react-fast-compare"
3
3
 
4
4
  import { CollectionsConfigController } from "./types/config_controller";
5
5
  import {
6
+ Entity,
6
7
  Property,
7
8
  useCustomizationController,
8
9
  useNavigationController,
@@ -48,14 +49,21 @@ export interface ConfigControllerProviderProps {
48
49
  icon: React.ReactNode
49
50
  };
50
51
 
51
- pathSuggestions?: (path?: string) => Promise<string[]>;
52
+ getPathSuggestions?: (path?: string) => Promise<string[]>;
52
53
 
53
- getUser: (uid: string) => User | null
54
+ getUser?: (uid: string) => User | null
54
55
 
55
56
  getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
56
57
 
57
58
  onAnalyticsEvent?: (event: string, params?: object) => void;
58
59
 
60
+ components?: {
61
+ /**
62
+ * Custom component to render the database field
63
+ */
64
+ DatabaseField?: React.ComponentType<{ databaseId?: string, onDatabaseIdUpdate: (databaseId:string) => void }>;
65
+ };
66
+
59
67
  }
60
68
 
61
69
  export const ConfigControllerProvider = React.memo(
@@ -66,10 +74,11 @@ export const ConfigControllerProvider = React.memo(
66
74
  reservedGroups,
67
75
  collectionInference,
68
76
  extraView,
69
- pathSuggestions,
77
+ getPathSuggestions,
70
78
  getUser,
71
79
  getData,
72
- onAnalyticsEvent
80
+ onAnalyticsEvent,
81
+ components
73
82
  }: PropsWithChildren<ConfigControllerProviderProps>) {
74
83
 
75
84
  const navigation = useNavigationController();
@@ -77,20 +86,6 @@ export const ConfigControllerProvider = React.memo(
77
86
  const snackbarController = useSnackbarController();
78
87
  const { propertyConfigs } = useCustomizationController();
79
88
 
80
- const {
81
- collections
82
- } = navigation;
83
- const existingPaths = (collections ?? []).map(col => col.path.trim().toLowerCase());
84
-
85
- const [rootPathSuggestions, setRootPathSuggestions] = React.useState<string[] | undefined>();
86
- useEffect(() => {
87
- if (pathSuggestions) {
88
- pathSuggestions().then((paths) => {
89
- setRootPathSuggestions(paths.filter(p => !existingPaths.includes(p.trim().toLowerCase())));
90
- });
91
- }
92
- }, [pathSuggestions]);
93
-
94
89
  const [currentDialog, setCurrentDialog] = React.useState<{
95
90
  isNewCollection: boolean,
96
91
  parentCollection?: PersistedCollection,
@@ -102,7 +97,8 @@ export const ConfigControllerProvider = React.memo(
102
97
  group?: string,
103
98
  name?: string
104
99
  },
105
- redirect: boolean
100
+ redirect: boolean,
101
+ existingEntities?: Entity<any>[]
106
102
  }>();
107
103
 
108
104
  const [currentPropertyDialog, setCurrentPropertyDialog] = React.useState<{
@@ -115,6 +111,7 @@ export const ConfigControllerProvider = React.memo(
115
111
  fullPath?: string,
116
112
  parentCollectionIds: string[],
117
113
  collectionEditable: boolean;
114
+ existingEntities?: Entity<any>[]
118
115
  }>();
119
116
 
120
117
  const defaultConfigPermissions: CollectionEditorPermissionsBuilder = useCallback(() => ({
@@ -123,46 +120,57 @@ export const ConfigControllerProvider = React.memo(
123
120
  deleteCollections: true
124
121
  }), []);
125
122
 
126
- const editCollection = useCallback(({
127
- id,
128
- fullPath,
129
- parentCollectionIds,
130
- parentCollection
131
- }: {
123
+ const editCollection = ({
124
+ id,
125
+ fullPath,
126
+ parentCollectionIds,
127
+ parentCollection,
128
+ existingEntities
129
+ }: {
132
130
  id?: string,
133
131
  fullPath?: string,
134
132
  parentCollectionIds: string[],
135
- parentCollection?: PersistedCollection
133
+ parentCollection?: PersistedCollection,
134
+ existingEntities?: Entity<any>[]
136
135
  }) => {
137
136
  console.debug("Edit collection", id, fullPath, parentCollectionIds, parentCollection);
138
- onAnalyticsEvent?.("edit_collection", { id, fullPath });
137
+ onAnalyticsEvent?.("edit_collection", {
138
+ id,
139
+ fullPath
140
+ });
139
141
  setCurrentDialog({
140
142
  editedCollectionId: id,
141
143
  fullPath,
142
144
  parentCollectionIds,
143
145
  isNewCollection: false,
144
146
  parentCollection,
145
- redirect: false
147
+ redirect: false,
148
+ existingEntities
146
149
  });
147
- }, []);
150
+ };
148
151
 
149
- const editProperty = useCallback(({
150
- propertyKey,
151
- property,
152
- editedCollectionId,
153
- currentPropertiesOrder,
154
- parentCollectionIds,
155
- collection
156
- }: {
152
+ const editProperty = ({
153
+ propertyKey,
154
+ property,
155
+ editedCollectionId,
156
+ currentPropertiesOrder,
157
+ parentCollectionIds,
158
+ collection,
159
+ existingEntities
160
+ }: {
157
161
  propertyKey?: string,
158
162
  property?: Property,
159
163
  currentPropertiesOrder?: string[],
160
164
  editedCollectionId: string,
161
165
  parentCollectionIds: string[],
162
166
  collection: PersistedCollection,
167
+ existingEntities?: Entity<any>[]
163
168
  }) => {
164
169
  console.debug("Edit property", propertyKey, property, editedCollectionId, currentPropertiesOrder, parentCollectionIds, collection);
165
- onAnalyticsEvent?.("edit_property", { propertyKey, editedCollectionId });
170
+ onAnalyticsEvent?.("edit_property", {
171
+ propertyKey,
172
+ editedCollectionId
173
+ });
166
174
  // namespace is all the path until the last dot
167
175
  const namespace = propertyKey && propertyKey.includes(".")
168
176
  ? propertyKey.substring(0, propertyKey.lastIndexOf("."))
@@ -175,19 +183,20 @@ export const ConfigControllerProvider = React.memo(
175
183
  property,
176
184
  namespace,
177
185
  currentPropertiesOrder,
178
- editedCollectionId: editedCollectionId,
186
+ editedCollectionId,
179
187
  parentCollectionIds,
180
- collectionEditable: collection?.editable ?? false
188
+ collectionEditable: collection?.editable ?? false,
189
+ existingEntities
181
190
  });
182
- }, []);
191
+ };
183
192
 
184
- const createCollection = React.useCallback(({
185
- parentCollectionIds,
186
- parentCollection,
187
- initialValues,
188
- redirect,
189
- sourceClick
190
- }: {
193
+ const createCollection = ({
194
+ parentCollectionIds,
195
+ parentCollection,
196
+ initialValues,
197
+ redirect,
198
+ sourceClick
199
+ }: {
191
200
  parentCollectionIds: string[],
192
201
  parentCollection?: PersistedCollection
193
202
  initialValues?: {
@@ -198,8 +207,20 @@ export const ConfigControllerProvider = React.memo(
198
207
  redirect: boolean,
199
208
  sourceClick?: string
200
209
  }) => {
201
- console.debug("Create collection", { parentCollectionIds, parentCollection, initialValues, redirect, sourceClick });
202
- onAnalyticsEvent?.("create_collection", { parentCollectionIds, parentCollection, initialValues, redirect, sourceClick });
210
+ console.debug("Create collection", {
211
+ parentCollectionIds,
212
+ parentCollection,
213
+ initialValues,
214
+ redirect,
215
+ sourceClick
216
+ });
217
+ onAnalyticsEvent?.("create_collection", {
218
+ parentCollectionIds,
219
+ parentCollection,
220
+ initialValues,
221
+ redirect,
222
+ sourceClick
223
+ });
203
224
  setCurrentDialog({
204
225
  isNewCollection: true,
205
226
  parentCollectionIds,
@@ -207,17 +228,7 @@ export const ConfigControllerProvider = React.memo(
207
228
  initialValues,
208
229
  redirect
209
230
  });
210
- }, []);
211
-
212
- const getPathSuggestions = !pathSuggestions
213
- ? undefined
214
- : (path?: string) => {
215
- if (!path && rootPathSuggestions)
216
- return Promise.resolve(rootPathSuggestions);
217
- else {
218
- return pathSuggestions?.(path);
219
- }
220
- }
231
+ };
221
232
 
222
233
  return (
223
234
  <ConfigControllerContext.Provider value={collectionConfigController}>
@@ -227,7 +238,8 @@ export const ConfigControllerProvider = React.memo(
227
238
  createCollection,
228
239
  editProperty,
229
240
  configPermissions: configPermissions ?? defaultConfigPermissions,
230
- rootPathSuggestions
241
+ getPathSuggestions,
242
+ components
231
243
  }}>
232
244
 
233
245
  {children}
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ export {
12
12
  export {
13
13
  editableProperty, removeNonEditableProperties
14
14
  } from "./utils/entities";
15
+ export * from "./utils/collections";
15
16
 
16
17
  export type {
17
18
  CollectionsConfigController, DeleteCollectionParams, SaveCollectionParams, UpdateCollectionParams
@@ -1,5 +1,6 @@
1
+ import React from "react";
1
2
  import { CollectionEditorPermissionsBuilder } from "./config_permissions";
2
- import { Property } from "@firecms/core";
3
+ import { Entity, Property } from "@firecms/core";
3
4
  import { PersistedCollection } from "./persisted_collection";
4
5
 
5
6
  /**
@@ -12,7 +13,8 @@ export interface CollectionEditorController {
12
13
  id?: string,
13
14
  fullPath?: string,
14
15
  parentCollectionIds: string[],
15
- parentCollection?: PersistedCollection
16
+ parentCollection?: PersistedCollection,
17
+ existingEntities?: Entity<any>[]
16
18
  }) => void;
17
19
 
18
20
  createCollection: (props: {
@@ -33,11 +35,19 @@ export interface CollectionEditorController {
33
35
  currentPropertiesOrder?: string[],
34
36
  editedCollectionId: string,
35
37
  parentCollectionIds: string[],
36
- collection: PersistedCollection
38
+ collection: PersistedCollection,
39
+ existingEntities: Entity<any>[]
37
40
  }) => void;
38
41
 
39
42
  configPermissions: CollectionEditorPermissionsBuilder;
40
43
 
41
- rootPathSuggestions?: string[];
44
+ getPathSuggestions?: (path: string) => Promise<string[]>;
45
+
46
+ components?: {
47
+ /**
48
+ * Custom component to render the database field
49
+ */
50
+ DatabaseField?: React.ComponentType<{ databaseId?: string, onDatabaseIdUpdate: (databaseId: string) => void }>;
51
+ };
42
52
 
43
53
  }
@@ -1,3 +1,3 @@
1
1
  import { EntityCollection } from "@firecms/core";
2
2
 
3
- export type CollectionInference = (path: string, collectionGroup: boolean, parentCollectionIds: string[]) => Promise<Partial<EntityCollection> | null>;
3
+ export type CollectionInference = (path: string, collectionGroup: boolean, parentCollectionPaths: string[]) => Promise<Partial<EntityCollection> | null>;
@@ -1,4 +1,4 @@
1
- import { ResolvedProperty } from "@firecms/core";
1
+ import { EntityTableController, ResolvedProperty } from "@firecms/core";
2
2
  import { IconButton, SettingsIcon, Tooltip } from "@firecms/ui";
3
3
  import React from "react";
4
4
  import { useCollectionEditorController } from "../useCollectionEditorController";
@@ -10,7 +10,8 @@ export function CollectionViewHeaderAction({
10
10
  property,
11
11
  fullPath,
12
12
  parentCollectionIds,
13
- collection
13
+ collection,
14
+ tableController
14
15
  }: {
15
16
  property: ResolvedProperty,
16
17
  propertyKey: string,
@@ -18,12 +19,15 @@ export function CollectionViewHeaderAction({
18
19
  fullPath: string,
19
20
  parentCollectionIds: string[],
20
21
  collection: PersistedCollection;
22
+ tableController: EntityTableController;
21
23
  }) {
22
24
 
23
25
  const collectionEditorController = useCollectionEditorController();
24
26
 
25
27
  return (
26
- <Tooltip title={"Edit"}>
28
+ <Tooltip
29
+ asChild={true}
30
+ title={"Edit"}>
27
31
  <IconButton
28
32
  className={onHover ? "bg-white dark:bg-gray-950" : "hidden"}
29
33
  onClick={() => {
@@ -32,7 +36,8 @@ export function CollectionViewHeaderAction({
32
36
  property,
33
37
  editedCollectionId: collection.id,
34
38
  parentCollectionIds,
35
- collection
39
+ collection,
40
+ existingEntities: tableController.data ?? []
36
41
  });
37
42
  }}
38
43
  size={"small"}>