@firecms/collection_editor 3.0.0-beta.11 → 3.0.0-beta.12

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,4 +1,3 @@
1
- import React from "react";
2
1
  import { CollectionEditorPermissionsBuilder } from "./config_permissions";
3
2
  import { Entity, Property } from "@firecms/core";
4
3
  import { PersistedCollection } from "./persisted_collection";
@@ -36,13 +35,4 @@ export interface CollectionEditorController {
36
35
  }) => void;
37
36
  configPermissions: CollectionEditorPermissionsBuilder;
38
37
  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
- };
48
38
  }
@@ -1,5 +1,6 @@
1
+ import React from "react";
1
2
  import { EntityCollection } from "@firecms/core";
2
- export declare function CollectionDetailsForm({ isNewCollection, reservedGroups, existingPaths, existingIds, groups, parentCollection }: {
3
+ export declare function CollectionDetailsForm({ isNewCollection, reservedGroups, existingPaths, existingIds, groups, parentCollection, children }: {
3
4
  isNewCollection: boolean;
4
5
  reservedGroups?: string[];
5
6
  existingPaths?: string[];
@@ -7,4 +8,5 @@ export declare function CollectionDetailsForm({ isNewCollection, reservedGroups,
7
8
  groups: string[] | null;
8
9
  parentCollection?: EntityCollection;
9
10
  parentCollectionIds?: string[];
11
+ children?: React.ReactNode;
10
12
  }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ export declare function LayoutModeSwitch({ value, onChange, className }: {
2
+ value: "side_panel" | "full_screen";
3
+ onChange: (value: "side_panel" | "full_screen") => void;
4
+ className?: string;
5
+ }): import("react/jsx-runtime").JSX.Element;
@@ -30,15 +30,6 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
30
30
  getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
31
31
  getUser?: (uid: string) => USER | null;
32
32
  onAnalyticsEvent?: (event: string, params?: object) => void;
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
- };
42
33
  }
43
34
  /**
44
35
  * Use this hook to initialise the Collection Editor plugin.
@@ -51,5 +42,5 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
51
42
  * @param getUser
52
43
  * @param collectionInference
53
44
  */
54
- export declare function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, USER extends User = User>({ collectionConfigController, configPermissions, reservedGroups, extraView, getPathSuggestions, getUser, collectionInference, getData, onAnalyticsEvent, components }: CollectionConfigControllerProps<EC, USER>): FireCMSPlugin<any, any, PersistedCollection>;
45
+ export declare function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, USER extends User = User>({ collectionConfigController, configPermissions, reservedGroups, extraView, getPathSuggestions, getUser, collectionInference, getData, onAnalyticsEvent, }: CollectionConfigControllerProps<EC, USER>): FireCMSPlugin<any, any, PersistedCollection>;
55
46
  export declare function IntroWidget({}: {}): import("react/jsx-runtime").JSX.Element | null;
@@ -3,4 +3,4 @@ import { PersistedCollection } from "../types/persisted_collection";
3
3
  /**
4
4
  * Function in charge of merging collections defined in code with those stored in the backend.
5
5
  */
6
- export declare const mergeCollections: (baseCollections: EntityCollection[], backendCollections: PersistedCollection[], modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | void) => EntityCollection<any, any>[];
6
+ export declare const mergeCollections: (baseCollections: EntityCollection[], backendCollections?: PersistedCollection[], modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | void) => EntityCollection<any, any>[];
package/package.json CHANGED
@@ -1,24 +1,25 @@
1
1
  {
2
2
  "name": "@firecms/collection_editor",
3
3
  "type": "module",
4
- "version": "3.0.0-beta.11",
4
+ "version": "3.0.0-beta.12",
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-beta.11",
11
- "@firecms/data_import": "^3.0.0-beta.11",
12
- "@firecms/data_import_export": "^3.0.0-beta.11",
13
- "@firecms/formex": "^3.0.0-beta.11",
14
- "@firecms/schema_inference": "^3.0.0-beta.11",
15
- "@firecms/ui": "^3.0.0-beta.11",
10
+ "@firecms/data_export": "^3.0.0-beta.12",
11
+ "@firecms/data_import": "^3.0.0-beta.12",
12
+ "@firecms/data_import_export": "^3.0.0-beta.12",
13
+ "@firecms/formex": "^3.0.0-beta.12",
14
+ "@firecms/schema_inference": "^3.0.0-beta.12",
15
+ "@firecms/ui": "^3.0.0-beta.12",
16
+ "@hello-pangea/dnd": "^17.0.0",
16
17
  "json5": "^2.2.3",
17
- "prism-react-renderer": "^2.4.0"
18
+ "prism-react-renderer": "^2.4.1"
18
19
  },
19
20
  "peerDependencies": {
20
- "react": "^18.3.1",
21
- "react-dom": "^18.3.1",
21
+ "react": ">=18.0.0",
22
+ "react-dom": ">=18.0.0",
22
23
  "react-router": "^6.28.0",
23
24
  "react-router-dom": "^6.28.0"
24
25
  },
@@ -50,17 +51,17 @@
50
51
  },
51
52
  "devDependencies": {
52
53
  "@jest/globals": "^29.7.0",
53
- "@types/react": "^18.3.11",
54
- "@types/react-dom": "^18.3.1",
54
+ "@types/react": "^18.3.18",
55
+ "@types/react-dom": "^18.3.0",
55
56
  "@vitejs/plugin-react": "^4.3.4",
56
57
  "babel-plugin-react-compiler": "beta",
57
58
  "eslint-plugin-react-compiler": "beta",
58
59
  "jest": "^29.7.0",
59
- "react-router": "^6.28.0",
60
- "react-router-dom": "^6.28.0",
60
+ "react-router": "^6.28.2",
61
+ "react-router-dom": "^6.28.2",
61
62
  "ts-jest": "^29.2.5",
62
- "typescript": "^5.7.2",
63
- "vite": "^5.4.11"
63
+ "typescript": "^5.7.3",
64
+ "vite": "^5.4.14"
64
65
  },
65
66
  "files": [
66
67
  "dist",
@@ -69,5 +70,5 @@
69
70
  "publishConfig": {
70
71
  "access": "public"
71
72
  },
72
- "gitHead": "cb6d419faf2664cfd6cb2603a834e4bf499a92bb"
73
+ "gitHead": "8de3edb4560643922fe44e9c357985f64c3951c1"
73
74
  }
@@ -57,13 +57,6 @@ export interface ConfigControllerProviderProps {
57
57
 
58
58
  onAnalyticsEvent?: (event: string, params?: object) => void;
59
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
-
67
60
  }
68
61
 
69
62
  export const ConfigControllerProvider = React.memo(
@@ -78,7 +71,6 @@ export const ConfigControllerProvider = React.memo(
78
71
  getUser,
79
72
  getData,
80
73
  onAnalyticsEvent,
81
- components
82
74
  }: PropsWithChildren<ConfigControllerProviderProps>) {
83
75
 
84
76
  const navigation = useNavigationController();
@@ -239,7 +231,6 @@ export const ConfigControllerProvider = React.memo(
239
231
  editProperty,
240
232
  configPermissions: configPermissions ?? defaultConfigPermissions,
241
233
  getPathSuggestions,
242
- components
243
234
  }}>
244
235
 
245
236
  {children}
@@ -277,7 +268,7 @@ export const ConfigControllerProvider = React.memo(
277
268
  getData={getData && currentPropertyDialog?.editedCollectionId
278
269
  ? () => {
279
270
  console.debug("get data for property", currentPropertyDialog?.editedCollectionId);
280
- const resolvedPath = navigation.resolveAliasesFrom(currentPropertyDialog.editedCollectionId!)
271
+ const resolvedPath = navigation.resolveIdsFrom(currentPropertyDialog.editedCollectionId!)
281
272
  return getData(resolvedPath, []);
282
273
  }
283
274
  : undefined}
@@ -43,11 +43,4 @@ export interface CollectionEditorController {
43
43
 
44
44
  getPathSuggestions?: (path: string) => Promise<string[]>;
45
45
 
46
- components?: {
47
- /**
48
- * Custom component to render the database field
49
- */
50
- DatabaseField?: React.ComponentType<{ databaseId?: string, onDatabaseIdUpdate: (databaseId: string) => void }>;
51
- };
52
-
53
46
  }
@@ -14,6 +14,7 @@ export function HomePageEditorCollectionAction({
14
14
  collection
15
15
  }: PluginHomePageActionsProps) {
16
16
 
17
+
17
18
  const snackbarController = useSnackbarController();
18
19
  const authController = useAuthController();
19
20
  const configController = useCollectionsConfigController();
@@ -23,6 +23,7 @@ import {
23
23
 
24
24
  import { Field, getIn, useFormex } from "@firecms/formex";
25
25
  import { useCollectionEditorController } from "../../useCollectionEditorController";
26
+ import { LayoutModeSwitch } from "./LayoutModeSwitch";
26
27
 
27
28
  export function CollectionDetailsForm({
28
29
  isNewCollection,
@@ -30,7 +31,8 @@ export function CollectionDetailsForm({
30
31
  existingPaths,
31
32
  existingIds,
32
33
  groups,
33
- parentCollection
34
+ parentCollection,
35
+ children
34
36
  }: {
35
37
  isNewCollection: boolean,
36
38
  reservedGroups?: string[];
@@ -39,6 +41,7 @@ export function CollectionDetailsForm({
39
41
  groups: string[] | null;
40
42
  parentCollection?: EntityCollection;
41
43
  parentCollectionIds?: string[];
44
+ children?: React.ReactNode;
42
45
  }) {
43
46
 
44
47
  const groupRef = React.useRef<HTMLInputElement>(null);
@@ -88,8 +91,6 @@ export function CollectionDetailsForm({
88
91
  }
89
92
  }, [errors.id]);
90
93
 
91
- const DatabaseField = collectionEditor.components?.DatabaseField ?? DefaultDatabaseField;
92
-
93
94
  const collectionIcon = <IconForView collectionOrView={values}/>;
94
95
 
95
96
  const groupOptions = groups?.filter((group) => !reservedGroups?.includes(group));
@@ -126,8 +127,8 @@ export function CollectionDetailsForm({
126
127
  <Typography variant={!isNewCollection ? "h5" : "h4"} className={"flex-grow"}>
127
128
  {isNewCollection ? "New collection" : `${values?.name} collection`}
128
129
  </Typography>
129
- <DatabaseField databaseId={values.databaseId}
130
- onDatabaseIdUpdate={updateDatabaseId}/>
130
+ <DefaultDatabaseField databaseId={values.databaseId}
131
+ onDatabaseIdUpdate={updateDatabaseId}/>
131
132
 
132
133
  <Tooltip title={"Change icon"}
133
134
  asChild={true}>
@@ -207,9 +208,16 @@ export function CollectionDetailsForm({
207
208
  <FieldCaption>
208
209
  {showErrors && Boolean(errors.group) ? errors.group : "Group in the home page"}
209
210
  </FieldCaption>
211
+
212
+
210
213
  </div>}
211
214
 
212
- <div className={"col-span-12"}>
215
+ <LayoutModeSwitch
216
+ className={"col-span-12"}
217
+ value={values.openEntityMode ?? "side_panel"}
218
+ onChange={(value) => setFieldValue("openEntityMode", value)}/>
219
+
220
+ <div className={"col-span-12 mt-8"}>
213
221
  <ExpandablePanel
214
222
  expanded={advancedPanelExpanded}
215
223
  onExpandedChange={setAdvancedPanelExpanded}
@@ -382,9 +390,13 @@ export function CollectionDetailsForm({
382
390
  for large collections, as it may incur in performance and cost issues.
383
391
  </FieldCaption>
384
392
  </div>
393
+
394
+
385
395
  </div>
386
396
  </ExpandablePanel>
387
397
 
398
+ {children}
399
+
388
400
  </div>
389
401
 
390
402
  </div>
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  import {
4
4
  CircularProgressCenter,
5
+ ConfirmationDialog,
5
6
  Entity,
6
7
  EntityCollection,
7
8
  ErrorView,
@@ -37,7 +38,8 @@ import {
37
38
  IconButton,
38
39
  LoadingButton,
39
40
  Tab,
40
- Tabs
41
+ Tabs,
42
+ Typography
41
43
  } from "@firecms/ui";
42
44
  import { YupSchema } from "./CollectionYupValidation";
43
45
  import { CollectionDetailsForm } from "./CollectionDetailsForm";
@@ -487,7 +489,7 @@ function CollectionEditorInternal<M extends Record<string, any>>({
487
489
  const pathError = validatePath(path, isNewCollection, existingPaths, values.id);
488
490
 
489
491
  const parentPaths = !pathError && parentCollectionIds ? navigation.convertIdsToPaths(parentCollectionIds) : undefined;
490
- const resolvedPath = !pathError ? navigation.resolveAliasesFrom(updatedFullPath) : undefined;
492
+ const resolvedPath = !pathError ? navigation.resolveIdsFrom(updatedFullPath) : undefined;
491
493
  const getDataWithPath = resolvedPath && getData ? async () => {
492
494
  const data = await getData(resolvedPath, parentPaths ?? []);
493
495
  if (existingEntities) {
@@ -533,14 +535,30 @@ function CollectionEditorInternal<M extends Record<string, any>>({
533
535
  };
534
536
 
535
537
  const editable = collection?.editable === undefined || collection?.editable === true;
538
+ // @ts-ignore
539
+ const isMergedCollection = collection?.merged ?? false;
536
540
  const collectionEditable = editable || isNewCollection;
537
541
 
542
+ const [deleteRequested, setDeleteRequested] = useState(false);
543
+
544
+ const deleteCollection = () => {
545
+ if (!collection) return;
546
+ configController?.deleteCollection({ id: collection.id }).then(() => {
547
+ setDeleteRequested(false);
548
+ handleCancel();
549
+ snackbarController.open({
550
+ message: "Collection deleted",
551
+ type: "success"
552
+ });
553
+ });
554
+ };
555
+
538
556
  return <DialogContent fullHeight={true}>
539
557
  <Formex value={formController}>
540
558
 
541
559
  <>
542
560
  {!isNewCollection && <Tabs value={currentView}
543
- innerClassName={cls(defaultBorderMixin, "justify-end bg-surface-50 dark:bg-surface-950 border-b")}
561
+ innerClassName={cls(defaultBorderMixin, "px-4 h-14 w-full justify-end bg-surface-50 dark:bg-surface-950 border-b")}
544
562
  onValueChange={(v) => setCurrentView(v as EditorView)}>
545
563
  <Tab value={"details"}>
546
564
  Details
@@ -614,7 +632,18 @@ function CollectionEditorInternal<M extends Record<string, any>>({
614
632
  groups={groups}
615
633
  parentCollectionIds={parentCollectionIds}
616
634
  parentCollection={parentCollection}
617
- isNewCollection={isNewCollection}/>}
635
+ isNewCollection={isNewCollection}>
636
+ {!isNewCollection && isMergedCollection && <div className={"flex flex-col gap-4 mt-8"}>
637
+ <Typography variant={"body2"} color={"secondary"}>This collection is defined in code.
638
+ The changes done in this editor will override the properties defined in code.
639
+ You can delete the overridden values to revert to the state defined in code.
640
+ </Typography>
641
+ <Button variant={"neutral"}
642
+ onClick={() => {
643
+ setDeleteRequested(true);
644
+ }}>Reset to code</Button>
645
+ </div>}
646
+ </CollectionDetailsForm>}
618
647
 
619
648
  {currentView === "subcollections" && collection &&
620
649
  <SubcollectionsEditTab
@@ -748,6 +777,15 @@ function CollectionEditorInternal<M extends Record<string, any>>({
748
777
 
749
778
  </Formex>
750
779
 
780
+ <ConfirmationDialog
781
+ open={deleteRequested}
782
+ onAccept={deleteCollection}
783
+ onCancel={() => setDeleteRequested(false)}
784
+ title={<>Delete the stored config?</>}
785
+ body={<> This will <b>not
786
+ delete any data</b>, only
787
+ the stored config, and reset to the code state.</>}/>
788
+
751
789
  </DialogContent>
752
790
 
753
791
  }
@@ -228,8 +228,6 @@ export function CollectionPropertiesEditorForm({
228
228
  namespace
229
229
  }: OnPropertyChangedParams) => {
230
230
 
231
- console.log("!!!!!! onPropertyChanged", property)
232
-
233
231
  const fullId = id ? getFullId(id, namespace) : undefined;
234
232
  const propertyPath = fullId ? idToPropertiesPath(fullId) : undefined;
235
233
 
@@ -183,7 +183,7 @@ function EnumFormFields({
183
183
  variant={"text"}
184
184
  size={"small"}
185
185
  onClick={inferValues}>
186
- {inferring ? <CircularProgress size={"small"}/> : <AutorenewIcon/>}
186
+ {inferring ? <CircularProgress size={"smallest"}/> : <AutorenewIcon/>}
187
187
  Infer values from data
188
188
  </Button>}
189
189
  </div>
@@ -28,7 +28,7 @@ export function GetCodeDialog({
28
28
  app configuration.
29
29
  More info in the <a
30
30
  rel="noopener noreferrer"
31
- href={"https://firecms.co/docs/customization_quickstart"}>docs</a>.
31
+ href={"https://firecms.co/docs/cloud/quickstart"}>docs</a>.
32
32
  </Typography>
33
33
  <Highlight
34
34
  theme={themes.vsDark}
@@ -0,0 +1,54 @@
1
+ import { Card, cls, SquareIcon, Tooltip, Typography, VerticalSplitIcon } from "@firecms/ui";
2
+
3
+ export function LayoutModeSwitch({
4
+ value,
5
+ onChange,
6
+ className
7
+ }: {
8
+ value: "side_panel" | "full_screen";
9
+ onChange: (value: "side_panel" | "full_screen") => void;
10
+ className?: string;
11
+ }) {
12
+
13
+ return <div className={cls(className)}>
14
+ <Typography variant={"label"} color={"secondary"} className={"ml-3.5"}>Document view</Typography>
15
+ <div className={cls("flex flex-row gap-4")}>
16
+
17
+ <Tooltip title={"Documents are open in a side panel"}>
18
+ <Card
19
+ onClick={() => onChange("side_panel")}
20
+ className={cls(
21
+ "my-2 rounded-md mx-0 p-4 focus:outline-none transition ease-in-out duration-150 flex flex-row gap-4 items-center",
22
+ "text-surface-700 dark:text-surface-accent-300",
23
+ "hover:text-primary-dark dark:hover:text-primary focus:ring-primary hover:ring-1 hover:ring-primary",
24
+ value === "side_panel" ? "border-primary dark:border-primary" : "border-surface-400 dark:border-surface-600",
25
+ )}
26
+ >
27
+ <VerticalSplitIcon/>
28
+ <Typography variant={"label"}>
29
+ Side panel
30
+ </Typography>
31
+ </Card>
32
+ </Tooltip>
33
+
34
+ <Tooltip title={"Documents are open full-screen"}>
35
+ <Card
36
+ onClick={() => onChange("full_screen")}
37
+ className={cls(
38
+ "my-2 rounded-md mx-0 p-4 focus:outline-none transition ease-in-out duration-150 flex flex-row gap-4 items-center",
39
+ "text-surface-700 dark:text-surface-accent-300",
40
+ "hover:text-primary-dark dark:hover:text-primary focus:ring-primary hover:ring-1 hover:ring-primary",
41
+ value === "full_screen" ? "border-primary dark:border-primary" : "border-surface-400 dark:border-surface-600",
42
+ )}
43
+ >
44
+ <SquareIcon/>
45
+ <Typography variant={"label"}>
46
+ Full screen
47
+ </Typography>
48
+ </Card>
49
+ </Tooltip>
50
+
51
+ </div>
52
+ <Typography variant={"caption"} color={"secondary"} className={"ml-3.5"}>Should documents be opened full screen or in an inline side dialog</Typography>
53
+ </div>
54
+ }
@@ -6,7 +6,8 @@ import {
6
6
  ConfirmationDialog,
7
7
  DEFAULT_FIELD_CONFIGS,
8
8
  getFieldConfig,
9
- getFieldId, isEmptyObject,
9
+ getFieldId,
10
+ isEmptyObject,
10
11
  isPropertyBuilder,
11
12
  isValidRegExp,
12
13
  mergeDeep,
@@ -47,6 +47,7 @@ export function CollectionEditorImportDataPreview({
47
47
  key: p,
48
48
  disabled: false
49
49
  }))}
50
+ openEntityMode={"side_panel"}
50
51
  properties={properties}
51
52
  enablePopupIcon={false}/>
52
53
 
@@ -51,13 +51,6 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
51
51
 
52
52
  onAnalyticsEvent?: (event: string, params?: object) => void;
53
53
 
54
- components?: {
55
- /**
56
- * Custom component to render the database field
57
- */
58
- DatabaseField?: React.ComponentType<{ databaseId?: string, onDatabaseIdUpdate: (databaseId:string) => void }>;
59
- };
60
-
61
54
  }
62
55
 
63
56
  /**
@@ -82,7 +75,6 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
82
75
  collectionInference,
83
76
  getData,
84
77
  onAnalyticsEvent,
85
- components
86
78
  }: CollectionConfigControllerProps<EC, USER>): FireCMSPlugin<any, any, PersistedCollection> {
87
79
 
88
80
  return {
@@ -100,7 +92,6 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
100
92
  getUser,
101
93
  getData,
102
94
  onAnalyticsEvent,
103
- components
104
95
  }
105
96
  },
106
97
  homePage: {
@@ -11,7 +11,7 @@ import { PersistedCollection } from "../types/persisted_collection";
11
11
  * Function in charge of merging collections defined in code with those stored in the backend.
12
12
  */
13
13
  export const mergeCollections = (baseCollections: EntityCollection[],
14
- backendCollections: PersistedCollection[],
14
+ backendCollections: PersistedCollection[] = [],
15
15
  modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | void
16
16
  ) => {
17
17
 
@@ -19,12 +19,18 @@ export const mergeCollections = (baseCollections: EntityCollection[],
19
19
  makePropertiesEditable(c.properties as Properties);
20
20
  c.subcollections?.forEach(markAsEditable);
21
21
  };
22
- const storedCollections = backendCollections ?? [];
23
- storedCollections.forEach(markAsEditable);
24
22
 
25
- console.debug("Collections specified in code:", baseCollections);
26
- console.debug("Collections stored in the backend", storedCollections);
27
- const result = joinCollectionLists(baseCollections, storedCollections, [], modifyCollection);
28
- console.debug("Collections after joining:", result);
23
+ backendCollections.forEach(markAsEditable);
24
+
25
+ const result = joinCollectionLists(baseCollections, backendCollections, [], modifyCollection);
26
+
27
+ // sort the collections so they are in the same order as the base collections
28
+ result.sort((a, b) => baseCollections.findIndex(c => c.id === a.id) - baseCollections.findIndex(c => c.id === b.id));
29
+ console.debug("Collections result", {
30
+ baseCollections,
31
+ backendCollections,
32
+ result
33
+ });
34
+
29
35
  return result;
30
36
  }