@firecms/collection_editor 3.0.0-canary.5 → 3.0.0-canary.50

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 (53) hide show
  1. package/LICENSE +113 -21
  2. package/dist/ConfigControllerProvider.d.ts +2 -2
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.es.js +1932 -1886
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/index.umd.js +2 -2
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/types/collection_editor_controller.d.ts +1 -1
  9. package/dist/types/persisted_collection.d.ts +1 -1
  10. package/dist/ui/EditorCollectionActionStart.d.ts +2 -0
  11. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +2 -2
  12. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +1 -1
  13. package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +1 -1
  14. package/dist/ui/collection_editor/PropertyTree.d.ts +9 -9
  15. package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +1 -1
  16. package/dist/ui/collection_editor/utils/supported_fields.d.ts +2 -2
  17. package/dist/useCollectionEditorPlugin.d.ts +6 -9
  18. package/dist/utils/collections.d.ts +6 -0
  19. package/package.json +21 -21
  20. package/src/ConfigControllerProvider.tsx +53 -59
  21. package/src/index.ts +1 -0
  22. package/src/types/collection_editor_controller.tsx +1 -1
  23. package/src/types/persisted_collection.ts +1 -1
  24. package/src/ui/EditorCollectionAction.tsx +0 -51
  25. package/src/ui/EditorCollectionActionStart.tsx +87 -0
  26. package/src/ui/HomePageEditorCollectionAction.tsx +5 -5
  27. package/src/ui/MissingReferenceWidget.tsx +2 -1
  28. package/src/ui/NewCollectionButton.tsx +12 -10
  29. package/src/ui/collection_editor/CollectionDetailsForm.tsx +49 -20
  30. package/src/ui/collection_editor/CollectionEditorDialog.tsx +45 -28
  31. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +3 -3
  32. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +25 -22
  33. package/src/ui/collection_editor/EnumForm.tsx +3 -4
  34. package/src/ui/collection_editor/GetCodeDialog.tsx +15 -3
  35. package/src/ui/collection_editor/PropertyEditView.tsx +7 -6
  36. package/src/ui/collection_editor/PropertyTree.tsx +3 -3
  37. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +1 -1
  38. package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +25 -9
  39. package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +9 -7
  40. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +14 -8
  41. package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +7 -8
  42. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +7 -8
  43. package/src/ui/collection_editor/properties/MapPropertyField.tsx +8 -9
  44. package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +3 -4
  45. package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +0 -1
  46. package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +3 -4
  47. package/src/ui/collection_editor/utils/supported_fields.tsx +3 -3
  48. package/src/useCollectionEditorPlugin.tsx +29 -30
  49. package/src/utils/collections.ts +30 -0
  50. package/dist/ui/RootCollectionSuggestions.d.ts +0 -3
  51. package/dist/ui/collection_editor/properties/FieldHelperView.d.ts +0 -4
  52. package/src/ui/RootCollectionSuggestions.tsx +0 -63
  53. package/src/ui/collection_editor/properties/FieldHelperView.tsx +0 -13
@@ -5,7 +5,7 @@ import { Formex, FormexController, getIn, useCreateFormex } from "@firecms/forme
5
5
  import {
6
6
  DEFAULT_FIELD_CONFIGS,
7
7
  DeleteConfirmationDialog,
8
- FieldConfigId,
8
+ PropertyConfigId,
9
9
  getFieldConfig,
10
10
  getFieldId,
11
11
  isPropertyBuilder,
@@ -228,6 +228,7 @@ export const PropertyForm = React.memo(
228
228
  a.includeIdAndName === b.includeIdAndName &&
229
229
  a.autoOpenTypeSelect === b.autoOpenTypeSelect &&
230
230
  a.autoUpdateId === b.autoUpdateId &&
231
+ a.existingPropertyKeys === b.existingPropertyKeys &&
231
232
  a.existingProperty === b.existingProperty
232
233
  );
233
234
 
@@ -367,15 +368,15 @@ function PropertyEditFormFields({
367
368
  }
368
369
  }
369
370
  }
370
- }, [deferredValues, includeIdAndTitle, onPropertyChanged, propertyNamespace]);
371
+ }, [deferredValues, includeIdAndTitle, propertyNamespace]);
371
372
 
372
373
  useEffect(() => {
373
374
  if (values?.id && onError) {
374
375
  onError(values?.id, propertyNamespace, errors);
375
376
  }
376
- }, [errors, onError, propertyNamespace, values?.id]);
377
+ }, [errors, propertyNamespace, values?.id]);
377
378
 
378
- const onWidgetSelectChanged = (newSelectedWidgetId: FieldConfigId) => {
379
+ const onWidgetSelectChanged = (newSelectedWidgetId: PropertyConfigId) => {
379
380
  setSelectedFieldConfigId(newSelectedWidgetId);
380
381
  setValues(updatePropertyFromWidget(values, newSelectedWidgetId, propertyConfigs));
381
382
  // Ugly hack to autofocus the name field
@@ -495,7 +496,7 @@ function PropertyEditFormFields({
495
496
  return <em>Select a property
496
497
  widget</em>;
497
498
  }
498
- const key = value as FieldConfigId;
499
+ const key = value as PropertyConfigId;
499
500
  const propertyConfig = DEFAULT_FIELD_CONFIGS[key] ?? propertyConfigs[key];
500
501
  const baseProperty = propertyConfig.property;
501
502
  const baseFieldConfig = baseProperty && !isPropertyBuilder(baseProperty) ? getFieldConfig(baseProperty, propertyConfigs) : undefined;
@@ -524,7 +525,7 @@ function PropertyEditFormFields({
524
525
  </div>
525
526
  }}
526
527
  onValueChange={(value) => {
527
- onWidgetSelectChanged(value as FieldConfigId);
528
+ onWidgetSelectChanged(value as PropertyConfigId);
528
529
  }}>
529
530
  {displayedWidgets.map(([key, propertyConfig]) => {
530
531
  const baseProperty = propertyConfig.property;
@@ -1,4 +1,4 @@
1
- import React, { useCallback } from "react";
1
+ import React from "react";
2
2
  import equal from "react-fast-compare"
3
3
 
4
4
  import {
@@ -48,7 +48,7 @@ export const PropertyTree = React.memo(
48
48
 
49
49
  const propertiesOrder = propertiesOrderProp ?? Object.keys(properties);
50
50
 
51
- const onDragEnd = useCallback((result: any) => {
51
+ const onDragEnd = (result: any) => {
52
52
  // dropped outside the list
53
53
  if (!result.destination) {
54
54
  return;
@@ -61,7 +61,7 @@ export const PropertyTree = React.memo(
61
61
  newPropertiesOrder.splice(endIndex, 0, removed);
62
62
  if (onPropertyMove)
63
63
  onPropertyMove(newPropertiesOrder, namespace);
64
- }, [namespace, onPropertyMove, propertiesOrder])
64
+ }
65
65
 
66
66
  return (
67
67
  <>
@@ -41,7 +41,7 @@ export function SubcollectionsEditTab({
41
41
  parentCollection?: EntityCollection,
42
42
  configController: CollectionsConfigController;
43
43
  collectionInference?: CollectionInference;
44
- getUser: (uid: string) => User | null;
44
+ getUser?: (uid: string) => User | null;
45
45
  parentCollectionIds?: string[];
46
46
  }) {
47
47
 
@@ -1,21 +1,33 @@
1
- import { convertDataToEntity, getPropertiesMapping, ImportConfig } from "@firecms/data_import_export";
2
- import { EntityCollectionTable, Properties, useSelectionController } from "@firecms/core";
3
- import { useEffect } from "react";
1
+ import { convertDataToEntity, ImportConfig } from "@firecms/data_import_export";
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(() => {
13
- const propertiesMapping = getPropertiesMapping(importConfig.originProperties, properties);
14
- const mappedData = importConfig.importData.map(d => convertDataToEntity(d, importConfig.idColumn, importConfig.headersMapping, properties, propertiesMapping, "TEMP_PATH"));
16
+ const [loading, setLoading] = useState<boolean>(false);
17
+
18
+ async function loadEntities() {
19
+ // const propertiesMapping = getPropertiesMapping(importConfig.originProperties, properties, importConfig.headersMapping);
20
+ const mappedData = importConfig.importData.map(d => convertDataToEntity(d, importConfig.idColumn, importConfig.headersMapping, properties, "TEMP_PATH", importConfig.defaultValues));
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,11 @@ 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 }))}
35
- properties={properties}/>
46
+ displayedColumnIds={propertiesOrder.map(p => ({
47
+ key: p,
48
+ disabled: false
49
+ }))}
50
+ properties={properties}
51
+ enablePopupIcon={false}/>
36
52
 
37
53
  }
@@ -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,18 +143,20 @@ 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
- <DataNewPropertiesMapping headersMapping={importConfig.headersMapping}
149
- idColumn={importConfig.idColumn}
150
- originProperties={importConfig.originProperties}
148
+ <DataNewPropertiesMapping importConfig={importConfig}
151
149
  destinationProperties={values.properties as Properties}
152
- onIdPropertyChanged={(value) => importConfig.setIdColumn(value)}
153
150
  buildPropertyView={({
154
151
  property,
155
152
  propertyKey,
156
- importKey
153
+ importKey,
154
+ isIdColumn
157
155
  }) => {
156
+ if (isIdColumn) {
157
+ return <Typography> This column will be used as ID</Typography>
158
+ }
159
+
158
160
  return <ImportNewPropertyFieldPreview
159
161
  property={property}
160
162
  propertyKey={propertyKey}
@@ -1,12 +1,18 @@
1
- import React, { useCallback, useState } from "react";
1
+ import React, { useState } from "react";
2
2
  import { AddIcon, Button, Paper, Typography } from "@firecms/ui";
3
3
  import { getIn, useFormex } from "@firecms/formex";
4
4
  import { PropertyFormDialog } from "../PropertyEditView";
5
- import { getFullId, idToPropertiesPath, namespaceToPropertiesOrderPath } from "../util";
5
+ import { getFullId, idToPropertiesPath, namespaceToPropertiesOrderPath, namespaceToPropertiesPath } from "../util";
6
6
  import { PropertyTree } from "../PropertyTree";
7
7
  import { ArrayProperty, Property, PropertyConfig } from "@firecms/core";
8
8
 
9
- export function BlockPropertyField({ disabled, getData, allowDataInference, propertyConfigs, collectionEditable }: {
9
+ export function BlockPropertyField({
10
+ disabled,
11
+ getData,
12
+ allowDataInference,
13
+ propertyConfigs,
14
+ collectionEditable
15
+ }: {
10
16
  disabled: boolean;
11
17
  getData?: () => Promise<object[]>;
12
18
  allowDataInference: boolean;
@@ -43,20 +49,20 @@ export function BlockPropertyField({ disabled, getData, allowDataInference, prop
43
49
  const selectedPropertyFullId = selectedPropertyKey ? getFullId(selectedPropertyKey, selectedPropertyNamespace) : undefined;
44
50
  const selectedProperty = selectedPropertyFullId ? getIn(values.oneOf?.properties, selectedPropertyFullId.replaceAll(".", ".properties.")) : undefined;
45
51
 
46
- const deleteProperty = useCallback((propertyKey?: string, namespace?: string) => {
52
+ const deleteProperty = (propertyKey?: string, namespace?: string) => {
47
53
  const fullId = propertyKey ? getFullId(propertyKey, namespace) : undefined;
48
54
  if (!fullId)
49
55
  throw Error("collection editor miss config");
50
56
 
51
57
  setFieldValue(`oneOf.${idToPropertiesPath(fullId)}`, undefined, false);
52
58
  const propertiesOrderPath = `oneOf.${namespaceToPropertiesOrderPath(namespace)}`;
53
- const currentPropertiesOrder: string[] = getIn(values, propertiesOrderPath);
59
+ const currentPropertiesOrder: string[] = getIn(values, propertiesOrderPath) ?? Object.keys(getIn(values, namespaceToPropertiesPath(namespace)));
54
60
  setFieldValue(propertiesOrderPath, currentPropertiesOrder.filter((p) => p !== propertyKey), false);
55
61
 
56
62
  setPropertyDialogOpen(false);
57
63
  setSelectedPropertyKey(undefined);
58
64
  setSelectedPropertyNamespace(undefined);
59
- }, [setFieldValue, values]);
65
+ };
60
66
 
61
67
  const addChildButton = <Button
62
68
  autoFocus
@@ -68,9 +74,9 @@ export function BlockPropertyField({ disabled, getData, allowDataInference, prop
68
74
  Add property to {values.name ?? "this block"}
69
75
  </Button>;
70
76
 
71
- const onPropertyMove = useCallback((propertiesOrder: string[], namespace?: string) => {
77
+ const onPropertyMove = (propertiesOrder: string[], namespace?: string) => {
72
78
  setFieldValue(`oneOf.${namespaceToPropertiesOrderPath(namespace)}`, propertiesOrder, false);
73
- }, []);
79
+ };
74
80
 
75
81
  return (
76
82
  <>
@@ -2,8 +2,7 @@ import { Field, getIn, useFormex } from "@firecms/formex";
2
2
  import { DebouncedTextField } from "@firecms/ui";
3
3
  import { PropertyWithId } from "../PropertyEditView";
4
4
  import React from "react";
5
- import { FieldHelperView } from "./FieldHelperView";
6
- import { toSnakeCase, unslugify } from "@firecms/core";
5
+ import { FieldCaption, toSnakeCase, unslugify } from "@firecms/core";
7
6
 
8
7
  type CommonPropertyFieldsProps = {
9
8
  showErrors: boolean,
@@ -64,9 +63,9 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
64
63
  disabled={disabled}
65
64
  error={Boolean(nameError)}/>
66
65
 
67
- <FieldHelperView error={Boolean(nameError)}>
66
+ <FieldCaption error={Boolean(nameError)}>
68
67
  {nameError}
69
- </FieldHelperView>
68
+ </FieldCaption>
70
69
  </div>
71
70
 
72
71
  <div>
@@ -88,9 +87,9 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
88
87
  required
89
88
  size="small"
90
89
  error={Boolean(idError)}/>
91
- <FieldHelperView error={Boolean(idError)}>
90
+ <FieldCaption error={Boolean(idError)}>
92
91
  {idError}
93
- </FieldHelperView>
92
+ </FieldCaption>
94
93
  </div>
95
94
 
96
95
  <div>
@@ -99,9 +98,9 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
99
98
  label={"Description"}
100
99
  disabled={disabled}
101
100
  error={Boolean(descriptionError)}/>
102
- <FieldHelperView error={Boolean(descriptionError)}>
101
+ <FieldCaption error={Boolean(descriptionError)}>
103
102
  {descriptionError}
104
- </FieldHelperView>
103
+ </FieldCaption>
105
104
  </div>
106
105
 
107
106
  </div>
@@ -1,10 +1,9 @@
1
1
  import React from "react";
2
2
  import { getIn, useFormex } from "@firecms/formex";
3
- import { NumberProperty, StringProperty } from "@firecms/core";
3
+ import { FieldCaption, NumberProperty, StringProperty } from "@firecms/core";
4
4
  import { Select, SelectItem } from "@firecms/ui";
5
5
  import { GeneralPropertyValidation } from "./validation/GeneralPropertyValidation";
6
6
  import { ValidationPanel } from "./validation/ValidationPanel";
7
- import { FieldHelperView } from "./FieldHelperView";
8
7
 
9
8
  export function DateTimePropertyField({ disabled }: {
10
9
  disabled: boolean;
@@ -47,14 +46,14 @@ export function DateTimePropertyField({ disabled }: {
47
46
  <SelectItem value={"date_time"}> Date/Time </SelectItem>
48
47
  <SelectItem value={"date"}> Date </SelectItem>
49
48
  </Select>
50
- <FieldHelperView error={Boolean(modeError)}>
49
+ <FieldCaption error={Boolean(modeError)}>
51
50
  {modeError}
52
- </FieldHelperView>
51
+ </FieldCaption>
53
52
 
54
53
  <Select name={autoValuePath}
55
54
  disabled={disabled}
56
55
  value={autoValueValue ?? ""}
57
- onValueChange={(v) => setFieldValue(autoValuePath, v)}
56
+ onValueChange={(v) => setFieldValue(autoValuePath, v === "none" ? null : v)}
58
57
  renderValue={(v) => {
59
58
  switch (v) {
60
59
  case "on_create":
@@ -67,13 +66,13 @@ export function DateTimePropertyField({ disabled }: {
67
66
  }}
68
67
  error={Boolean(autoValueError)}
69
68
  label={"Automatic value"}>
70
- <SelectItem value={""}> None </SelectItem>
69
+ <SelectItem value={"none"}> None </SelectItem>
71
70
  <SelectItem value={"on_create"}> On create </SelectItem>
72
71
  <SelectItem value={"on_update"}> On any update </SelectItem>
73
72
  </Select>
74
- <FieldHelperView error={Boolean(autoValueError)}>
73
+ <FieldCaption error={Boolean(autoValueError)}>
75
74
  {autoValueError ?? "Update this field automatically when creating or updating the entity"}
76
- </FieldHelperView>
75
+ </FieldCaption>
77
76
 
78
77
  </div>
79
78
 
@@ -1,11 +1,10 @@
1
- import React, { useCallback, useState } from "react";
2
- import { MapProperty, Property, PropertyConfig, } from "@firecms/core";
1
+ import React, { useState } from "react";
2
+ import { FieldCaption, MapProperty, Property, PropertyConfig, } from "@firecms/core";
3
3
  import { AddIcon, BooleanSwitchWithLabel, Button, Paper, Typography } from "@firecms/ui";
4
4
  import { PropertyFormDialog } from "../PropertyEditView";
5
5
  import { getIn, useFormex } from "@firecms/formex";
6
6
  import { PropertyTree } from "../PropertyTree";
7
7
  import { getFullId, idToPropertiesPath, namespaceToPropertiesOrderPath, namespaceToPropertiesPath } from "../util";
8
- import { FieldHelperView } from "./FieldHelperView";
9
8
 
10
9
  export function MapPropertyField({ disabled, getData, allowDataInference, propertyConfigs, collectionEditable }: {
11
10
  disabled: boolean;
@@ -43,7 +42,7 @@ export function MapPropertyField({ disabled, getData, allowDataInference, proper
43
42
  setPropertyDialogOpen(false);
44
43
  };
45
44
 
46
- const deleteProperty = useCallback((propertyKey?: string, namespace?: string) => {
45
+ const deleteProperty = (propertyKey?: string, namespace?: string) => {
47
46
  const fullId = propertyKey ? getFullId(propertyKey, namespace) : undefined;
48
47
  if (!fullId)
49
48
  throw Error("collection editor miss config");
@@ -59,16 +58,16 @@ export function MapPropertyField({ disabled, getData, allowDataInference, proper
59
58
  setPropertyDialogOpen(false);
60
59
  setSelectedPropertyKey(undefined);
61
60
  setSelectedPropertyNamespace(undefined);
62
- }, [setFieldValue, values]);
61
+ };
63
62
 
64
63
  const selectedPropertyFullId = selectedPropertyKey ? getFullId(selectedPropertyKey, selectedPropertyNamespace) : undefined;
65
64
  const selectedProperty = selectedPropertyFullId ? getIn(values.properties, selectedPropertyFullId.replaceAll(".", ".properties.")) : undefined;
66
65
 
67
66
  const empty = !propertiesOrder || propertiesOrder.length < 1;
68
67
 
69
- const onPropertyMove = useCallback((propertiesOrder: string[], namespace?: string) => {
68
+ const onPropertyMove = (propertiesOrder: string[], namespace?: string) => {
70
69
  setFieldValue(namespaceToPropertiesOrderPath(namespace), propertiesOrder, false);
71
- }, []);
70
+ };
72
71
 
73
72
  return (
74
73
  <>
@@ -113,9 +112,9 @@ export function MapPropertyField({ disabled, getData, allowDataInference, proper
113
112
  onValueChange={(v) => setFieldValue("spreadChildren", v)}
114
113
  value={values.spreadChildren ?? false}
115
114
  />
116
- <FieldHelperView>
115
+ <FieldCaption>
117
116
  Set this flag to true if you want to display the children of this group as individual columns.
118
- </FieldHelperView>
117
+ </FieldCaption>
119
118
  </div>
120
119
 
121
120
  <PropertyFormDialog
@@ -1,8 +1,7 @@
1
1
  import React from "react";
2
2
  import { Field, getIn, useFormex } from "@firecms/formex";
3
- import { IconForView, NumberProperty, StringProperty, useNavigationController } from "@firecms/core";
3
+ import { FieldCaption, IconForView, NumberProperty, StringProperty, useNavigationController } from "@firecms/core";
4
4
  import { CircularProgress, Select, SelectGroup, SelectItem, Typography, } from "@firecms/ui";
5
- import { FieldHelperView } from "./FieldHelperView";
6
5
 
7
6
  export function ReferencePropertyField({
8
7
  existing,
@@ -152,10 +151,10 @@ export function CollectionsSelect({
152
151
 
153
152
  </Select>
154
153
 
155
- <FieldHelperView>
154
+ <FieldCaption>
156
155
  You can only edit the reference collection upon field
157
156
  creation.
158
- </FieldHelperView>
157
+ </FieldCaption>
159
158
  </>
160
159
  );
161
160
  }
@@ -39,7 +39,6 @@ export function RepeatPropertyField({
39
39
 
40
40
  const onPropertyChanged = ({ id, property, namespace }:
41
41
  { id?: string, property: Property, namespace?: string }) => {
42
- console.log("onPropertyChanged", id, property, namespace);
43
42
  setFieldValue("of", property);
44
43
  };
45
44
 
@@ -1,10 +1,9 @@
1
1
  import React from "react";
2
2
 
3
3
  import { Field, FormexFieldProps, getIn, useFormex } from "@firecms/formex";
4
- import { serializeRegExp } from "@firecms/core";
4
+ import { FieldCaption, serializeRegExp } from "@firecms/core";
5
5
  import { DebouncedTextField, } from "@firecms/ui";
6
6
  import { GeneralPropertyValidation } from "./GeneralPropertyValidation";
7
- import { FieldHelperView } from "../FieldHelperView";
8
7
  import { SwitchControl } from "../../SwitchControl";
9
8
 
10
9
  export function StringPropertyValidation({
@@ -140,9 +139,9 @@ export function StringPropertyValidation({
140
139
  disabled={disabled}
141
140
  value={matchesStringValue}
142
141
  error={Boolean(matchesError)}/>
143
- <FieldHelperView error={Boolean(matchesError)}>
142
+ <FieldCaption error={Boolean(matchesError)}>
144
143
  {matchesError ? "Not a valid regexp" : "e.g. /^\\d+$/ for digits only"}
145
- </FieldHelperView>
144
+ </FieldCaption>
146
145
  </div>}
147
146
 
148
147
  </div>
@@ -1,6 +1,6 @@
1
- import { DEFAULT_FIELD_CONFIGS, FieldConfigId, PropertyConfig } from "@firecms/core";
1
+ import { DEFAULT_FIELD_CONFIGS, PropertyConfigId, PropertyConfig } from "@firecms/core";
2
2
 
3
- export const supportedFieldsIds: FieldConfigId[] = [
3
+ export const supportedFieldsIds: PropertyConfigId[] = [
4
4
  "text_field",
5
5
  "multiline",
6
6
  "markdown",
@@ -24,6 +24,6 @@ export const supportedFieldsIds: FieldConfigId[] = [
24
24
  ];
25
25
 
26
26
  export const supportedFields: Record<string, PropertyConfig> = Object.entries(DEFAULT_FIELD_CONFIGS)
27
- .filter(([id]) => supportedFieldsIds.includes(id as FieldConfigId))
27
+ .filter(([id]) => supportedFieldsIds.includes(id as PropertyConfigId))
28
28
  .map(([id, config]) => ({ [id]: config }))
29
29
  .reduce((a, b) => ({ ...a, ...b }), {});
@@ -4,16 +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";
15
+ import { EditorCollectionActionStart } from "./ui/EditorCollectionActionStart";
16
+ import { NewCollectionCard } from "./ui/NewCollectionCard";
17
17
 
18
18
  export interface CollectionConfigControllerProps<EC extends PersistedCollection = PersistedCollection, UserType extends User = User> {
19
19
 
@@ -32,7 +32,7 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
32
32
  * names when creating collections.
33
33
  * e.g. ["admin"]
34
34
  */
35
- reservedGroups: string[];
35
+ reservedGroups?: string[];
36
36
 
37
37
  extraView?: {
38
38
  View: React.ComponentType<{
@@ -41,18 +41,16 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
41
41
  icon: React.ReactNode
42
42
  };
43
43
 
44
- pathSuggestions?: (path: string) => Promise<string[]>;
44
+ getPathSuggestions?: (path?: string) => Promise<string[]>;
45
45
 
46
46
  collectionInference?: CollectionInference;
47
47
 
48
48
  getData?: (path: string, parentPaths: string[]) => Promise<object[]>;
49
49
 
50
- getUser: (uid: string) => UserType | null;
50
+ getUser?: (uid: string) => UserType | null;
51
51
 
52
52
  onAnalyticsEvent?: (event: string, params?: object) => void;
53
53
 
54
- introMode?: "new_project" | "existing_project";
55
-
56
54
  }
57
55
 
58
56
  /**
@@ -62,18 +60,17 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
62
60
  * @param configPermissions
63
61
  * @param reservedGroups
64
62
  * @param extraView
65
- * @param pathSuggestions
63
+ * @param getPathsSuggestions
66
64
  * @param getUser
67
65
  * @param collectionInference
68
66
  */
69
67
  export function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, UserType extends User = User>
70
68
  ({
71
69
  collectionConfigController,
72
- introMode,
73
70
  configPermissions,
74
71
  reservedGroups,
75
72
  extraView,
76
- pathSuggestions,
73
+ getPathSuggestions,
77
74
  getUser,
78
75
  collectionInference,
79
76
  getData,
@@ -81,11 +78,8 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
81
78
  }: CollectionConfigControllerProps<EC, UserType>): FireCMSPlugin<any, any, PersistedCollection> {
82
79
 
83
80
  return {
84
- name: "Collection Editor",
81
+ key: "collection_editor",
85
82
  loading: collectionConfigController.loading,
86
- collections: {
87
- CollectionActions: EditorCollectionAction
88
- },
89
83
  provider: {
90
84
  Component: ConfigControllerProvider,
91
85
  props: {
@@ -94,7 +88,7 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
94
88
  collectionInference,
95
89
  reservedGroups,
96
90
  extraView,
97
- pathSuggestions,
91
+ getPathSuggestions,
98
92
  getUser,
99
93
  getData,
100
94
  onAnalyticsEvent
@@ -102,21 +96,21 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
102
96
  },
103
97
  homePage: {
104
98
  additionalActions: <NewCollectionButton/>,
105
- additionalChildrenStart: introMode ? <IntroWidget introMode={introMode}/> : undefined,
106
- additionalChildrenEnd: <RootCollectionSuggestions introMode={introMode}/>,
99
+ additionalChildrenStart: <IntroWidget/>,
100
+ // additionalChildrenEnd: <RootCollectionSuggestions introMode={introMode}/>,
107
101
  CollectionActions: HomePageEditorCollectionAction,
108
- AdditionalCards: introMode ? undefined : NewCollectionCard,
102
+ AdditionalCards: NewCollectionCard,
109
103
  },
110
104
  collectionView: {
105
+ CollectionActionsStart: EditorCollectionActionStart,
106
+ CollectionActions: EditorCollectionAction,
111
107
  HeaderAction: CollectionViewHeaderAction,
112
108
  AddColumnComponent: PropertyAddColumnComponent
113
109
  }
114
110
  };
115
111
  }
116
112
 
117
- export function IntroWidget({ introMode }: {
118
- introMode?: "new_project" | "existing_project";
119
- }) {
113
+ export function IntroWidget({}: {}) {
120
114
 
121
115
  const navigation = useNavigationController();
122
116
  if (!navigation.topLevelNavigation)
@@ -131,17 +125,19 @@ export function IntroWidget({ introMode }: {
131
125
  }).createCollections
132
126
  : true;
133
127
 
128
+ if (!navigation.initialised || navigation.collections === undefined || (navigation.collections ?? []).length > 0) {
129
+ return null;
130
+ }
131
+
134
132
  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}>
133
+ <Paper
134
+ className={"my-4 px-4 py-6 flex flex-col bg-white dark:bg-slate-800 gap-2"}>
135
+ <Typography variant={"subtitle2"} className={"uppercase"}>No collections found</Typography>
136
+ <Typography>
139
137
  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.
138
+ database data, import from files, or use our templates.
142
139
  </Typography>
143
140
  {canCreateCollections && <Button
144
- className={"mt-4"}
145
141
  onClick={collectionEditorController && canCreateCollections
146
142
  ? () => collectionEditorController.createCollection({
147
143
  parentCollectionIds: [],
@@ -151,6 +147,9 @@ export function IntroWidget({ introMode }: {
151
147
  : undefined}>
152
148
  <AddIcon/>Create your first collection
153
149
  </Button>}
154
- </div>
150
+ <Typography variant={"caption"} color={"secondary"}>
151
+ You can also define collections programmatically.
152
+ </Typography>
153
+ </Paper>
155
154
  );
156
155
  }
@@ -0,0 +1,30 @@
1
+ import {
2
+ EntityCollection,
3
+ joinCollectionLists,
4
+ makePropertiesEditable,
5
+ ModifyCollectionProps,
6
+ Properties
7
+ } from "@firecms/core";
8
+ import { PersistedCollection } from "../types/persisted_collection";
9
+
10
+ /**
11
+ * Function in charge of merging collections defined in code with those stored in the backend.
12
+ */
13
+ export const mergeCollections = (baseCollections: EntityCollection[],
14
+ backendCollections: PersistedCollection[],
15
+ modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | void
16
+ ) => {
17
+
18
+ const markAsEditable = (c: PersistedCollection) => {
19
+ makePropertiesEditable(c.properties as Properties);
20
+ c.subcollections?.forEach(markAsEditable);
21
+ };
22
+ const storedCollections = backendCollections ?? [];
23
+ storedCollections.forEach(markAsEditable);
24
+
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);
29
+ return result;
30
+ }