@firecms/collection_editor 3.0.0-canary.41 → 3.0.0-canary.42

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.
@@ -32,5 +32,5 @@ export interface CollectionEditorController {
32
32
  collection: PersistedCollection;
33
33
  }) => void;
34
34
  configPermissions: CollectionEditorPermissionsBuilder;
35
- rootPathSuggestions?: string[];
35
+ getPathSuggestions?: (path: string) => Promise<string[]>;
36
36
  }
@@ -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 }: {
@@ -25,12 +25,11 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
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
31
  getUser?: (uid: string) => UserType | null;
32
32
  onAnalyticsEvent?: (event: string, params?: object) => void;
33
- introMode?: "new_project" | "existing_project";
34
33
  }
35
34
  /**
36
35
  * Use this hook to initialise the Collection Editor plugin.
@@ -39,11 +38,11 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
39
38
  * @param configPermissions
40
39
  * @param reservedGroups
41
40
  * @param extraView
42
- * @param pathSuggestions
41
+ * @param getPathsSuggestions
43
42
  * @param getUser
44
43
  * @param collectionInference
45
44
  */
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>;
45
+ export declare function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, UserType extends User = User>({ collectionConfigController, configPermissions, reservedGroups, extraView, getPathSuggestions, getUser, collectionInference, getData, onAnalyticsEvent }: CollectionConfigControllerProps<EC, UserType>): FireCMSPlugin<any, any, PersistedCollection>;
47
46
  export declare function IntroWidget({ introMode }: {
48
47
  introMode?: "new_project" | "existing_project";
49
- }): import("react/jsx-runtime").JSX.Element;
48
+ }): import("react/jsx-runtime").JSX.Element | null;
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@firecms/collection_editor",
3
3
  "type": "module",
4
- "version": "3.0.0-canary.41",
4
+ "version": "3.0.0-canary.42",
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.41",
11
- "@firecms/formex": "^3.0.0-canary.41",
12
- "@firecms/schema_inference": "^3.0.0-canary.41",
13
- "@firecms/ui": "^3.0.0-canary.41",
10
+ "@firecms/data_import_export": "^3.0.0-canary.42",
11
+ "@firecms/formex": "^3.0.0-canary.42",
12
+ "@firecms/schema_inference": "^3.0.0-canary.42",
13
+ "@firecms/ui": "^3.0.0-canary.42",
14
14
  "json5": "^2.2.3",
15
15
  "prism-react-renderer": "^2.3.1"
16
16
  },
@@ -81,5 +81,5 @@
81
81
  "publishConfig": {
82
82
  "access": "public"
83
83
  },
84
- "gitHead": "d1ffa185f8930bab4e7b9941ba551c53f947aa1f"
84
+ "gitHead": "d6a2f28e93d3c532dd6efacfccffb91383d5330e"
85
85
  }
@@ -1,4 +1,4 @@
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";
@@ -48,7 +48,7 @@ export interface ConfigControllerProviderProps {
48
48
  icon: React.ReactNode
49
49
  };
50
50
 
51
- pathSuggestions?: (path?: string) => Promise<string[]>;
51
+ getPathSuggestions?: (path?: string) => Promise<string[]>;
52
52
 
53
53
  getUser?: (uid: string) => User | null
54
54
 
@@ -66,7 +66,7 @@ export const ConfigControllerProvider = React.memo(
66
66
  reservedGroups,
67
67
  collectionInference,
68
68
  extraView,
69
- pathSuggestions,
69
+ getPathSuggestions,
70
70
  getUser,
71
71
  getData,
72
72
  onAnalyticsEvent
@@ -77,20 +77,6 @@ export const ConfigControllerProvider = React.memo(
77
77
  const snackbarController = useSnackbarController();
78
78
  const { propertyConfigs } = useCustomizationController();
79
79
 
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
80
  const [currentDialog, setCurrentDialog] = React.useState<{
95
81
  isNewCollection: boolean,
96
82
  parentCollection?: PersistedCollection,
@@ -135,7 +121,10 @@ export const ConfigControllerProvider = React.memo(
135
121
  parentCollection?: PersistedCollection
136
122
  }) => {
137
123
  console.debug("Edit collection", id, fullPath, parentCollectionIds, parentCollection);
138
- onAnalyticsEvent?.("edit_collection", { id, fullPath });
124
+ onAnalyticsEvent?.("edit_collection", {
125
+ id,
126
+ fullPath
127
+ });
139
128
  setCurrentDialog({
140
129
  editedCollectionId: id,
141
130
  fullPath,
@@ -162,7 +151,10 @@ export const ConfigControllerProvider = React.memo(
162
151
  collection: PersistedCollection,
163
152
  }) => {
164
153
  console.debug("Edit property", propertyKey, property, editedCollectionId, currentPropertiesOrder, parentCollectionIds, collection);
165
- onAnalyticsEvent?.("edit_property", { propertyKey, editedCollectionId });
154
+ onAnalyticsEvent?.("edit_property", {
155
+ propertyKey,
156
+ editedCollectionId
157
+ });
166
158
  // namespace is all the path until the last dot
167
159
  const namespace = propertyKey && propertyKey.includes(".")
168
160
  ? propertyKey.substring(0, propertyKey.lastIndexOf("."))
@@ -175,7 +167,7 @@ export const ConfigControllerProvider = React.memo(
175
167
  property,
176
168
  namespace,
177
169
  currentPropertiesOrder,
178
- editedCollectionId: editedCollectionId,
170
+ editedCollectionId,
179
171
  parentCollectionIds,
180
172
  collectionEditable: collection?.editable ?? false
181
173
  });
@@ -198,8 +190,20 @@ export const ConfigControllerProvider = React.memo(
198
190
  redirect: boolean,
199
191
  sourceClick?: string
200
192
  }) => {
201
- console.debug("Create collection", { parentCollectionIds, parentCollection, initialValues, redirect, sourceClick });
202
- onAnalyticsEvent?.("create_collection", { parentCollectionIds, parentCollection, initialValues, redirect, sourceClick });
193
+ console.debug("Create collection", {
194
+ parentCollectionIds,
195
+ parentCollection,
196
+ initialValues,
197
+ redirect,
198
+ sourceClick
199
+ });
200
+ onAnalyticsEvent?.("create_collection", {
201
+ parentCollectionIds,
202
+ parentCollection,
203
+ initialValues,
204
+ redirect,
205
+ sourceClick
206
+ });
203
207
  setCurrentDialog({
204
208
  isNewCollection: true,
205
209
  parentCollectionIds,
@@ -209,16 +213,6 @@ export const ConfigControllerProvider = React.memo(
209
213
  });
210
214
  }, []);
211
215
 
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
- }
221
-
222
216
  return (
223
217
  <ConfigControllerContext.Provider value={collectionConfigController}>
224
218
  <CollectionEditorContext.Provider
@@ -227,7 +221,7 @@ export const ConfigControllerProvider = React.memo(
227
221
  createCollection,
228
222
  editProperty,
229
223
  configPermissions: configPermissions ?? defaultConfigPermissions,
230
- rootPathSuggestions
224
+ getPathSuggestions
231
225
  }}>
232
226
 
233
227
  {children}
@@ -38,6 +38,6 @@ export interface CollectionEditorController {
38
38
 
39
39
  configPermissions: CollectionEditorPermissionsBuilder;
40
40
 
41
- rootPathSuggestions?: string[];
41
+ getPathSuggestions?: (path: string) => Promise<string[]>;
42
42
 
43
43
  }
@@ -216,7 +216,7 @@ export function CollectionDetailsForm({
216
216
  label={"Collection id"}
217
217
  error={showErrors && Boolean(errors.id)}/>
218
218
  <FieldCaption error={touched.id && Boolean(errors.id)}>
219
- {touched.id && Boolean(errors.id) ? errors.id : "This id identifies this collection"}
219
+ {touched.id && Boolean(errors.id) ? errors.id : "This id identifies this collection. Typically the same as the path."}
220
220
  </FieldCaption>
221
221
  </div>
222
222
 
@@ -487,19 +487,23 @@ function CollectionEditorInternal<M extends Record<string, any>>({
487
487
  setFormDirty(dirty);
488
488
  }, [dirty]);
489
489
 
490
- function onImportDataSet(data: object[]) {
490
+ function onImportDataSet(data: object[], propertiesOrder?: string[]) {
491
491
  importConfig.setInUse(true);
492
492
  buildEntityPropertiesFromData(data, getInferenceType)
493
493
  .then((properties) => {
494
494
  const res = cleanPropertiesFromImport(properties);
495
495
 
496
- setFieldValue("properties", res.properties);
497
- setFieldValue("propertiesOrder", Object.keys(res.properties));
498
-
499
496
  importConfig.setIdColumn(res.idColumn);
500
497
  importConfig.setImportData(data);
501
498
  importConfig.setHeadersMapping(res.headersMapping);
499
+ const filteredHeadingsOrder = ((propertiesOrder ?? [])
500
+ .filter((key) => res.headersMapping[key]) as string[]) ?? Object.keys(res.properties);
501
+ importConfig.setHeadingsOrder(filteredHeadingsOrder);
502
502
  importConfig.setOriginProperties(res.properties);
503
+
504
+ const mappedHeadings = (propertiesOrder ?? []).map((key) => res.headersMapping[key]).filter(Boolean) as string[] ?? Object.keys(res.properties);
505
+ setFieldValue("properties", res.properties);
506
+ setFieldValue("propertiesOrder", mappedHeadings);
503
507
  });
504
508
  }
505
509
 
@@ -552,9 +556,10 @@ function CollectionEditorInternal<M extends Record<string, any>>({
552
556
  {currentView === "welcome" &&
553
557
  <CollectionEditorWelcomeView
554
558
  path={path}
555
- onContinue={(importData) => {
559
+ onContinue={(importData, propertiesOrder) => {
560
+ // console.log("Import data", importData, propertiesOrder)
556
561
  if (importData) {
557
- onImportDataSet(importData);
562
+ onImportDataSet(importData, propertiesOrder);
558
563
  setCurrentView("import_data_mapping");
559
564
  } else {
560
565
  setCurrentView("details");
@@ -19,7 +19,7 @@ export function CollectionEditorWelcomeView({
19
19
  path: string;
20
20
  pathSuggestions?: (path: string) => Promise<string[]>;
21
21
  parentCollection?: EntityCollection;
22
- onContinue: (importData?: object[]) => void;
22
+ onContinue: (importData?: object[], propertiesOrder?: string[]) => void;
23
23
  existingCollectionPaths?: string[];
24
24
  }) {
25
25
 
@@ -154,7 +154,7 @@ export function CollectionEditorWelcomeView({
154
154
  ● Create a collection from a file (csv, json, xls, xslx...)
155
155
  </Typography>
156
156
 
157
- <ImportFileUpload onDataAdded={(data) => onContinue(data)}/>
157
+ <ImportFileUpload onDataAdded={(data, propertiesOrder) => onContinue(data, propertiesOrder)}/>
158
158
 
159
159
  </div>}
160
160
 
@@ -1,21 +1,33 @@
1
1
  import { convertDataToEntity, getPropertiesMapping, ImportConfig } from "@firecms/data_import_export";
2
- import { EntityCollectionTable, Properties, useSelectionController } from "@firecms/core";
3
- import { useEffect } from "react";
2
+ import { CircularProgressCenter, EntityCollectionTable, Properties, useSelectionController } from "@firecms/core";
3
+ import { useEffect, useState } from "react";
4
4
  import { Typography } from "@firecms/ui";
5
5
 
6
- export function CollectionEditorImportDataPreview({ importConfig, properties, propertiesOrder }: {
6
+ export function CollectionEditorImportDataPreview({
7
+ importConfig,
8
+ properties,
9
+ propertiesOrder
10
+ }: {
7
11
  importConfig: ImportConfig,
8
12
  properties: Properties,
9
13
  propertiesOrder: string[]
10
14
  }) {
11
15
 
12
- useEffect(() => {
16
+ const [loading, setLoading] = useState<boolean>(false);
17
+
18
+ async function loadEntities() {
13
19
  const propertiesMapping = getPropertiesMapping(importConfig.originProperties, properties);
14
20
  const mappedData = importConfig.importData.map(d => convertDataToEntity(d, importConfig.idColumn, importConfig.headersMapping, properties, propertiesMapping, "TEMP_PATH"));
15
21
  importConfig.setEntities(mappedData);
22
+ }
23
+
24
+ useEffect(() => {
25
+ loadEntities().finally(() => setLoading(false));
16
26
  }, []);
17
27
 
18
28
  const selectionController = useSelectionController();
29
+ if (loading)
30
+ return <CircularProgressCenter/>
19
31
 
20
32
  return <EntityCollectionTable
21
33
  title={<div>
@@ -31,7 +43,10 @@ export function CollectionEditorImportDataPreview({ importConfig, properties, pr
31
43
  filterable={false}
32
44
  sortable={false}
33
45
  selectionController={selectionController}
34
- displayedColumnIds={propertiesOrder.map(p => ({ key: p, disabled: false }))}
46
+ displayedColumnIds={propertiesOrder.map(p => ({
47
+ key: p,
48
+ disabled: false
49
+ }))}
35
50
  properties={properties}/>
36
51
 
37
52
  }
@@ -6,7 +6,7 @@ import {
6
6
  } from "@firecms/data_import_export";
7
7
  import { getIn, useFormex } from "@firecms/formex";
8
8
 
9
- import { PropertyConfigBadge, getFieldConfig, getFieldId, Properties, Property, PropertyConfig, } from "@firecms/core";
9
+ import { getFieldConfig, getFieldId, Properties, Property, PropertyConfig, PropertyConfigBadge, } from "@firecms/core";
10
10
  import { Container, Select, Tooltip, Typography } from "@firecms/ui";
11
11
  import React, { useState } from "react";
12
12
  import { OnPropertyChangedParams, PropertyFormDialog, PropertyWithId } from "../PropertyEditView";
@@ -143,9 +143,10 @@ export function CollectionEditorImportMapping({
143
143
  <div className={"overflow-auto my-auto"}>
144
144
  <Container maxWidth={"6xl"} className={"flex flex-col gap-4 p-8 m-auto"}>
145
145
 
146
- <Typography variant="h6" className={"mt-4"}>Data property mapping</Typography>
146
+ <Typography variant="h6" className={"my-4 ml-3.5"}>Data property mapping</Typography>
147
147
 
148
148
  <DataNewPropertiesMapping headersMapping={importConfig.headersMapping}
149
+ headingsOrder={importConfig.headingsOrder}
149
150
  idColumn={importConfig.idColumn}
150
151
  originProperties={importConfig.originProperties}
151
152
  destinationProperties={values.properties as Properties}
@@ -153,8 +154,13 @@ export function CollectionEditorImportMapping({
153
154
  buildPropertyView={({
154
155
  property,
155
156
  propertyKey,
156
- importKey
157
+ importKey,
158
+ isIdColumn
157
159
  }) => {
160
+ if (isIdColumn) {
161
+ return <Typography> This column will be used as ID</Typography>
162
+ }
163
+
158
164
  return <ImportNewPropertyFieldPreview
159
165
  property={property}
160
166
  propertyKey={propertyKey}
@@ -4,17 +4,16 @@ import { ConfigControllerProvider } from "./ConfigControllerProvider";
4
4
  import { CollectionEditorPermissionsBuilder } from "./types/config_permissions";
5
5
  import { EditorCollectionAction } from "./ui/EditorCollectionAction";
6
6
  import { HomePageEditorCollectionAction } from "./ui/HomePageEditorCollectionAction";
7
- import { NewCollectionCard } from "./ui/NewCollectionCard";
8
7
  import { PersistedCollection } from "./types/persisted_collection";
9
8
  import { CollectionInference } from "./types/collection_inference";
10
9
  import { CollectionsConfigController } from "./types/config_controller";
11
- import { RootCollectionSuggestions } from "./ui/RootCollectionSuggestions";
12
10
  import { CollectionViewHeaderAction } from "./ui/CollectionViewHeaderAction";
13
11
  import { PropertyAddColumnComponent } from "./ui/PropertyAddColumnComponent";
14
12
  import { NewCollectionButton } from "./ui/NewCollectionButton";
15
- import { AddIcon, Button, Typography } from "@firecms/ui";
13
+ import { AddIcon, Button, Paper, Typography } from "@firecms/ui";
16
14
  import { useCollectionEditorController } from "./useCollectionEditorController";
17
15
  import { EditorCollectionActionStart } from "./ui/EditorCollectionActionStart";
16
+ import { NewCollectionCard } from "./ui/NewCollectionCard";
18
17
 
19
18
  export interface CollectionConfigControllerProps<EC extends PersistedCollection = PersistedCollection, UserType extends User = User> {
20
19
 
@@ -42,7 +41,7 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
42
41
  icon: React.ReactNode
43
42
  };
44
43
 
45
- pathSuggestions?: (path: string) => Promise<string[]>;
44
+ getPathSuggestions?: (path?: string) => Promise<string[]>;
46
45
 
47
46
  collectionInference?: CollectionInference;
48
47
 
@@ -52,8 +51,6 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
52
51
 
53
52
  onAnalyticsEvent?: (event: string, params?: object) => void;
54
53
 
55
- introMode?: "new_project" | "existing_project";
56
-
57
54
  }
58
55
 
59
56
  /**
@@ -63,18 +60,17 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
63
60
  * @param configPermissions
64
61
  * @param reservedGroups
65
62
  * @param extraView
66
- * @param pathSuggestions
63
+ * @param getPathsSuggestions
67
64
  * @param getUser
68
65
  * @param collectionInference
69
66
  */
70
67
  export function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, UserType extends User = User>
71
68
  ({
72
69
  collectionConfigController,
73
- introMode,
74
70
  configPermissions,
75
71
  reservedGroups,
76
72
  extraView,
77
- pathSuggestions,
73
+ getPathSuggestions,
78
74
  getUser,
79
75
  collectionInference,
80
76
  getData,
@@ -92,7 +88,7 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
92
88
  collectionInference,
93
89
  reservedGroups,
94
90
  extraView,
95
- pathSuggestions,
91
+ getPathSuggestions,
96
92
  getUser,
97
93
  getData,
98
94
  onAnalyticsEvent
@@ -100,10 +96,10 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
100
96
  },
101
97
  homePage: {
102
98
  additionalActions: <NewCollectionButton/>,
103
- additionalChildrenStart: introMode ? <IntroWidget introMode={introMode}/> : undefined,
104
- additionalChildrenEnd: <RootCollectionSuggestions introMode={introMode}/>,
99
+ additionalChildrenStart: <IntroWidget/>,
100
+ // additionalChildrenEnd: <RootCollectionSuggestions introMode={introMode}/>,
105
101
  CollectionActions: HomePageEditorCollectionAction,
106
- AdditionalCards: introMode ? undefined : NewCollectionCard,
102
+ AdditionalCards: NewCollectionCard,
107
103
  },
108
104
  collectionView: {
109
105
  CollectionActionsStart: EditorCollectionActionStart,
@@ -131,17 +127,19 @@ export function IntroWidget({ introMode }: {
131
127
  }).createCollections
132
128
  : true;
133
129
 
130
+ if ((navigation.collections ?? []).length > 0) {
131
+ return null;
132
+ }
133
+
134
134
  return (
135
- <div className={"mt-8 flex flex-col mt-8 p-2"}>
136
- <Typography variant={"h4"} className="mb-4">Welcome</Typography>
137
- <Typography paragraph={true}>Your admin panel is ready ✌️</Typography>
138
- <Typography paragraph={true}>
135
+ <Paper
136
+ className={"my-4 px-4 py-6 flex flex-col bg-white dark:bg-slate-800 gap-2"}>
137
+ <Typography variant={"subtitle2"} className={"uppercase"}>No collections found</Typography>
138
+ <Typography>
139
139
  Start building collections in FireCMS easily. Map them to your existing
140
- database data, import from files, or use our templates. Simplify your data management process
141
- now.
140
+ database data, import from files, or use our templates.
142
141
  </Typography>
143
142
  {canCreateCollections && <Button
144
- className={"mt-4"}
145
143
  onClick={collectionEditorController && canCreateCollections
146
144
  ? () => collectionEditorController.createCollection({
147
145
  parentCollectionIds: [],
@@ -151,6 +149,9 @@ export function IntroWidget({ introMode }: {
151
149
  : undefined}>
152
150
  <AddIcon/>Create your first collection
153
151
  </Button>}
154
- </div>
152
+ <Typography variant={"caption"} color={"secondary"}>
153
+ You can also define collections programmatically.
154
+ </Typography>
155
+ </Paper>
155
156
  );
156
157
  }
@@ -1,3 +0,0 @@
1
- export declare function RootCollectionSuggestions({ introMode }: {
2
- introMode?: "new_project" | "existing_project";
3
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,63 +0,0 @@
1
- import { unslugify, useAuthController, useNavigationController } from "@firecms/core";
2
- import { AddIcon, Chip, CircularProgress, Collapse, Typography, } from "@firecms/ui";
3
- import { useCollectionEditorController } from "../useCollectionEditorController";
4
- import React from "react";
5
-
6
- export function RootCollectionSuggestions({ introMode }: { introMode?: "new_project" | "existing_project" }) {
7
-
8
- const authController = useAuthController();
9
- const navigationController = useNavigationController();
10
-
11
- const collectionEditorController = useCollectionEditorController();
12
- const canCreateCollections = collectionEditorController.configPermissions
13
- ? collectionEditorController.configPermissions({
14
- user: authController.user
15
- }).createCollections
16
- : true;
17
-
18
- const rootPathSuggestions = collectionEditorController.rootPathSuggestions;
19
-
20
- const showSuggestions = (rootPathSuggestions ?? []).length > 3 || ((navigationController.collections ?? []).length === 0 && (rootPathSuggestions ?? []).length > 0);
21
- const forceShowSuggestions = introMode === "existing_project";
22
- return <Collapse
23
- in={forceShowSuggestions || showSuggestions}>
24
-
25
- <div
26
- className={"flex flex-col gap-1 p-2 my-4"}>
27
-
28
- {!introMode && <Typography variant={"body2"} color={"secondary"}>
29
- Create a collection <b>automatically</b> from your data:
30
- </Typography>}
31
-
32
- {introMode === "existing_project" && <Typography>
33
- You will see your <b>database collections</b> here, a few seconds after project creation
34
- </Typography>}
35
-
36
- <div
37
- className={"flex flex-row gap-1 overflow-scroll no-scrollbar "}>
38
- {(rootPathSuggestions ?? []).map((path) => {
39
- return (
40
- <div key={path}>
41
- <Chip
42
- icon={<AddIcon size={"small"}/>}
43
- colorScheme={"cyanLighter"}
44
- onClick={collectionEditorController && canCreateCollections
45
- ? () => collectionEditorController.createCollection({
46
- initialValues: { path, name: unslugify(path) },
47
- parentCollectionIds: [],
48
- redirect: true,
49
- sourceClick: "root_collection_suggestion"
50
- })
51
- : undefined}
52
- size="small">
53
- {path}
54
- </Chip>
55
- </div>
56
- );
57
- })}
58
- {rootPathSuggestions === undefined && <CircularProgress size={"small"}/>}
59
- {rootPathSuggestions?.length === 0 && <Typography variant={"caption"}>No suggestions</Typography>}
60
- </div>
61
- </div>
62
- </Collapse>
63
- }