@firecms/collection_editor 3.0.0-canary.15 → 3.0.0-canary.151

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 (67) 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 +4921 -3536
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/index.umd.js +6846 -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/types/config_permissions.d.ts +2 -2
  11. package/dist/types/persisted_collection.d.ts +1 -1
  12. package/dist/ui/CollectionViewHeaderAction.d.ts +3 -2
  13. package/dist/ui/EditorCollectionActionStart.d.ts +2 -0
  14. package/dist/ui/PropertyAddColumnComponent.d.ts +3 -1
  15. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +4 -3
  16. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +1 -1
  17. package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +1 -1
  18. package/dist/ui/collection_editor/PropertyEditView.d.ts +8 -0
  19. package/dist/ui/collection_editor/PropertyTree.d.ts +9 -9
  20. package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +1 -1
  21. package/dist/ui/collection_editor/import/CollectionEditorImportMapping.d.ts +7 -0
  22. package/dist/ui/collection_editor/properties/MarkdownPropertyField.d.ts +4 -0
  23. package/dist/ui/collection_editor/properties/StringPropertyField.d.ts +1 -1
  24. package/dist/useCollectionEditorPlugin.d.ts +17 -11
  25. package/dist/utils/collections.d.ts +6 -0
  26. package/package.json +21 -35
  27. package/src/ConfigControllerProvider.tsx +75 -63
  28. package/src/index.ts +1 -0
  29. package/src/types/collection_editor_controller.tsx +14 -4
  30. package/src/types/collection_inference.ts +1 -1
  31. package/src/types/config_permissions.ts +1 -1
  32. package/src/types/persisted_collection.ts +2 -3
  33. package/src/ui/CollectionViewHeaderAction.tsx +10 -5
  34. package/src/ui/EditorCollectionAction.tsx +10 -63
  35. package/src/ui/EditorCollectionActionStart.tsx +88 -0
  36. package/src/ui/HomePageEditorCollectionAction.tsx +18 -13
  37. package/src/ui/NewCollectionButton.tsx +12 -10
  38. package/src/ui/NewCollectionCard.tsx +3 -3
  39. package/src/ui/PropertyAddColumnComponent.tsx +11 -6
  40. package/src/ui/collection_editor/CollectionDetailsForm.tsx +70 -9
  41. package/src/ui/collection_editor/CollectionEditorDialog.tsx +61 -34
  42. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +8 -7
  43. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +37 -34
  44. package/src/ui/collection_editor/EnumForm.tsx +5 -2
  45. package/src/ui/collection_editor/GetCodeDialog.tsx +52 -21
  46. package/src/ui/collection_editor/PropertyEditView.tsx +255 -80
  47. package/src/ui/collection_editor/PropertyFieldPreview.tsx +4 -7
  48. package/src/ui/collection_editor/PropertyTree.tsx +7 -5
  49. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +26 -19
  50. package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +25 -9
  51. package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +40 -9
  52. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +32 -20
  53. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +50 -47
  54. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +1 -1
  55. package/src/ui/collection_editor/properties/MapPropertyField.tsx +7 -6
  56. package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +139 -0
  57. package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +0 -1
  58. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +32 -17
  59. package/src/ui/collection_editor/properties/StringPropertyField.tsx +1 -10
  60. package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +2 -2
  61. package/src/ui/collection_editor/templates/pages_template.ts +1 -6
  62. package/src/useCollectionEditorPlugin.tsx +41 -31
  63. package/src/utils/collections.ts +30 -0
  64. package/dist/ui/RootCollectionSuggestions.d.ts +0 -3
  65. package/dist/ui/collection_editor/PropertySelectItem.d.ts +0 -8
  66. package/src/ui/RootCollectionSuggestions.tsx +0 -63
  67. package/src/ui/collection_editor/PropertySelectItem.tsx +0 -32
@@ -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,6 +1,6 @@
1
1
  import { EntityCollection } from "@firecms/core";
2
2
 
3
- export type CollectionEditorPermissionsBuilder<UserType = any, EC extends EntityCollection = EntityCollection> = (params: { user: UserType | null, collection?: EC }) => CollectionEditorPermissions;
3
+ export type CollectionEditorPermissionsBuilder<USER = any, EC extends EntityCollection = EntityCollection> = (params: { user: USER | null, collection?: EC }) => CollectionEditorPermissions;
4
4
 
5
5
  export type CollectionEditorPermissions = {
6
6
  /**
@@ -1,8 +1,7 @@
1
1
  import { EntityCollection, User } from "@firecms/core";
2
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>;
3
+ export type PersistedCollection<M extends Record<string, any> = any, USER extends User = User>
4
+ = Omit<EntityCollection<M, USER>, "subcollections"> & {
6
5
  ownerId?: string;
7
6
  subcollections?: PersistedCollection<any, any>[];
8
7
  editable?: boolean;
@@ -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,21 +19,25 @@ 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
- className={onHover ? "bg-white dark:bg-gray-950" : "hidden"}
32
+ className={onHover ? "bg-white dark:bg-surface-950" : "hidden"}
29
33
  onClick={() => {
30
34
  collectionEditorController.editProperty({
31
35
  propertyKey,
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"}>
@@ -1,16 +1,7 @@
1
- import equal from "react-fast-compare"
2
-
3
- import {
4
- CollectionActionsProps,
5
- mergeDeep,
6
- useAuthController,
7
- useNavigationController,
8
- useSnackbarController
9
- } from "@firecms/core";
10
- import { Button, IconButton, SaveIcon, SettingsIcon, Tooltip, UndoIcon, } from "@firecms/ui";
1
+ import { CollectionActionsProps, useAuthController, useNavigationController } from "@firecms/core";
2
+ import { IconButton, SettingsIcon, Tooltip, } from "@firecms/ui";
11
3
 
12
4
  import { useCollectionEditorController } from "../useCollectionEditorController";
13
- import { useCollectionsConfigController } from "../useCollectionsConfigController";
14
5
  import { PersistedCollection } from "../types/persisted_collection";
15
6
 
16
7
  export function EditorCollectionAction({
@@ -23,8 +14,6 @@ export function EditorCollectionAction({
23
14
  const authController = useAuthController();
24
15
  const navigationController = useNavigationController();
25
16
  const collectionEditorController = useCollectionEditorController();
26
- const configController = useCollectionsConfigController();
27
- const snackbarController = useSnackbarController();
28
17
 
29
18
  const parentCollection = navigationController.getCollectionFromIds(parentCollectionIds);
30
19
 
@@ -35,68 +24,26 @@ export function EditorCollectionAction({
35
24
  }).editCollections
36
25
  : true;
37
26
 
38
- let saveDefaultFilterButton = null;
39
- if (!equal(getObjectOrNull(tableController.filterValues), getObjectOrNull(collection.initialFilter)) ||
40
- !equal(getObjectOrNull(tableController.sortBy), getObjectOrNull(collection.initialSort))) {
41
- saveDefaultFilterButton = <>
42
- {(collection.initialFilter || collection.initialSort) && <Tooltip
43
- title={"Reset to default filter and sort"}>
44
- <Button
45
- color={"primary"}
46
- size={"small"}
47
- variant={"text"}
48
- onClick={() => {
49
- tableController.clearFilter?.();
50
- if (collection?.initialFilter)
51
- tableController.setFilterValues?.(collection?.initialFilter);
52
- if (collection?.initialSort)
53
- tableController.setSortBy?.(collection?.initialSort);
54
- }}>
55
- <UndoIcon/>
56
- </Button>
57
- </Tooltip>}
58
-
59
- <Tooltip
60
- title={tableController.sortBy || tableController.filterValues ? "Save default filter and sort" : "Clear default filter and sort"}>
61
- <Button
62
- color={"primary"}
63
- size={"small"}
64
- variant={"outlined"}
65
- onClick={() => configController
66
- ?.saveCollection({
67
- id: collection.id,
68
- parentCollectionIds,
69
- collectionData: mergeDeep(collection as PersistedCollection,
70
- {
71
- initialFilter: tableController.filterValues ?? null,
72
- initialSort: tableController.sortBy ?? null
73
- })
74
- }).then(() => {
75
- snackbarController.open({
76
- type: "success",
77
- message: "Default config saved"
78
- });
79
- })}>
80
- <SaveIcon/>
81
- </Button>
82
- </Tooltip>
83
- </>;
84
- }
85
-
86
27
  const editorButton = <Tooltip
28
+ asChild={true}
87
29
  title={canEditCollection ? "Edit collection" : "You don't have permissions to edit this collection"}>
88
30
  <IconButton
89
31
  color={"primary"}
90
32
  disabled={!canEditCollection}
91
33
  onClick={canEditCollection
92
- ? () => collectionEditorController?.editCollection({ id: collection.id, fullPath, parentCollectionIds, parentCollection: parentCollection as PersistedCollection })
34
+ ? () => collectionEditorController?.editCollection({
35
+ id: collection.id,
36
+ fullPath,
37
+ parentCollectionIds,
38
+ parentCollection: parentCollection as PersistedCollection,
39
+ existingEntities: tableController?.data ?? []
40
+ })
93
41
  : undefined}>
94
42
  <SettingsIcon/>
95
43
  </IconButton>
96
44
  </Tooltip>;
97
45
 
98
46
  return <>
99
- {canEditCollection && saveDefaultFilterButton}
100
47
  {editorButton}
101
48
  </>
102
49
 
@@ -0,0 +1,88 @@
1
+ import equal from "react-fast-compare"
2
+
3
+ import { CollectionActionsProps, mergeDeep, useAuthController, useSnackbarController } from "@firecms/core";
4
+ import { Button, SaveIcon, Tooltip, UndoIcon, } from "@firecms/ui";
5
+
6
+ import { useCollectionEditorController } from "../useCollectionEditorController";
7
+ import { useCollectionsConfigController } from "../useCollectionsConfigController";
8
+ import { PersistedCollection } from "../types/persisted_collection";
9
+
10
+ export function EditorCollectionActionStart({
11
+ path: fullPath,
12
+ parentCollectionIds,
13
+ collection,
14
+ tableController
15
+ }: CollectionActionsProps) {
16
+
17
+ const authController = useAuthController();
18
+ const collectionEditorController = useCollectionEditorController();
19
+ const configController = useCollectionsConfigController();
20
+ const snackbarController = useSnackbarController();
21
+
22
+ const canEditCollection = collectionEditorController.configPermissions
23
+ ? collectionEditorController.configPermissions({
24
+ user: authController.user,
25
+ collection
26
+ }).editCollections
27
+ : true;
28
+
29
+ let saveDefaultFilterButton = null;
30
+ if (!equal(getObjectOrNull(tableController.filterValues), getObjectOrNull(collection.initialFilter)) ||
31
+ !equal(getObjectOrNull(tableController.sortBy), getObjectOrNull(collection.initialSort))) {
32
+ saveDefaultFilterButton = <>
33
+ <Tooltip
34
+ asChild={true}
35
+ title={tableController.sortBy || tableController.filterValues ? "Save default filter and sort" : "Clear default filter and sort"}>
36
+ <Button
37
+ color={"primary"}
38
+ size={"small"}
39
+ variant={"outlined"}
40
+ onClick={() => configController
41
+ ?.saveCollection({
42
+ id: collection.id,
43
+ parentCollectionIds,
44
+ collectionData: mergeDeep(collection as PersistedCollection,
45
+ {
46
+ initialFilter: tableController.filterValues ?? null,
47
+ initialSort: tableController.sortBy ?? null
48
+ })
49
+ }).then(() => {
50
+ snackbarController.open({
51
+ type: "success",
52
+ message: "Default config saved"
53
+ });
54
+ })}>
55
+ <SaveIcon/>
56
+ </Button>
57
+ </Tooltip>
58
+
59
+ {(collection.initialFilter || collection.initialSort) && <Tooltip
60
+ title={"Reset to default filter and sort"}>
61
+ <Button
62
+ color={"primary"}
63
+ size={"small"}
64
+ variant={"text"}
65
+ onClick={() => {
66
+ tableController.clearFilter?.();
67
+ if (collection?.initialFilter)
68
+ tableController.setFilterValues?.(collection?.initialFilter);
69
+ if (collection?.initialSort)
70
+ tableController.setSortBy?.(collection?.initialSort);
71
+ }}>
72
+ <UndoIcon/>
73
+ </Button>
74
+ </Tooltip>}
75
+ </>;
76
+ }
77
+
78
+ return <>
79
+ {canEditCollection && saveDefaultFilterButton}
80
+ </>
81
+
82
+ }
83
+
84
+ function getObjectOrNull(o?: object): object | null {
85
+ if (o && Object.keys(o).length === 0)
86
+ return o
87
+ return o ?? null;
88
+ }
@@ -1,12 +1,12 @@
1
1
  import {
2
- DeleteConfirmationDialog,
2
+ ConfirmationDialog,
3
3
  PluginHomePageActionsProps,
4
4
  useAuthController,
5
5
  useSnackbarController
6
6
  } from "@firecms/core";
7
7
  import { DeleteIcon, IconButton, Menu, MenuItem, MoreVertIcon, SettingsIcon, } from "@firecms/ui";
8
8
  import { useCollectionEditorController } from "../useCollectionEditorController";
9
- import { useCallback, useState } from "react";
9
+ import { useState } from "react";
10
10
  import { useCollectionsConfigController } from "../useCollectionsConfigController";
11
11
 
12
12
  export function HomePageEditorCollectionAction({
@@ -24,13 +24,16 @@ export function HomePageEditorCollectionAction({
24
24
  collection
25
25
  });
26
26
 
27
- const onEditCollectionClicked = useCallback(() => {
28
- collectionEditorController?.editCollection({ id: collection.id, parentCollectionIds: [] });
29
- }, [collectionEditorController, path]);
27
+ const onEditCollectionClicked = () => {
28
+ collectionEditorController?.editCollection({
29
+ id: collection.id,
30
+ parentCollectionIds: []
31
+ });
32
+ };
30
33
 
31
34
  const [deleteRequested, setDeleteRequested] = useState(false);
32
35
 
33
- const deleteCollection = useCallback(() => {
36
+ const deleteCollection = () => {
34
37
  configController?.deleteCollection({ id: collection.id }).then(() => {
35
38
  setDeleteRequested(false);
36
39
  snackbarController.open({
@@ -38,7 +41,7 @@ export function HomePageEditorCollectionAction({
38
41
  type: "success"
39
42
  });
40
43
  });
41
- }, [path, configController]);
44
+ };
42
45
 
43
46
  return <>
44
47
 
@@ -49,11 +52,13 @@ export function HomePageEditorCollectionAction({
49
52
  <MoreVertIcon size={"small"}/>
50
53
  </IconButton>}
51
54
  >
52
- <MenuItem onClick={(event) => {
53
- event.preventDefault();
54
- event.stopPropagation();
55
- setDeleteRequested(true);
56
- }}>
55
+ <MenuItem
56
+ dense={true}
57
+ onClick={(event) => {
58
+ event.preventDefault();
59
+ event.stopPropagation();
60
+ setDeleteRequested(true);
61
+ }}>
57
62
  <DeleteIcon/>
58
63
  Delete
59
64
  </MenuItem>
@@ -71,7 +76,7 @@ export function HomePageEditorCollectionAction({
71
76
  </IconButton>}
72
77
  </div>
73
78
 
74
- <DeleteConfirmationDialog
79
+ <ConfirmationDialog
75
80
  open={deleteRequested}
76
81
  onAccept={deleteCollection}
77
82
  onCancel={() => setDeleteRequested(false)}
@@ -3,14 +3,16 @@ import { useCollectionEditorController } from "../useCollectionEditorController"
3
3
 
4
4
  export function NewCollectionButton() {
5
5
  const collectionEditorController = useCollectionEditorController();
6
- return <Button className={"min-w-fit"}
7
- variant={"outlined"}
8
- onClick={() => collectionEditorController.createCollection({
9
- parentCollectionIds: [],
10
- redirect: true,
11
- sourceClick: "new_collection_button"
12
- })}>
13
- <AddIcon/>
14
- New collection
15
- </Button>
6
+ return <div className={"bg-surface-50 dark:bg-surface-900 min-w-fit rounded"}>
7
+ <Button className={"min-w-fit"}
8
+ variant={"outlined"}
9
+ onClick={() => collectionEditorController.createCollection({
10
+ parentCollectionIds: [],
11
+ redirect: true,
12
+ sourceClick: "new_collection_button"
13
+ })}>
14
+ <AddIcon/>
15
+ New collection
16
+ </Button>
17
+ </div>
16
18
  }
@@ -1,5 +1,5 @@
1
1
  import { PluginHomePageAdditionalCardsProps, useAuthController } from "@firecms/core";
2
- import { AddIcon, Card, cn, Typography } from "@firecms/ui";
2
+ import { AddIcon, Card, cls, Typography } from "@firecms/ui";
3
3
  import { useCollectionEditorController } from "../useCollectionEditorController";
4
4
 
5
5
  export function NewCollectionCard({
@@ -20,7 +20,7 @@ export function NewCollectionCard({
20
20
  : true;
21
21
 
22
22
  return (
23
- <Card className={cn("h-full p-4 min-h-[124px]")}
23
+ <Card className={cls("h-full p-4 min-h-[124px]")}
24
24
  onClick={collectionEditorController && canCreateCollections
25
25
  ? () => collectionEditorController.createCollection({
26
26
  initialValues: group ? { group } : undefined,
@@ -31,7 +31,7 @@ export function NewCollectionCard({
31
31
  : undefined}>
32
32
 
33
33
  <div
34
- className="flex flex-col items-start h-full w-full items-center justify-center h-full w-full flex-grow flex-col">
34
+ className="flex items-center justify-center h-full w-full flex-grow flex-col">
35
35
  <AddIcon color="primary" size={"large"}/>
36
36
  <Typography color="primary"
37
37
  variant={"caption"}
@@ -1,4 +1,4 @@
1
- import { getDefaultPropertiesOrder, useAuthController } from "@firecms/core";
1
+ import { EntityTableController, getDefaultPropertiesOrder, useAuthController } from "@firecms/core";
2
2
  import { AddIcon, Tooltip } from "@firecms/ui";
3
3
  import { useCollectionEditorController } from "../useCollectionEditorController";
4
4
  import { PersistedCollection } from "../types/persisted_collection";
@@ -6,11 +6,13 @@ import { PersistedCollection } from "../types/persisted_collection";
6
6
  export function PropertyAddColumnComponent({
7
7
  fullPath,
8
8
  parentCollectionIds,
9
- collection
9
+ collection,
10
+ tableController
10
11
  }: {
11
12
  fullPath: string,
12
13
  parentCollectionIds: string[],
13
14
  collection: PersistedCollection;
15
+ tableController: EntityTableController;
14
16
  }) {
15
17
 
16
18
  const authController = useAuthController();
@@ -23,16 +25,19 @@ export function PropertyAddColumnComponent({
23
25
  : true;
24
26
 
25
27
  return (
26
- <Tooltip title={canEditCollection ? "Add new property" : "You don't have permission to add new properties"}>
28
+ <Tooltip
29
+ asChild={true}
30
+ title={canEditCollection ? "Add new property" : "You don't have permission to add new properties"}>
27
31
  <div
28
- className={"p-0.5 w-20 h-full flex items-center justify-center cursor-pointer bg-gray-100 bg-opacity-40 hover:bg-gray-100 dark:bg-gray-950 dark:bg-opacity-40 dark:hover:bg-gray-950"}
29
- // className={onHover ? "bg-white dark:bg-gray-950" : undefined}
32
+ className={"p-0.5 w-20 h-full flex items-center justify-center cursor-pointer bg-surface-100 bg-opacity-40 hover:bg-surface-100 dark:bg-surface-950 dark:bg-opacity-40 dark:hover:bg-surface-950"}
33
+ // className={onHover ? "bg-white dark:bg-surface-950" : undefined}
30
34
  onClick={() => {
31
35
  collectionEditorController.editProperty({
32
36
  editedCollectionId: collection.id,
33
37
  parentCollectionIds,
34
38
  currentPropertiesOrder: getDefaultPropertiesOrder(collection),
35
- collection
39
+ collection,
40
+ existingEntities: tableController.data
36
41
  });
37
42
  }}>
38
43
  <AddIcon color={"inherit"}/>
@@ -5,7 +5,8 @@ import {
5
5
  AutocompleteItem,
6
6
  BooleanSwitchWithLabel,
7
7
  Chip,
8
- cn,
8
+ ClearIcon,
9
+ cls,
9
10
  Container,
10
11
  DebouncedTextField,
11
12
  Dialog,
@@ -21,6 +22,7 @@ import {
21
22
  } from "@firecms/ui";
22
23
 
23
24
  import { Field, getIn, useFormex } from "@firecms/formex";
25
+ import { useCollectionEditorController } from "../../useCollectionEditorController";
24
26
 
25
27
  export function CollectionDetailsForm({
26
28
  isNewCollection,
@@ -51,9 +53,15 @@ export function CollectionDetailsForm({
51
53
  submitCount
52
54
  } = useFormex<EntityCollection>();
53
55
 
56
+ const collectionEditor = useCollectionEditorController();
57
+
54
58
  const [iconDialogOpen, setIconDialogOpen] = useState(false);
55
59
  const [advancedPanelExpanded, setAdvancedPanelExpanded] = useState(false);
56
60
 
61
+ const updateDatabaseId = (databaseId: string) => {
62
+ setFieldValue("databaseId", databaseId ?? undefined);
63
+ }
64
+
57
65
  const updateName = (name: string) => {
58
66
  setFieldValue("name", name);
59
67
 
@@ -80,6 +88,8 @@ export function CollectionDetailsForm({
80
88
  }
81
89
  }, [errors.id]);
82
90
 
91
+ const DatabaseField = collectionEditor.components?.DatabaseField ?? DefaultDatabaseField;
92
+
83
93
  const collectionIcon = <IconForView collectionOrView={values}/>;
84
94
 
85
95
  const groupOptions = groups?.filter((group) => !reservedGroups?.includes(group));
@@ -112,11 +122,15 @@ export function CollectionDetailsForm({
112
122
 
113
123
  <div>
114
124
  <div
115
- className="flex flex-row py-2 pt-3 items-center">
125
+ className="flex flex-row gap-2 py-2 pt-3 items-center">
116
126
  <Typography variant={!isNewCollection ? "h5" : "h4"} className={"flex-grow"}>
117
127
  {isNewCollection ? "New collection" : `${values?.name} collection`}
118
128
  </Typography>
119
- <Tooltip title={"Change icon"}>
129
+ <DatabaseField databaseId={values.databaseId}
130
+ onDatabaseIdUpdate={updateDatabaseId}/>
131
+
132
+ <Tooltip title={"Change icon"}
133
+ asChild={true}>
120
134
  <IconButton
121
135
  shape={"square"}
122
136
  onClick={() => setIconDialogOpen(true)}>
@@ -139,14 +153,15 @@ export function CollectionDetailsForm({
139
153
  value={values.name ?? ""}
140
154
  onChange={(e: any) => updateName(e.target.value)}
141
155
  label={"Name"}
156
+ autoFocus={true}
142
157
  required
143
158
  error={showErrors && Boolean(errors.name)}/>
144
159
  <FieldCaption error={touched.name && Boolean(errors.name)}>
145
- {touched.name && Boolean(errors.name) ? errors.name : "Name of in this collection, usually a plural name (e.g. Products)"}
160
+ {touched.name && Boolean(errors.name) ? errors.name : "Name of this collection, usually a plural name (e.g. Products)"}
146
161
  </FieldCaption>
147
162
  </div>
148
163
 
149
- <div className={cn("col-span-12 ", isSubcollection ? "" : "sm:col-span-8")}>
164
+ <div className={cls("col-span-12 ", isSubcollection ? "" : "sm:col-span-8")}>
150
165
  <Field name={"path"}
151
166
  as={DebouncedTextField}
152
167
  label={"Path"}
@@ -190,7 +205,7 @@ export function CollectionDetailsForm({
190
205
  })}
191
206
  </Autocomplete>
192
207
  <FieldCaption>
193
- {showErrors && Boolean(errors.group) ? errors.group : "Group of the collection"}
208
+ {showErrors && Boolean(errors.group) ? errors.group : "Group in the home page"}
194
209
  </FieldCaption>
195
210
  </div>}
196
211
 
@@ -199,7 +214,7 @@ export function CollectionDetailsForm({
199
214
  expanded={advancedPanelExpanded}
200
215
  onExpandedChange={setAdvancedPanelExpanded}
201
216
  title={
202
- <div className="flex flex-row text-gray-500">
217
+ <div className="flex flex-row text-surface-500">
203
218
  <SettingsIcon/>
204
219
  <Typography variant={"subtitle2"}
205
220
  className="ml-2">
@@ -216,7 +231,7 @@ export function CollectionDetailsForm({
216
231
  label={"Collection id"}
217
232
  error={showErrors && Boolean(errors.id)}/>
218
233
  <FieldCaption error={touched.id && Boolean(errors.id)}>
219
- {touched.id && Boolean(errors.id) ? errors.id : "This id identifies this collection"}
234
+ {touched.id && Boolean(errors.id) ? errors.id : "This id identifies this collection. Typically the same as the path."}
220
235
  </FieldCaption>
221
236
  </div>
222
237
 
@@ -235,6 +250,35 @@ export function CollectionDetailsForm({
235
250
  {showErrors && Boolean(errors.singularName) ? errors.singularName : "Optionally define a singular name for your entities"}
236
251
  </FieldCaption>
237
252
  </div>
253
+ <div className={"col-span-12"}>
254
+ <TextField
255
+ error={showErrors && Boolean(errors.sideDialogWidth)}
256
+ name={"sideDialogWidth"}
257
+ type={"number"}
258
+ aria-describedby={"sideDialogWidth-helper"}
259
+ onChange={(e) => {
260
+ setFieldTouched("sideDialogWidth", true);
261
+ const value = e.target.value;
262
+ if (!value) {
263
+ setFieldValue("sideDialogWidth", null);
264
+ } else if (!isNaN(Number(value))) {
265
+ setFieldValue("sideDialogWidth", Number(value));
266
+ }
267
+ }}
268
+ endAdornment={<IconButton
269
+ size={"small"}
270
+ onClick={() => {
271
+ setFieldValue("sideDialogWidth", null);
272
+ }}
273
+ disabled={!values.sideDialogWidth}>
274
+ <ClearIcon size={"small"}/>
275
+ </IconButton>}
276
+ value={values.sideDialogWidth ?? ""}
277
+ label={"Side dialog width"}/>
278
+ <FieldCaption error={showErrors && Boolean(errors.singularName)}>
279
+ {showErrors && Boolean(errors.singularName) ? errors.singularName : "Optionally define the width (in pixels) of entities side dialog. Default is 768px"}
280
+ </FieldCaption>
281
+ </div>
238
282
  <div className={"col-span-12"}>
239
283
  <TextField
240
284
  error={showErrors && Boolean(errors.description)}
@@ -272,7 +316,7 @@ export function CollectionDetailsForm({
272
316
  <div className={"col-span-12"}>
273
317
  <Select
274
318
  name="customId"
275
- label="Data IDs generation"
319
+ label="Document IDs generation"
276
320
  position={"item-aligned"}
277
321
  disabled={customIdValue === "code_defined"}
278
322
  onValueChange={(v) => {
@@ -363,3 +407,20 @@ export function CollectionDetailsForm({
363
407
  </div>
364
408
  );
365
409
  }
410
+
411
+ function DefaultDatabaseField({
412
+ databaseId,
413
+ onDatabaseIdUpdate
414
+ }: { databaseId?: string, onDatabaseIdUpdate: (databaseId: string) => void }) {
415
+
416
+ return <Tooltip title={"Database ID"}
417
+ side={"top"}
418
+ align={"start"}>
419
+ <TextField size={"smallest"}
420
+ invisible={true}
421
+ inputClassName={"text-end"}
422
+ value={databaseId ?? ""}
423
+ onChange={(e: any) => onDatabaseIdUpdate(e.target.value)}
424
+ placeholder={"(default)"}></TextField>
425
+ </Tooltip>
426
+ }