@firecms/collection_editor 3.0.0-alpha.5 → 3.0.0-alpha.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.
- package/dist/ConfigControllerProvider.d.ts +36 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.es.js +6998 -0
- package/dist/index.es.js.map +1 -0
- package/dist/index.umd.js +4 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/types/collection_editor_controller.d.ts +35 -0
- package/dist/types/collection_inference.d.ts +2 -0
- package/dist/types/config_controller.d.ts +41 -0
- package/dist/types/config_permissions.d.ts +19 -0
- package/dist/types/persisted_collection.d.ts +6 -0
- package/dist/ui/CollectionViewHeaderAction.d.ts +10 -0
- package/dist/ui/EditorCollectionAction.d.ts +2 -0
- package/dist/ui/HomePageEditorCollectionAction.d.ts +2 -0
- package/dist/ui/MissingReferenceWidget.d.ts +3 -0
- package/dist/ui/NewCollectionCard.d.ts +2 -0
- package/dist/ui/PropertyAddColumnComponent.d.ts +6 -0
- package/dist/ui/RootCollectionSuggestions.d.ts +1 -0
- package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +9 -0
- package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +38 -0
- package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +15 -0
- package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +20 -0
- package/dist/ui/collection_editor/CollectionYupValidation.d.ts +14 -0
- package/dist/ui/collection_editor/EntityCustomViewsSelectDialog.d.ts +4 -0
- package/dist/ui/collection_editor/EnumForm.d.ts +13 -0
- package/dist/ui/collection_editor/GetCodeDialog.d.ts +5 -0
- package/dist/ui/collection_editor/PropertyEditView.d.ts +40 -0
- package/dist/ui/collection_editor/PropertyFieldPreview.d.ts +15 -0
- package/dist/ui/collection_editor/PropertySelectItem.d.ts +8 -0
- package/dist/ui/collection_editor/PropertyTree.d.ts +32 -0
- package/dist/ui/collection_editor/SelectIcons.d.ts +6 -0
- package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +12 -0
- package/dist/ui/collection_editor/UnsavedChangesDialog.d.ts +9 -0
- package/dist/ui/collection_editor/import/CollectionEditorImportDataPreview.d.ts +7 -0
- package/dist/ui/collection_editor/import/CollectionEditorImportMapping.d.ts +7 -0
- package/dist/ui/collection_editor/import/clean_import_data.d.ts +7 -0
- package/dist/ui/collection_editor/properties/BlockPropertyField.d.ts +8 -0
- package/dist/ui/collection_editor/properties/BooleanPropertyField.d.ts +3 -0
- package/dist/ui/collection_editor/properties/CommonPropertyFields.d.ts +10 -0
- package/dist/ui/collection_editor/properties/DateTimePropertyField.d.ts +3 -0
- package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +8 -0
- package/dist/ui/collection_editor/properties/FieldHelperView.d.ts +4 -0
- package/dist/ui/collection_editor/properties/KeyValuePropertyField.d.ts +3 -0
- package/dist/ui/collection_editor/properties/MapPropertyField.d.ts +8 -0
- package/dist/ui/collection_editor/properties/NumberPropertyField.d.ts +3 -0
- package/dist/ui/collection_editor/properties/ReferencePropertyField.d.ts +13 -0
- package/dist/ui/collection_editor/properties/RepeatPropertyField.d.ts +10 -0
- package/dist/ui/collection_editor/properties/StoragePropertyField.d.ts +5 -0
- package/dist/ui/collection_editor/properties/StringPropertyField.d.ts +5 -0
- package/dist/ui/collection_editor/properties/UrlPropertyField.d.ts +4 -0
- package/dist/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.d.ts +3 -0
- package/dist/ui/collection_editor/properties/validation/ArrayPropertyValidation.d.ts +5 -0
- package/dist/ui/collection_editor/properties/validation/GeneralPropertyValidation.d.ts +4 -0
- package/dist/ui/collection_editor/properties/validation/NumberPropertyValidation.d.ts +3 -0
- package/dist/ui/collection_editor/properties/validation/StringPropertyValidation.d.ts +11 -0
- package/dist/ui/collection_editor/properties/validation/ValidationPanel.d.ts +2 -0
- package/dist/ui/collection_editor/templates/blog_template.d.ts +2 -0
- package/dist/ui/collection_editor/templates/products_template.d.ts +2 -0
- package/dist/ui/collection_editor/templates/users_template.d.ts +2 -0
- package/dist/ui/collection_editor/util.d.ts +4 -0
- package/dist/ui/collection_editor/utils/strings.d.ts +1 -0
- package/dist/ui/collection_editor/utils/supported_fields.d.ts +3 -0
- package/dist/ui/collection_editor/utils/update_property_for_widget.d.ts +2 -0
- package/dist/ui/collection_editor/utils/useTraceUpdate.d.ts +1 -0
- package/dist/useCollectionEditorController.d.ts +6 -0
- package/dist/useCollectionEditorPlugin.d.ts +45 -0
- package/dist/useCollectionsConfigController.d.ts +6 -0
- package/dist/utils/arrays.d.ts +1 -0
- package/dist/utils/entities.d.ts +3 -0
- package/dist/utils/icons.d.ts +1 -0
- package/dist/utils/synonyms.d.ts +1951 -0
- package/package.json +26 -23
- package/src/ConfigControllerProvider.tsx +321 -0
- package/src/index.ts +35 -0
- package/src/types/collection_editor_controller.tsx +42 -0
- package/src/types/collection_inference.ts +3 -0
- package/src/types/config_controller.tsx +50 -0
- package/src/types/config_permissions.ts +20 -0
- package/src/types/persisted_collection.ts +9 -0
- package/src/ui/CollectionViewHeaderAction.tsx +42 -0
- package/src/ui/EditorCollectionAction.tsx +95 -0
- package/src/ui/HomePageEditorCollectionAction.tsx +88 -0
- package/src/ui/MissingReferenceWidget.tsx +34 -0
- package/src/ui/NewCollectionCard.tsx +46 -0
- package/src/ui/PropertyAddColumnComponent.tsx +41 -0
- package/src/ui/RootCollectionSuggestions.tsx +62 -0
- package/src/ui/collection_editor/CollectionDetailsForm.tsx +353 -0
- package/src/ui/collection_editor/CollectionEditorDialog.tsx +744 -0
- package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +212 -0
- package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +480 -0
- package/src/ui/collection_editor/CollectionYupValidation.tsx +7 -0
- package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +36 -0
- package/src/ui/collection_editor/EnumForm.tsx +356 -0
- package/src/ui/collection_editor/GetCodeDialog.tsx +118 -0
- package/src/ui/collection_editor/PropertyEditView.tsx +564 -0
- package/src/ui/collection_editor/PropertyFieldPreview.tsx +201 -0
- package/src/ui/collection_editor/PropertySelectItem.tsx +31 -0
- package/src/ui/collection_editor/PropertyTree.tsx +238 -0
- package/src/ui/collection_editor/SelectIcons.tsx +72 -0
- package/src/ui/collection_editor/SubcollectionsEditTab.tsx +252 -0
- package/src/ui/collection_editor/UnsavedChangesDialog.tsx +47 -0
- package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +37 -0
- package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +275 -0
- package/src/ui/collection_editor/import/clean_import_data.ts +53 -0
- package/src/ui/collection_editor/properties/BlockPropertyField.tsx +134 -0
- package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +36 -0
- package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +111 -0
- package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +86 -0
- package/src/ui/collection_editor/properties/EnumPropertyField.tsx +116 -0
- package/src/ui/collection_editor/properties/FieldHelperView.tsx +13 -0
- package/src/ui/collection_editor/properties/KeyValuePropertyField.tsx +20 -0
- package/src/ui/collection_editor/properties/MapPropertyField.tsx +157 -0
- package/src/ui/collection_editor/properties/NumberPropertyField.tsx +38 -0
- package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +184 -0
- package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +107 -0
- package/src/ui/collection_editor/properties/StoragePropertyField.tsx +194 -0
- package/src/ui/collection_editor/properties/StringPropertyField.tsx +79 -0
- package/src/ui/collection_editor/properties/UrlPropertyField.tsx +89 -0
- package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +36 -0
- package/src/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +50 -0
- package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +49 -0
- package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +99 -0
- package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +131 -0
- package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +28 -0
- package/src/ui/collection_editor/templates/blog_template.ts +115 -0
- package/src/ui/collection_editor/templates/products_template.ts +88 -0
- package/src/ui/collection_editor/templates/users_template.ts +34 -0
- package/src/ui/collection_editor/util.ts +21 -0
- package/src/ui/collection_editor/utils/strings.ts +8 -0
- package/src/ui/collection_editor/utils/supported_fields.tsx +28 -0
- package/src/ui/collection_editor/utils/update_property_for_widget.ts +271 -0
- package/src/ui/collection_editor/utils/useTraceUpdate.tsx +23 -0
- package/src/useCollectionEditorController.tsx +9 -0
- package/src/useCollectionEditorPlugin.tsx +128 -0
- package/src/useCollectionsConfigController.tsx +9 -0
- package/src/utils/arrays.ts +3 -0
- package/src/utils/entities.ts +38 -0
- package/src/utils/icons.ts +17 -0
- package/src/utils/synonyms.ts +1952 -0
- package/src/vite-env.d.ts +1 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { EntityCollection, makePropertiesEditable } from "@firecms/core";
|
|
2
|
+
|
|
3
|
+
export const productsCollectionTemplate: EntityCollection = {
|
|
4
|
+
id: "products",
|
|
5
|
+
path: "products",
|
|
6
|
+
name: "Products",
|
|
7
|
+
singularName: "Product",
|
|
8
|
+
icon: "shopping_cart",
|
|
9
|
+
description: "List of the products currently sold in your shop",
|
|
10
|
+
properties: makePropertiesEditable({
|
|
11
|
+
name: {
|
|
12
|
+
dataType: "string",
|
|
13
|
+
name: "Name",
|
|
14
|
+
description: "Name of this product",
|
|
15
|
+
validation: {
|
|
16
|
+
required: true
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
brand: {
|
|
20
|
+
dataType: "string",
|
|
21
|
+
name: "Brand",
|
|
22
|
+
validation: {
|
|
23
|
+
required: true
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
description: {
|
|
27
|
+
dataType: "string",
|
|
28
|
+
name: "Description",
|
|
29
|
+
description: "Description of this product, supports markdown",
|
|
30
|
+
markdown: true
|
|
31
|
+
},
|
|
32
|
+
main_image: {
|
|
33
|
+
dataType: "string",
|
|
34
|
+
name: "Image",
|
|
35
|
+
storage: {
|
|
36
|
+
storagePath: "images",
|
|
37
|
+
acceptedFiles: ["image/*"],
|
|
38
|
+
},
|
|
39
|
+
description: "Upload field for images"
|
|
40
|
+
},
|
|
41
|
+
available: {
|
|
42
|
+
dataType: "boolean",
|
|
43
|
+
name: "Available",
|
|
44
|
+
columnWidth: 100,
|
|
45
|
+
description: "Is this product available in the website"
|
|
46
|
+
},
|
|
47
|
+
price: {
|
|
48
|
+
dataType: "number",
|
|
49
|
+
name: "Price",
|
|
50
|
+
validation: {
|
|
51
|
+
requiredMessage: "You must set a positive price",
|
|
52
|
+
min: 0
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
images: {
|
|
56
|
+
dataType: "array",
|
|
57
|
+
name: "Images",
|
|
58
|
+
hideFromCollection: true,
|
|
59
|
+
of: {
|
|
60
|
+
dataType: "string",
|
|
61
|
+
storage: {
|
|
62
|
+
storagePath: "images",
|
|
63
|
+
acceptedFiles: ["image/*"]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
related_products: {
|
|
68
|
+
dataType: "array",
|
|
69
|
+
name: "Related products",
|
|
70
|
+
description: "Products related to this one",
|
|
71
|
+
of: {
|
|
72
|
+
dataType: "reference",
|
|
73
|
+
path: "products"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
metadata: {
|
|
77
|
+
name: "Metadata",
|
|
78
|
+
description: "This is an example of a map property",
|
|
79
|
+
dataType: "map",
|
|
80
|
+
keyValue: true
|
|
81
|
+
},
|
|
82
|
+
added_on: {
|
|
83
|
+
dataType: "date",
|
|
84
|
+
name: "Added on",
|
|
85
|
+
autoValue: "on_create"
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { EntityCollection, makePropertiesEditable } from "@firecms/core";
|
|
2
|
+
|
|
3
|
+
export const usersCollectionTemplate: EntityCollection = {
|
|
4
|
+
id: "users",
|
|
5
|
+
path: "users",
|
|
6
|
+
name: "Users",
|
|
7
|
+
singularName: "User",
|
|
8
|
+
description: "Registered users in the app/web",
|
|
9
|
+
icon: "person",
|
|
10
|
+
properties: makePropertiesEditable({
|
|
11
|
+
displayName: {
|
|
12
|
+
name: "Display name",
|
|
13
|
+
dataType: "string"
|
|
14
|
+
},
|
|
15
|
+
email: {
|
|
16
|
+
name: "Email",
|
|
17
|
+
dataType: "string",
|
|
18
|
+
email: true
|
|
19
|
+
},
|
|
20
|
+
emailVerified: {
|
|
21
|
+
name: "Email verified",
|
|
22
|
+
dataType: "boolean"
|
|
23
|
+
},
|
|
24
|
+
phone: {
|
|
25
|
+
name: "Phone",
|
|
26
|
+
dataType: "string"
|
|
27
|
+
},
|
|
28
|
+
photoURL: {
|
|
29
|
+
name: "Photo URL",
|
|
30
|
+
dataType: "string",
|
|
31
|
+
url: "image"
|
|
32
|
+
}
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function idToPropertiesPath(id: string): string {
|
|
2
|
+
return "properties." + id.replaceAll(".", ".properties.");
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function namespaceToPropertiesPath(namespace?: string): string {
|
|
6
|
+
return namespace
|
|
7
|
+
? "properties." + namespace.replaceAll(".", ".properties.") + ".properties"
|
|
8
|
+
: "properties";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function namespaceToPropertiesOrderPath(namespace?: string): string {
|
|
12
|
+
return namespace
|
|
13
|
+
? "properties." + namespace.replaceAll(".", ".properties.") + ".propertiesOrder"
|
|
14
|
+
: "propertiesOrder";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getFullId(propertyKey: string, propertyNamespace?: string): string {
|
|
18
|
+
return propertyNamespace
|
|
19
|
+
? `${propertyNamespace}.${propertyKey}`
|
|
20
|
+
: propertyKey;
|
|
21
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DEFAULT_FIELD_CONFIGS, FieldConfigId } from "@firecms/core";
|
|
2
|
+
|
|
3
|
+
export const supportedFieldsIds: FieldConfigId[] = [
|
|
4
|
+
"text_field",
|
|
5
|
+
"multiline",
|
|
6
|
+
"markdown",
|
|
7
|
+
"url",
|
|
8
|
+
"email",
|
|
9
|
+
"select",
|
|
10
|
+
"multi_select",
|
|
11
|
+
"number_input",
|
|
12
|
+
"number_select",
|
|
13
|
+
"multi_number_select",
|
|
14
|
+
"file_upload",
|
|
15
|
+
"multi_file_upload",
|
|
16
|
+
"group",
|
|
17
|
+
"key_value",
|
|
18
|
+
"reference",
|
|
19
|
+
"multi_references",
|
|
20
|
+
"switch",
|
|
21
|
+
"date_time",
|
|
22
|
+
"repeat",
|
|
23
|
+
"block"
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export const supportedFields = Object.entries(DEFAULT_FIELD_CONFIGS).filter(([id]) =>
|
|
27
|
+
supportedFieldsIds.includes(id as FieldConfigId)
|
|
28
|
+
);
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ArrayProperty,
|
|
3
|
+
BooleanProperty,
|
|
4
|
+
DateProperty,
|
|
5
|
+
MapProperty,
|
|
6
|
+
mergeDeep,
|
|
7
|
+
NumberProperty,
|
|
8
|
+
Property,
|
|
9
|
+
PropertyConfig,
|
|
10
|
+
StringProperty
|
|
11
|
+
} from "@firecms/core";
|
|
12
|
+
|
|
13
|
+
export function updatePropertyFromWidget(propertyData: any,
|
|
14
|
+
selectedWidgetId: string | undefined,
|
|
15
|
+
propertyConfigs: Record<string, PropertyConfig>): Property {
|
|
16
|
+
|
|
17
|
+
let updatedProperty;
|
|
18
|
+
if (selectedWidgetId === "text_field") {
|
|
19
|
+
updatedProperty = mergeDeep(
|
|
20
|
+
propertyData,
|
|
21
|
+
{
|
|
22
|
+
dataType: "string",
|
|
23
|
+
propertyConfig: "text_field",
|
|
24
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
25
|
+
storage: undefined,
|
|
26
|
+
multiline: undefined,
|
|
27
|
+
markdown: undefined,
|
|
28
|
+
email: undefined,
|
|
29
|
+
url: undefined,
|
|
30
|
+
enumValues: undefined
|
|
31
|
+
} satisfies StringProperty
|
|
32
|
+
);
|
|
33
|
+
} else if (selectedWidgetId === "multiline") {
|
|
34
|
+
updatedProperty = mergeDeep(
|
|
35
|
+
propertyData,
|
|
36
|
+
{
|
|
37
|
+
dataType: "string",
|
|
38
|
+
propertyConfig: "multiline",
|
|
39
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
40
|
+
multiline: true,
|
|
41
|
+
storage: undefined,
|
|
42
|
+
markdown: undefined,
|
|
43
|
+
email: undefined,
|
|
44
|
+
url: undefined,
|
|
45
|
+
enumValues: undefined
|
|
46
|
+
} satisfies StringProperty
|
|
47
|
+
);
|
|
48
|
+
} else if (selectedWidgetId === "markdown") {
|
|
49
|
+
updatedProperty = mergeDeep(
|
|
50
|
+
propertyData,
|
|
51
|
+
{
|
|
52
|
+
dataType: "string",
|
|
53
|
+
propertyConfig: "markdown",
|
|
54
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
55
|
+
storage: undefined,
|
|
56
|
+
multiline: undefined,
|
|
57
|
+
markdown: true,
|
|
58
|
+
email: undefined,
|
|
59
|
+
url: undefined
|
|
60
|
+
} satisfies StringProperty
|
|
61
|
+
);
|
|
62
|
+
} else if (selectedWidgetId === "url") {
|
|
63
|
+
updatedProperty = mergeDeep(
|
|
64
|
+
propertyData,
|
|
65
|
+
{
|
|
66
|
+
dataType: "string",
|
|
67
|
+
propertyConfig: "url",
|
|
68
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
69
|
+
storage: undefined,
|
|
70
|
+
multiline: undefined,
|
|
71
|
+
markdown: undefined,
|
|
72
|
+
email: undefined,
|
|
73
|
+
url: true,
|
|
74
|
+
enumValues: undefined
|
|
75
|
+
} satisfies StringProperty
|
|
76
|
+
);
|
|
77
|
+
} else if (selectedWidgetId === "email") {
|
|
78
|
+
updatedProperty = mergeDeep(
|
|
79
|
+
propertyData,
|
|
80
|
+
{
|
|
81
|
+
dataType: "string",
|
|
82
|
+
propertyConfig: "email",
|
|
83
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
84
|
+
storage: undefined,
|
|
85
|
+
multiline: undefined,
|
|
86
|
+
markdown: undefined,
|
|
87
|
+
email: true,
|
|
88
|
+
url: undefined,
|
|
89
|
+
enumValues: undefined
|
|
90
|
+
} satisfies StringProperty
|
|
91
|
+
);
|
|
92
|
+
} else if (selectedWidgetId === "select") {
|
|
93
|
+
updatedProperty = mergeDeep(
|
|
94
|
+
propertyData,
|
|
95
|
+
{
|
|
96
|
+
dataType: "string",
|
|
97
|
+
propertyConfig: "select",
|
|
98
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
99
|
+
storage: undefined,
|
|
100
|
+
multiline: undefined,
|
|
101
|
+
markdown: undefined,
|
|
102
|
+
email: undefined,
|
|
103
|
+
url: undefined,
|
|
104
|
+
enumValues: propertyData.enumValues ?? []
|
|
105
|
+
} satisfies StringProperty
|
|
106
|
+
);
|
|
107
|
+
} else if (selectedWidgetId === "multi_select") {
|
|
108
|
+
updatedProperty = mergeDeep(
|
|
109
|
+
propertyData,
|
|
110
|
+
{
|
|
111
|
+
dataType: "array",
|
|
112
|
+
propertyConfig: "multi_select",
|
|
113
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
114
|
+
of: {
|
|
115
|
+
dataType: "string",
|
|
116
|
+
enumValues: propertyData.of?.enumValues ?? []
|
|
117
|
+
}
|
|
118
|
+
} satisfies ArrayProperty
|
|
119
|
+
);
|
|
120
|
+
} else if (selectedWidgetId === "number_input") {
|
|
121
|
+
updatedProperty = mergeDeep(
|
|
122
|
+
propertyData,
|
|
123
|
+
{
|
|
124
|
+
dataType: "number",
|
|
125
|
+
propertyConfig: "number_input",
|
|
126
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
127
|
+
enumValues: undefined
|
|
128
|
+
} satisfies NumberProperty
|
|
129
|
+
);
|
|
130
|
+
} else if (selectedWidgetId === "number_select") {
|
|
131
|
+
updatedProperty = mergeDeep(
|
|
132
|
+
propertyData,
|
|
133
|
+
{
|
|
134
|
+
dataType: "number",
|
|
135
|
+
propertyConfig: "number_select",
|
|
136
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
137
|
+
enumValues: propertyData.enumValues ?? []
|
|
138
|
+
} satisfies NumberProperty
|
|
139
|
+
);
|
|
140
|
+
} else if (selectedWidgetId === "multi_number_select") {
|
|
141
|
+
updatedProperty = mergeDeep(
|
|
142
|
+
propertyData,
|
|
143
|
+
{
|
|
144
|
+
dataType: "array",
|
|
145
|
+
propertyConfig: "multi_number_select",
|
|
146
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
147
|
+
of: {
|
|
148
|
+
dataType: "number",
|
|
149
|
+
enumValues: propertyData.of?.enumValues ?? []
|
|
150
|
+
}
|
|
151
|
+
} satisfies ArrayProperty
|
|
152
|
+
);
|
|
153
|
+
} else if (selectedWidgetId === "file_upload") {
|
|
154
|
+
updatedProperty = mergeDeep(
|
|
155
|
+
propertyData,
|
|
156
|
+
{
|
|
157
|
+
dataType: "string",
|
|
158
|
+
propertyConfig: "file_upload",
|
|
159
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
160
|
+
storage: {
|
|
161
|
+
storagePath: "/"
|
|
162
|
+
}
|
|
163
|
+
} satisfies StringProperty
|
|
164
|
+
);
|
|
165
|
+
} else if (selectedWidgetId === "multi_file_upload") {
|
|
166
|
+
updatedProperty = mergeDeep(
|
|
167
|
+
propertyData,
|
|
168
|
+
{
|
|
169
|
+
dataType: "array",
|
|
170
|
+
propertyConfig: "multi_file_upload",
|
|
171
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
172
|
+
of: {
|
|
173
|
+
dataType: "string",
|
|
174
|
+
storage: propertyData.of?.storage ?? {
|
|
175
|
+
storagePath: "/"
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
} satisfies ArrayProperty
|
|
179
|
+
);
|
|
180
|
+
} else if (selectedWidgetId === "group") {
|
|
181
|
+
updatedProperty = mergeDeep(
|
|
182
|
+
propertyData,
|
|
183
|
+
{
|
|
184
|
+
dataType: "map",
|
|
185
|
+
propertyConfig: "group",
|
|
186
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
187
|
+
keyValue: false,
|
|
188
|
+
properties: propertyData.properties ?? {}
|
|
189
|
+
} satisfies MapProperty
|
|
190
|
+
);
|
|
191
|
+
} else if (selectedWidgetId === "key_value") {
|
|
192
|
+
updatedProperty = mergeDeep(
|
|
193
|
+
propertyData,
|
|
194
|
+
{
|
|
195
|
+
dataType: "map",
|
|
196
|
+
propertyConfig: "key_value",
|
|
197
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
198
|
+
keyValue: true,
|
|
199
|
+
properties: undefined
|
|
200
|
+
} satisfies MapProperty
|
|
201
|
+
);
|
|
202
|
+
} else if (selectedWidgetId === "reference") {
|
|
203
|
+
updatedProperty = mergeDeep(
|
|
204
|
+
propertyData,
|
|
205
|
+
{
|
|
206
|
+
dataType: "reference",
|
|
207
|
+
propertyConfig: "reference",
|
|
208
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true
|
|
209
|
+
} satisfies Property
|
|
210
|
+
);
|
|
211
|
+
} else if (selectedWidgetId === "multi_references") {
|
|
212
|
+
updatedProperty = mergeDeep(
|
|
213
|
+
propertyData,
|
|
214
|
+
{
|
|
215
|
+
dataType: "array",
|
|
216
|
+
propertyConfig: "multi_references",
|
|
217
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
218
|
+
of: {
|
|
219
|
+
dataType: "reference"
|
|
220
|
+
}
|
|
221
|
+
} satisfies ArrayProperty
|
|
222
|
+
);
|
|
223
|
+
} else if (selectedWidgetId === "switch") {
|
|
224
|
+
updatedProperty = mergeDeep(
|
|
225
|
+
propertyData,
|
|
226
|
+
{
|
|
227
|
+
dataType: "boolean",
|
|
228
|
+
propertyConfig: "switch",
|
|
229
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true
|
|
230
|
+
} satisfies BooleanProperty
|
|
231
|
+
);
|
|
232
|
+
} else if (selectedWidgetId === "date_time") {
|
|
233
|
+
updatedProperty = mergeDeep(
|
|
234
|
+
propertyData,
|
|
235
|
+
{
|
|
236
|
+
dataType: "date",
|
|
237
|
+
propertyConfig: "date_time",
|
|
238
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
239
|
+
mode: "date_time"
|
|
240
|
+
} satisfies DateProperty
|
|
241
|
+
);
|
|
242
|
+
} else if (selectedWidgetId === "repeat") {
|
|
243
|
+
updatedProperty = mergeDeep(
|
|
244
|
+
propertyData,
|
|
245
|
+
{
|
|
246
|
+
dataType: "array",
|
|
247
|
+
propertyConfig: "repeat",
|
|
248
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true
|
|
249
|
+
} satisfies ArrayProperty
|
|
250
|
+
);
|
|
251
|
+
} else if (selectedWidgetId === "block") {
|
|
252
|
+
updatedProperty = mergeDeep(
|
|
253
|
+
propertyData,
|
|
254
|
+
{
|
|
255
|
+
dataType: "array",
|
|
256
|
+
propertyConfig: "block",
|
|
257
|
+
editable: propertyData.editable !== undefined ? propertyData.editable : true,
|
|
258
|
+
oneOf: {
|
|
259
|
+
properties: {}
|
|
260
|
+
}
|
|
261
|
+
} satisfies ArrayProperty
|
|
262
|
+
);
|
|
263
|
+
} else if (selectedWidgetId && propertyConfigs[selectedWidgetId]) {
|
|
264
|
+
updatedProperty = {
|
|
265
|
+
...propertyConfigs[selectedWidgetId].property,
|
|
266
|
+
propertyConfig: selectedWidgetId
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return updatedProperty;
|
|
271
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
function printChanged(props: any, prev: any, path = "", depth = 0) {
|
|
4
|
+
if (depth > 10) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
if (props && prev && typeof props === "object" && typeof prev === "object") {
|
|
8
|
+
Object.keys(props).forEach((key) => {
|
|
9
|
+
printChanged(props[key], prev[key], path + "." + key, depth + 1);
|
|
10
|
+
});
|
|
11
|
+
} else if (props !== prev) {
|
|
12
|
+
console.log("Changed props:", path);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function useTraceUpdate(props: any) {
|
|
18
|
+
const prev = useRef(props);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
printChanged(props, prev.current, "");
|
|
21
|
+
prev.current = props;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { CollectionEditorController } from "./types/collection_editor_controller";
|
|
3
|
+
import { CollectionEditorContext } from "./ConfigControllerProvider";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hook to access the collection editor controller.
|
|
7
|
+
* The methods in this controller can be used to open the collection editor dialog.
|
|
8
|
+
*/
|
|
9
|
+
export const useCollectionEditorController = (): CollectionEditorController => useContext(CollectionEditorContext);
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React, { useCallback } from "react";
|
|
2
|
+
import {
|
|
3
|
+
EntityCollection,
|
|
4
|
+
FireCMSPlugin,
|
|
5
|
+
joinCollectionLists,
|
|
6
|
+
makePropertiesEditable,
|
|
7
|
+
ModifyCollectionProps,
|
|
8
|
+
Properties,
|
|
9
|
+
User
|
|
10
|
+
} from "@firecms/core";
|
|
11
|
+
import { ConfigControllerProvider } from "./ConfigControllerProvider";
|
|
12
|
+
import { CollectionEditorPermissionsBuilder } from "./types/config_permissions";
|
|
13
|
+
import { EditorCollectionAction } from "./ui/EditorCollectionAction";
|
|
14
|
+
import { HomePageEditorCollectionAction } from "./ui/HomePageEditorCollectionAction";
|
|
15
|
+
import { NewCollectionCard } from "./ui/NewCollectionCard";
|
|
16
|
+
import { PersistedCollection } from "./types/persisted_collection";
|
|
17
|
+
import { CollectionInference } from "./types/collection_inference";
|
|
18
|
+
import { CollectionsConfigController } from "./types/config_controller";
|
|
19
|
+
import { RootCollectionSuggestions } from "./ui/RootCollectionSuggestions";
|
|
20
|
+
import { CollectionViewHeaderAction } from "./ui/CollectionViewHeaderAction";
|
|
21
|
+
import { PropertyAddColumnComponent } from "./ui/PropertyAddColumnComponent";
|
|
22
|
+
|
|
23
|
+
export interface CollectionConfigControllerProps<EC extends PersistedCollection = PersistedCollection, UserType extends User = User> {
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Firebase app where the configuration is saved.
|
|
27
|
+
*/
|
|
28
|
+
collectionConfigController: CollectionsConfigController;
|
|
29
|
+
|
|
30
|
+
modifyCollection?: (props: ModifyCollectionProps) => EntityCollection | void;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Define what actions can be performed on the configuration.
|
|
34
|
+
*/
|
|
35
|
+
configPermissions?: CollectionEditorPermissionsBuilder<UserType, EC>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The words you define here will not be allowed to be used as group
|
|
39
|
+
* names when creating collections.
|
|
40
|
+
* e.g. ["admin"]
|
|
41
|
+
*/
|
|
42
|
+
reservedGroups: string[];
|
|
43
|
+
|
|
44
|
+
extraView?: {
|
|
45
|
+
View: React.ComponentType<{
|
|
46
|
+
path: string
|
|
47
|
+
}>,
|
|
48
|
+
icon: React.ReactNode
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
pathSuggestions?: (path: string) => Promise<string[]>;
|
|
52
|
+
|
|
53
|
+
collectionInference?: CollectionInference;
|
|
54
|
+
|
|
55
|
+
getData?: (path: string) => Promise<object[]>;
|
|
56
|
+
|
|
57
|
+
getUser: (uid: string) => UserType | null;
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Use this hook to initialise the Collection Editor plugin.
|
|
64
|
+
* This is likely the only hook you will need to use.
|
|
65
|
+
* @param firebaseApp Firebase app where your project data lives.
|
|
66
|
+
* @param configPermissions
|
|
67
|
+
* @param reservedGroups
|
|
68
|
+
* @param extraView
|
|
69
|
+
* @param pathSuggestions
|
|
70
|
+
* @param getUser
|
|
71
|
+
* @param collectionInference
|
|
72
|
+
*/
|
|
73
|
+
export function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, UserType extends User = User>
|
|
74
|
+
({
|
|
75
|
+
collectionConfigController,
|
|
76
|
+
modifyCollection,
|
|
77
|
+
configPermissions,
|
|
78
|
+
reservedGroups,
|
|
79
|
+
extraView,
|
|
80
|
+
pathSuggestions,
|
|
81
|
+
getUser,
|
|
82
|
+
collectionInference,
|
|
83
|
+
getData
|
|
84
|
+
}: CollectionConfigControllerProps<EC, UserType>): FireCMSPlugin<any, any, PersistedCollection> {
|
|
85
|
+
|
|
86
|
+
const injectCollections = useCallback(
|
|
87
|
+
(collections: EntityCollection[]) => {
|
|
88
|
+
const markAsEditable = (c: PersistedCollection) => {
|
|
89
|
+
makePropertiesEditable(c.properties as Properties);
|
|
90
|
+
c.subcollections?.forEach(markAsEditable);
|
|
91
|
+
};
|
|
92
|
+
const storedCollections = collectionConfigController.collections ?? [];
|
|
93
|
+
storedCollections.forEach(markAsEditable);
|
|
94
|
+
return joinCollectionLists(collections, storedCollections, [], modifyCollection);
|
|
95
|
+
},
|
|
96
|
+
[collectionConfigController.collections, modifyCollection]);
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
name: "Collection Editor",
|
|
100
|
+
loading: collectionConfigController.loading,
|
|
101
|
+
collections: {
|
|
102
|
+
injectCollections,
|
|
103
|
+
CollectionActions: EditorCollectionAction
|
|
104
|
+
},
|
|
105
|
+
provider: {
|
|
106
|
+
Component: ConfigControllerProvider,
|
|
107
|
+
props: {
|
|
108
|
+
collectionConfigController,
|
|
109
|
+
configPermissions,
|
|
110
|
+
collectionInference,
|
|
111
|
+
reservedGroups,
|
|
112
|
+
extraView,
|
|
113
|
+
pathSuggestions,
|
|
114
|
+
getUser,
|
|
115
|
+
getData
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
homePage: {
|
|
119
|
+
additionalChildrenEnd: <RootCollectionSuggestions/>,
|
|
120
|
+
CollectionActions: HomePageEditorCollectionAction,
|
|
121
|
+
AdditionalCards: NewCollectionCard,
|
|
122
|
+
},
|
|
123
|
+
collectionView: {
|
|
124
|
+
HeaderAction: CollectionViewHeaderAction,
|
|
125
|
+
AddColumnComponent: PropertyAddColumnComponent
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { CollectionsConfigController } from "./types/config_controller";
|
|
3
|
+
import { ConfigControllerContext } from "./ConfigControllerProvider";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Use this hook to access the configuration controller.
|
|
7
|
+
* You can use it to get the list of collections, and to save/delete collections.
|
|
8
|
+
*/
|
|
9
|
+
export const useCollectionsConfigController = (): CollectionsConfigController => useContext(ConfigControllerContext);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { isPropertyBuilder, Properties, PropertiesOrBuilders, Property, PropertyOrBuilder } from "@firecms/core";
|
|
2
|
+
|
|
3
|
+
export function editableProperty(property: PropertyOrBuilder | PropertyOrBuilder): boolean {
|
|
4
|
+
if (isPropertyBuilder(property))
|
|
5
|
+
return false;
|
|
6
|
+
if (isPropertyBuilder(property as PropertyOrBuilder))
|
|
7
|
+
return false;
|
|
8
|
+
else {
|
|
9
|
+
const eProperty = property as Property;
|
|
10
|
+
if (eProperty.dataType === "array" && typeof eProperty.of === "function")
|
|
11
|
+
return false;
|
|
12
|
+
else if (eProperty.dataType === "array" && Array.isArray(eProperty.of))
|
|
13
|
+
return false;
|
|
14
|
+
return Boolean(eProperty.editable);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function removeNonEditableProperties(properties: PropertiesOrBuilders<any>): Properties {
|
|
19
|
+
return Object.entries(properties)
|
|
20
|
+
.filter(([_, property]) => editableProperty(property))
|
|
21
|
+
.map(([key, propertyOrBuilder]) => {
|
|
22
|
+
const property = propertyOrBuilder as Property;
|
|
23
|
+
if (!editableProperty(property)) {
|
|
24
|
+
return undefined;
|
|
25
|
+
} else if (property.dataType === "map" && property.properties) {
|
|
26
|
+
return {
|
|
27
|
+
[key]: {
|
|
28
|
+
...property,
|
|
29
|
+
properties: removeNonEditableProperties(property.properties as PropertiesOrBuilders)
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
} else {
|
|
33
|
+
return { [key]: property };
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
.filter((e) => Boolean(e))
|
|
37
|
+
.reduce((a, b) => ({ ...a, ...b }), {}) as Properties;
|
|
38
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import synonyms from "./synonyms";
|
|
2
|
+
import { iconKeys } from "@firecms/core";
|
|
3
|
+
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
import * as JsSearch from "js-search";
|
|
6
|
+
|
|
7
|
+
export const iconsSearch = new JsSearch.Search("key");
|
|
8
|
+
iconsSearch.addIndex("synonyms");
|
|
9
|
+
|
|
10
|
+
iconsSearch.addDocuments(iconKeys
|
|
11
|
+
.map((importName) => {
|
|
12
|
+
return {
|
|
13
|
+
key: importName,
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
synonyms: synonyms[importName] ?? [],
|
|
16
|
+
}
|
|
17
|
+
}));
|