@firecms/collection_editor 3.0.0-canary.258 → 3.0.0-canary.259

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.
@@ -1,2 +1,5 @@
1
1
  import { EntityCollection } from "@firecms/core";
2
+ /**
3
+ * This function is used to infer the configuration of a collection given its path.
4
+ */
2
5
  export type CollectionInference = (path: string, collectionGroup: boolean, parentCollectionPaths: string[]) => Promise<Partial<EntityCollection> | null>;
@@ -0,0 +1,2 @@
1
+ import { PluginFormActionProps } from "@firecms/core";
2
+ export declare function EditorEntityAction({ path: fullPath, parentCollectionIds, collection, formContext }: PluginFormActionProps): import("react/jsx-runtime").JSX.Element;
@@ -11,7 +11,7 @@ type CollectionEditorFormProps = {
11
11
  extraIcon: React.ReactNode;
12
12
  getUser?: (uid: string) => User | null;
13
13
  getData?: () => Promise<object[]>;
14
- doCollectionInference: (collection: PersistedCollection) => Promise<Partial<EntityCollection> | null> | undefined;
14
+ doCollectionInference?: (collection: PersistedCollection) => Promise<Partial<EntityCollection> | null> | undefined;
15
15
  propertyConfigs: Record<string, PropertyConfig>;
16
16
  collectionEditable: boolean;
17
17
  };
@@ -0,0 +1,4 @@
1
+ import { PersistedCollection } from "../../types/persisted_collection";
2
+ export declare function EntityActionsEditTab({ collection, }: {
3
+ collection: PersistedCollection;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare function EntityActionsSelectDialog({ open, onClose }: {
2
+ open: boolean;
3
+ onClose: (selectedActionKey?: string) => void;
4
+ }): import("react/jsx-runtime").JSX.Element;
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@firecms/collection_editor",
3
3
  "type": "module",
4
- "version": "3.0.0-canary.258",
4
+ "version": "3.0.0-canary.259",
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_export": "^3.0.0-canary.258",
11
- "@firecms/data_import": "^3.0.0-canary.258",
12
- "@firecms/data_import_export": "^3.0.0-canary.258",
13
- "@firecms/formex": "^3.0.0-canary.258",
14
- "@firecms/schema_inference": "^3.0.0-canary.258",
15
- "@firecms/ui": "^3.0.0-canary.258",
10
+ "@firecms/data_export": "^3.0.0-canary.259",
11
+ "@firecms/data_import": "^3.0.0-canary.259",
12
+ "@firecms/data_import_export": "^3.0.0-canary.259",
13
+ "@firecms/formex": "^3.0.0-canary.259",
14
+ "@firecms/schema_inference": "^3.0.0-canary.259",
15
+ "@firecms/ui": "^3.0.0-canary.259",
16
16
  "json5": "^2.2.3",
17
17
  "prism-react-renderer": "^2.4.1"
18
18
  },
@@ -69,5 +69,5 @@
69
69
  "publishConfig": {
70
70
  "access": "public"
71
71
  },
72
- "gitHead": "2d408ab25c6f29305fa6052d2aff07a5ab3daa14"
72
+ "gitHead": "a4ab5e6aacfb9e10ee8c1c72354c939fb2275ab0"
73
73
  }
@@ -1,3 +1,6 @@
1
1
  import { EntityCollection } from "@firecms/core";
2
2
 
3
+ /**
4
+ * This function is used to infer the configuration of a collection given its path.
5
+ */
3
6
  export type CollectionInference = (path: string, collectionGroup: boolean, parentCollectionPaths: string[]) => Promise<Partial<EntityCollection> | null>;
@@ -28,6 +28,7 @@ export function EditorCollectionAction({
28
28
  asChild={true}
29
29
  title={canEditCollection ? "Edit collection" : "You don't have permissions to edit this collection"}>
30
30
  <IconButton
31
+ size={"small"}
31
32
  color={"primary"}
32
33
  disabled={!canEditCollection}
33
34
  onClick={canEditCollection
@@ -39,7 +40,7 @@ export function EditorCollectionAction({
39
40
  existingEntities: tableController?.data ?? []
40
41
  })
41
42
  : undefined}>
42
- <SettingsIcon/>
43
+ <SettingsIcon size={"small"}/>
43
44
  </IconButton>
44
45
  </Tooltip>;
45
46
 
@@ -48,9 +49,3 @@ export function EditorCollectionAction({
48
49
  </>
49
50
 
50
51
  }
51
-
52
- function getObjectOrNull(o?: object): object | null {
53
- if (o && Object.keys(o).length === 0)
54
- return o
55
- return o ?? null;
56
- }
@@ -0,0 +1,51 @@
1
+ import { PluginFormActionProps, useAuthController, useNavigationController } from "@firecms/core";
2
+ import { IconButton, SettingsIcon, Tooltip, } from "@firecms/ui";
3
+
4
+ import { useCollectionEditorController } from "../useCollectionEditorController";
5
+ import { PersistedCollection } from "../types/persisted_collection";
6
+
7
+ export function EditorEntityAction({
8
+ path: fullPath,
9
+ parentCollectionIds,
10
+ collection,
11
+ formContext
12
+ }: PluginFormActionProps) {
13
+
14
+ const authController = useAuthController();
15
+ const navigationController = useNavigationController();
16
+ const collectionEditorController = useCollectionEditorController();
17
+
18
+ const parentCollection = navigationController.getCollectionFromIds(parentCollectionIds);
19
+
20
+ const canEditCollection = collectionEditorController.configPermissions
21
+ ? collectionEditorController.configPermissions({
22
+ user: authController.user,
23
+ collection
24
+ }).editCollections
25
+ : true;
26
+
27
+ const isDirty = formContext?.formex.dirty ?? false;
28
+
29
+ const editorButton = <Tooltip
30
+ asChild={true}
31
+ title={canEditCollection ? (isDirty ? "You need to save the document before changing the schema" : "Edit schema for this form") : "You don't have permissions to edit this collection"}>
32
+ <IconButton
33
+ color={"primary"}
34
+ disabled={!canEditCollection || isDirty}
35
+ onClick={canEditCollection
36
+ ? () => collectionEditorController?.editCollection({
37
+ id: collection.id,
38
+ fullPath,
39
+ parentCollectionIds,
40
+ parentCollection: parentCollection as PersistedCollection,
41
+ })
42
+ : undefined}>
43
+ <SettingsIcon size={"small"}/>
44
+ </IconButton>
45
+ </Tooltip>;
46
+
47
+ return <>
48
+ {editorButton}
49
+ </>
50
+
51
+ }
@@ -9,6 +9,7 @@ import {
9
9
  isPropertyBuilder,
10
10
  MapProperty,
11
11
  mergeDeep,
12
+ NavigationResult,
12
13
  Properties,
13
14
  PropertiesOrBuilders,
14
15
  Property,
@@ -17,7 +18,6 @@ import {
17
18
  randomString,
18
19
  removeInitialAndTrailingSlashes,
19
20
  removeUndefined,
20
- NavigationResult,
21
21
  useAuthController,
22
22
  useCustomizationController,
23
23
  useNavigationController,
@@ -57,6 +57,7 @@ import { cleanPropertiesFromImport } from "./import/clean_import_data";
57
57
  import { PersistedCollection } from "../../types/persisted_collection";
58
58
  import { Formex, FormexController, useCreateFormex } from "@firecms/formex";
59
59
  import { getFullIdPath } from "./util";
60
+ import { EntityActionsEditTab } from "./EntityActionsEditTab";
60
61
 
61
62
  export interface CollectionEditorDialogProps {
62
63
  open: boolean;
@@ -140,7 +141,8 @@ type EditorView = "welcome"
140
141
  | "properties"
141
142
  | "loading"
142
143
  | "extra_view"
143
- | "subcollections";
144
+ | "subcollections"
145
+ | "custom_actions";
144
146
 
145
147
  export function CollectionEditor(props: CollectionEditorDialogProps & {
146
148
  handleCancel: () => void,
@@ -325,10 +327,10 @@ function CollectionEditorInternal<M extends Record<string, any>>({
325
327
 
326
328
  };
327
329
 
328
- const doCollectionInference = (collection: PersistedCollection<any>) => {
330
+ const doCollectionInference = collectionInference ? (collection: PersistedCollection<any>) => {
329
331
  if (!collectionInference) return undefined;
330
332
  return collectionInference?.(collection.path, collection.collectionGroup ?? false, parentPaths ?? []);
331
- };
333
+ } : undefined;
332
334
 
333
335
  const inferCollectionFromData = async (newCollection: PersistedCollection<M>) => {
334
336
 
@@ -569,6 +571,9 @@ function CollectionEditorInternal<M extends Record<string, any>>({
569
571
  <Tab value={"subcollections"}>
570
572
  Additional views
571
573
  </Tab>
574
+ <Tab value={"custom_actions"}>
575
+ Custom actions
576
+ </Tab>
572
577
  </Tabs>}
573
578
 
574
579
  <form noValidate
@@ -645,6 +650,9 @@ function CollectionEditorInternal<M extends Record<string, any>>({
645
650
  </div>}
646
651
  </CollectionDetailsForm>}
647
652
 
653
+ {currentView === "custom_actions" && collection &&
654
+ <EntityActionsEditTab collection={collection}/>}
655
+
648
656
  {currentView === "subcollections" && collection &&
649
657
  <SubcollectionsEditTab
650
658
  parentCollection={parentCollection}
@@ -687,6 +695,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
687
695
  {isNewCollection && includeTemplates && currentView === "import_data_mapping" &&
688
696
  <Button variant={"text"}
689
697
  type="button"
698
+ color={"primary"}
690
699
  onClick={() => {
691
700
  importConfig.setInUse(false);
692
701
  return setCurrentView("welcome");
@@ -698,6 +707,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
698
707
  {isNewCollection && includeTemplates && currentView === "import_data_preview" &&
699
708
  <Button variant={"text"}
700
709
  type="button"
710
+ color={"primary"}
701
711
  onClick={() => {
702
712
  setCurrentView("import_data_mapping");
703
713
  }}>
@@ -707,6 +717,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
707
717
 
708
718
  {isNewCollection && includeTemplates && currentView === "details" &&
709
719
  <Button variant={"text"}
720
+ color={"primary"}
710
721
  type="button"
711
722
  onClick={() => setCurrentView("welcome")}>
712
723
  <ArrowBackIcon/>
@@ -715,12 +726,14 @@ function CollectionEditorInternal<M extends Record<string, any>>({
715
726
 
716
727
  {isNewCollection && currentView === "properties" && <Button variant={"text"}
717
728
  type="button"
729
+ color={"primary"}
718
730
  onClick={() => setCurrentView("details")}>
719
731
  <ArrowBackIcon/>
720
732
  Back
721
733
  </Button>}
722
734
 
723
735
  <Button variant={"text"}
736
+ color={"primary"}
724
737
  onClick={() => {
725
738
  handleCancel();
726
739
  }}>
@@ -89,6 +89,11 @@ export function CollectionEditorWelcomeView({
89
89
  {suggestion}
90
90
  </Chip>
91
91
  ))}
92
+ {(filteredPathSuggestions ?? []).length === 0 && !loadingPathSuggestions && <Typography
93
+ variant={"caption"}
94
+ color={"secondary"}>
95
+ No existing paths found
96
+ </Typography>}
92
97
 
93
98
  </div>
94
99
 
@@ -24,7 +24,6 @@ import {
24
24
  DebouncedTextField,
25
25
  defaultBorderMixin,
26
26
  IconButton,
27
- Paper,
28
27
  Tooltip,
29
28
  Typography,
30
29
  } from "@firecms/ui";
@@ -45,7 +44,7 @@ type CollectionEditorFormProps = {
45
44
  extraIcon: React.ReactNode;
46
45
  getUser?: (uid: string) => User | null;
47
46
  getData?: () => Promise<object[]>;
48
- doCollectionInference: (collection: PersistedCollection) => Promise<Partial<EntityCollection> | null> | undefined;
47
+ doCollectionInference?: (collection: PersistedCollection) => Promise<Partial<EntityCollection> | null> | undefined;
49
48
  propertyConfigs: Record<string, PropertyConfig>;
50
49
  collectionEditable: boolean;
51
50
  };
@@ -108,6 +107,8 @@ export function CollectionPropertiesEditorForm({
108
107
  return;
109
108
 
110
109
  setInferringProperties(true);
110
+
111
+ console.debug("CollectionEditor: inferring properties from data", doCollectionInference, values);
111
112
  // @ts-ignore
112
113
  doCollectionInference(values)
113
114
  .then((newCollection) => {
@@ -368,6 +369,7 @@ export function CollectionPropertiesEditorForm({
368
369
  asChild={true}>
369
370
  <Button
370
371
  variant={"outlined"}
372
+ color={"primary"}
371
373
  onClick={() => setNewPropertyDialogOpen(true)}>
372
374
  <AddIcon/>
373
375
  </Button>
@@ -436,6 +438,7 @@ export function CollectionPropertiesEditorForm({
436
438
  : "Select a property to edit it"}
437
439
  </Typography>
438
440
  <Button variant={"outlined"}
441
+ color={"primary"}
439
442
  onClick={() => setNewPropertyDialogOpen(true)}
440
443
  >
441
444
  <AddIcon/>
@@ -0,0 +1,163 @@
1
+ import React from "react";
2
+ import {
3
+ ConfirmationDialog,
4
+ EntityAction,
5
+ EntityCollection,
6
+ resolveEntityAction,
7
+ useCustomizationController
8
+ } from "@firecms/core";
9
+ import {
10
+ AddIcon,
11
+ Alert,
12
+ Button,
13
+ Container,
14
+ DeleteIcon,
15
+ IconButton,
16
+ Paper,
17
+ Table,
18
+ TableBody,
19
+ TableCell,
20
+ TableRow,
21
+ Tooltip,
22
+ Typography,
23
+ } from "@firecms/ui";
24
+ import { PersistedCollection } from "../../types/persisted_collection";
25
+ import { useFormex } from "@firecms/formex";
26
+ import { EntityActionsSelectDialog } from "./EntityActionsSelectDialog";
27
+
28
+ export function EntityActionsEditTab({
29
+ collection,
30
+ }: {
31
+ collection: PersistedCollection,
32
+ }) {
33
+
34
+ const { entityActions: contextEntityActions } = useCustomizationController();
35
+
36
+ const [addEntityActionDialogOpen, setAddEntityActionDialogOpen] = React.useState<boolean>(false);
37
+ const [actionToDelete, setActionToDelete] = React.useState<string | undefined>();
38
+
39
+ const {
40
+ values,
41
+ setFieldValue
42
+ } = useFormex<EntityCollection>();
43
+
44
+ const resolvedEntityActions = values.entityActions?.filter((e): e is string => typeof e === "string")
45
+ .map(e => resolveEntityAction(e, contextEntityActions))
46
+ .filter(Boolean) as EntityAction<any>[] ?? [];
47
+ const hardCodedEntityActions = collection.entityActions?.filter((e): e is EntityAction<any> => typeof e !== "string") ?? [];
48
+ const totalEntityActions = resolvedEntityActions.length + hardCodedEntityActions.length;
49
+
50
+ return (
51
+ <div className={"overflow-auto my-auto"}>
52
+ <Container maxWidth={"2xl"} className={"flex flex-col gap-4 p-8 m-auto"}>
53
+ <div className={"flex flex-col gap-16"}>
54
+ <div className={"flex-grow flex flex-col gap-4 items-start"}>
55
+ <Typography variant={"h5"}>
56
+ Custom actions
57
+ </Typography>
58
+
59
+ {totalEntityActions === 0 &&
60
+ <Alert action={<Button variant="text"
61
+ size={"small"}
62
+ href={"https://firecms.co/docs/custom_actions"}
63
+ component={"a"}
64
+ rel="noopener noreferrer"
65
+ target="_blank">More info</Button>}>
66
+ Define your own custom actions by uploading them with the CLI.
67
+ </Alert>
68
+ }
69
+
70
+ {<>
71
+ <Paper className={"flex flex-col gap-4 p-2 w-full"}>
72
+ <Table>
73
+ <TableBody>
74
+ {resolvedEntityActions.map((action) => (
75
+ <TableRow key={action.key}>
76
+ <TableCell
77
+ align="left">
78
+ <Typography variant={"subtitle2"} className={"flex-grow"}>
79
+ {action.name}
80
+ </Typography>
81
+ </TableCell>
82
+ <TableCell
83
+ align="right">
84
+ <Tooltip title={"Remove"}
85
+ asChild={true}>
86
+ <IconButton size="small"
87
+ onClick={(e) => {
88
+ e.preventDefault();
89
+ e.stopPropagation();
90
+ setActionToDelete(action.key);
91
+ }}
92
+ color="inherit">
93
+ <DeleteIcon size={"small"}/>
94
+ </IconButton>
95
+ </Tooltip>
96
+ </TableCell>
97
+ </TableRow>
98
+ ))}
99
+ {hardCodedEntityActions.map((action) => (
100
+ <TableRow key={action.key}>
101
+ <TableCell
102
+ align="left">
103
+ <Typography variant={"subtitle2"} className={"flex-grow"}>
104
+ {action.name}
105
+ </Typography>
106
+ <Typography variant={"caption"} className={"flex-grow"}>
107
+ This action is defined in code with
108
+ key <code>{action.key}</code>
109
+ </Typography>
110
+ </TableCell>
111
+ </TableRow>
112
+ ))}
113
+ </TableBody>
114
+ </Table>
115
+
116
+ <Button
117
+ onClick={() => {
118
+ setAddEntityActionDialogOpen(true);
119
+ }}
120
+ variant={"text"}
121
+ startIcon={<AddIcon/>}>
122
+ Add custom entity action
123
+ </Button>
124
+ </Paper>
125
+
126
+ </>}
127
+
128
+
129
+ </div>
130
+
131
+ </div>
132
+ </Container>
133
+
134
+ <div style={{ height: "52px" }}/>
135
+
136
+ {actionToDelete &&
137
+ <ConfirmationDialog open={Boolean(actionToDelete)}
138
+ onAccept={() => {
139
+ setFieldValue("entityActions", values.entityActions?.filter(e => e !== actionToDelete));
140
+ setActionToDelete(undefined);
141
+ }}
142
+ onCancel={() => setActionToDelete(undefined)}
143
+ title={<>Remove this action?</>}
144
+ body={<>This will <b>not
145
+ delete any data</b>, only
146
+ the action in the CMS</>}/>}
147
+
148
+ <EntityActionsSelectDialog
149
+ open={addEntityActionDialogOpen}
150
+ onClose={(selectedActionKey) => {
151
+ if (selectedActionKey) {
152
+ console.log("Selected action key:", selectedActionKey);
153
+ const value = [...(values.entityActions ?? []), selectedActionKey]
154
+ // only actions that are defined in the registry
155
+ .filter((e): e is string => typeof e === "string" && (contextEntityActions ?? []).some(action => action.key === e));
156
+ ;
157
+ setFieldValue("entityActions", value);
158
+ }
159
+ setAddEntityActionDialogOpen(false);
160
+ }}/>
161
+ </div>
162
+ );
163
+ }
@@ -0,0 +1,41 @@
1
+ import { useCustomizationController } from "@firecms/core";
2
+ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@firecms/ui";
3
+ import React from "react";
4
+
5
+ export function EntityActionsSelectDialog({
6
+ open,
7
+ onClose
8
+ }: { open: boolean, onClose: (selectedActionKey?: string) => void }) {
9
+ const {
10
+ entityActions
11
+ } = useCustomizationController();
12
+
13
+ return <Dialog
14
+ maxWidth={"md"}
15
+ open={open}>
16
+ <DialogTitle>Select custom action</DialogTitle>
17
+ <DialogContent className={"flex flex-col gap-4"}>
18
+ {entityActions?.map((action) => {
19
+ return <Button
20
+ key={action.key}
21
+ onClick={() => onClose(action.key)}
22
+ fullWidth
23
+ variant={"text"}
24
+ >
25
+ {action.name} ({action.key})
26
+ </Button>;
27
+ })}
28
+ {(entityActions ?? []).length === 0 &&
29
+ <Typography variant={"body2"}>
30
+ No custom actions defined. Define your custom actions in the customization settings, before using this
31
+ dialog.
32
+ </Typography>
33
+ }
34
+ </DialogContent>
35
+ <DialogActions>
36
+ <Button variant={"outlined"}
37
+ color={"primary"}
38
+ onClick={() => onClose()}>Cancel</Button>
39
+ </DialogActions>
40
+ </Dialog>
41
+ }
@@ -27,12 +27,15 @@ export function EntityCustomViewsSelectDialog({
27
27
  })}
28
28
  {(entityViews ?? []).length === 0 &&
29
29
  <Typography variant={"body2"}>
30
- No custom views defined
30
+ No custom views defined. Define your custom views in the customization settings, before using this
31
+ dialog.
31
32
  </Typography>
32
33
  }
33
34
  </DialogContent>
34
35
  <DialogActions>
35
- <Button variant={"outlined"} onClick={() => onClose()}>Cancel</Button>
36
+ <Button variant={"outlined"}
37
+ color={"primary"}
38
+ onClick={() => onClose()}>Cancel</Button>
36
39
  </DialogActions>
37
40
  </Dialog>
38
41
  }
@@ -1,5 +1,5 @@
1
1
  import { EntityCollection, isEmptyObject, useSnackbarController } from "@firecms/core";
2
- import { Button, ContentCopyIcon, Dialog, DialogActions, DialogContent, DialogTitle, Typography, } from "@firecms/ui";
2
+ import { Button, ContentCopyIcon, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@firecms/ui";
3
3
  import React from "react";
4
4
  import JSON5 from "json5";
5
5
  import { Highlight, themes } from "prism-react-renderer"
@@ -59,12 +59,13 @@ export function GetCodeDialog({
59
59
  <Button
60
60
  variant={"text"}
61
61
  size={"small"}
62
+ color={"primary"}
62
63
  onClick={(e) => {
63
64
  e.stopPropagation();
64
65
  e.preventDefault();
65
66
  snackbarController.open({
66
67
  type: "success",
67
- message: `Copied`
68
+ message: "Copied"
68
69
  })
69
70
  return navigator.clipboard.writeText(code);
70
71
  }}>
@@ -133,7 +134,8 @@ function collectionToCode(collection: EntityCollection): object {
133
134
  .map(([key, value]) => ({
134
135
  [key]: propertyCleanup(value)
135
136
  }))
136
- .reduce((a, b) => ({ ...a, ...b }), {}),
137
+ .reduce((a, b) => ({ ...a,
138
+ ...b }), {}),
137
139
  subcollections: (collection.subcollections ?? []).map(collectionToCode)
138
140
  }
139
141
 
@@ -295,6 +295,7 @@ export function PropertyFormDialog({
295
295
 
296
296
  {onCancel && <Button
297
297
  variant={"text"}
298
+ color={"primary"}
298
299
  onClick={() => {
299
300
  onCancel();
300
301
  formexRef.current?.resetForm();
@@ -37,8 +37,12 @@ export function UnsavedChangesDialog({
37
37
  </DialogContent>
38
38
 
39
39
  <DialogActions>
40
- <Button variant="text" onClick={handleCancel} autoFocus> Cancel </Button>
41
- <Button onClick={handleOk}> Ok </Button>
40
+ <Button variant="text"
41
+ color={"primary"}
42
+ onClick={handleCancel} autoFocus> Cancel </Button>
43
+ <Button
44
+ color={"primary"}
45
+ onClick={handleOk}> Ok </Button>
42
46
  </DialogActions>
43
47
  </Dialog>
44
48
  );
@@ -14,6 +14,7 @@ import { AddIcon, Button, Paper, Typography } from "@firecms/ui";
14
14
  import { useCollectionEditorController } from "./useCollectionEditorController";
15
15
  import { EditorCollectionActionStart } from "./ui/EditorCollectionActionStart";
16
16
  import { NewCollectionCard } from "./ui/NewCollectionCard";
17
+ import { EditorEntityAction } from "./ui/EditorEntityAction";
17
18
 
18
19
  export interface CollectionConfigControllerProps<EC extends PersistedCollection = PersistedCollection, USER extends User = User> {
19
20
 
@@ -107,6 +108,9 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
107
108
  CollectionActions: EditorCollectionAction,
108
109
  HeaderAction: CollectionViewHeaderAction,
109
110
  AddColumnComponent: PropertyAddColumnComponent
111
+ },
112
+ form: {
113
+ ActionsTop: EditorEntityAction,
110
114
  }
111
115
  };
112
116
  }