@firecms/collection_editor 3.0.1 → 3.1.0-canary.02232f4
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 +6 -0
- package/dist/api/generateCollectionApi.d.ts +71 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.es.js +15260 -8173
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +15257 -8170
- package/dist/index.umd.js.map +1 -1
- package/dist/locales/de.d.ts +120 -0
- package/dist/locales/en.d.ts +120 -0
- package/dist/locales/es.d.ts +120 -0
- package/dist/locales/fr.d.ts +120 -0
- package/dist/locales/hi.d.ts +120 -0
- package/dist/locales/it.d.ts +120 -0
- package/dist/locales/pt.d.ts +120 -0
- package/dist/types/collection_editor_controller.d.ts +14 -0
- package/dist/types/collection_inference.d.ts +8 -2
- package/dist/types/config_controller.d.ts +23 -2
- package/dist/ui/AddKanbanColumnAction.d.ts +11 -0
- package/dist/ui/KanbanSetupAction.d.ts +10 -0
- package/dist/ui/collection_editor/AICollectionGeneratorPopover.d.ts +37 -0
- package/dist/ui/collection_editor/AIModifiedPathsContext.d.ts +20 -0
- package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +2 -3
- package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +24 -0
- package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +4 -1
- package/dist/ui/collection_editor/CollectionJsonImportDialog.d.ts +7 -0
- package/dist/ui/collection_editor/CollectionYupValidation.d.ts +9 -13
- package/dist/ui/collection_editor/DisplaySettingsForm.d.ts +3 -0
- package/dist/ui/collection_editor/EntityActionsEditTab.d.ts +2 -1
- package/dist/ui/collection_editor/ExtendSettingsForm.d.ts +14 -0
- package/dist/ui/collection_editor/GeneralSettingsForm.d.ts +7 -0
- package/dist/ui/collection_editor/KanbanConfigSection.d.ts +4 -0
- package/dist/ui/collection_editor/PropertyEditView.d.ts +6 -1
- package/dist/ui/collection_editor/PropertyTree.d.ts +2 -1
- package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +2 -1
- package/dist/ui/collection_editor/ViewModeSwitch.d.ts +6 -0
- package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +2 -1
- package/dist/ui/collection_editor/properties/conditions/ConditionsEditor.d.ts +10 -0
- package/dist/ui/collection_editor/properties/conditions/ConditionsPanel.d.ts +2 -0
- package/dist/ui/collection_editor/properties/conditions/EnumConditionsEditor.d.ts +6 -0
- package/dist/ui/collection_editor/properties/conditions/index.d.ts +6 -0
- package/dist/ui/collection_editor/properties/conditions/property_paths.d.ts +19 -0
- package/dist/useCollectionEditorPlugin.d.ts +7 -1
- package/dist/utils/validateCollectionJson.d.ts +22 -0
- package/package.json +15 -15
- package/src/ConfigControllerProvider.tsx +82 -47
- package/src/api/generateCollectionApi.ts +119 -0
- package/src/api/index.ts +1 -0
- package/src/index.ts +28 -1
- package/src/locales/de.ts +125 -0
- package/src/locales/en.ts +145 -0
- package/src/locales/es.ts +125 -0
- package/src/locales/fr.ts +125 -0
- package/src/locales/hi.ts +125 -0
- package/src/locales/it.ts +125 -0
- package/src/locales/pt.ts +125 -0
- package/src/types/collection_editor_controller.tsx +16 -3
- package/src/types/collection_inference.ts +15 -2
- package/src/types/config_controller.tsx +27 -2
- package/src/ui/AddKanbanColumnAction.tsx +203 -0
- package/src/ui/EditorCollectionAction.tsx +3 -3
- package/src/ui/EditorCollectionActionStart.tsx +1 -2
- package/src/ui/EditorEntityAction.tsx +3 -2
- package/src/ui/HomePageEditorCollectionAction.tsx +41 -13
- package/src/ui/KanbanSetupAction.tsx +38 -0
- package/src/ui/MissingReferenceWidget.tsx +1 -1
- package/src/ui/NewCollectionButton.tsx +4 -2
- package/src/ui/NewCollectionCard.tsx +7 -4
- package/src/ui/PropertyAddColumnComponent.tsx +4 -3
- package/src/ui/collection_editor/AICollectionGeneratorPopover.tsx +243 -0
- package/src/ui/collection_editor/AIModifiedPathsContext.tsx +88 -0
- package/src/ui/collection_editor/CollectionDetailsForm.tsx +222 -267
- package/src/ui/collection_editor/CollectionEditorDialog.tsx +270 -198
- package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +138 -71
- package/src/ui/collection_editor/CollectionJsonImportDialog.tsx +171 -0
- package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +202 -101
- package/src/ui/collection_editor/DisplaySettingsForm.tsx +335 -0
- package/src/ui/collection_editor/EntityActionsEditTab.tsx +106 -97
- package/src/ui/collection_editor/EntityActionsSelectDialog.tsx +8 -10
- package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +5 -7
- package/src/ui/collection_editor/EnumForm.tsx +153 -102
- package/src/ui/collection_editor/ExtendSettingsForm.tsx +94 -0
- package/src/ui/collection_editor/GeneralSettingsForm.tsx +335 -0
- package/src/ui/collection_editor/GetCodeDialog.tsx +63 -41
- package/src/ui/collection_editor/KanbanConfigSection.tsx +209 -0
- package/src/ui/collection_editor/LayoutModeSwitch.tsx +27 -43
- package/src/ui/collection_editor/PropertyEditView.tsx +272 -199
- package/src/ui/collection_editor/PropertyFieldPreview.tsx +1 -1
- package/src/ui/collection_editor/PropertyTree.tsx +130 -58
- package/src/ui/collection_editor/SubcollectionsEditTab.tsx +169 -163
- package/src/ui/collection_editor/UnsavedChangesDialog.tsx +0 -2
- package/src/ui/collection_editor/ViewModeSwitch.tsx +43 -0
- package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +6 -3
- package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +5 -2
- package/src/ui/collection_editor/properties/BlockPropertyField.tsx +0 -2
- package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +4 -1
- package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +6 -4
- package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +126 -42
- package/src/ui/collection_editor/properties/EnumPropertyField.tsx +32 -24
- package/src/ui/collection_editor/properties/MapPropertyField.tsx +8 -9
- package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +128 -53
- package/src/ui/collection_editor/properties/NumberPropertyField.tsx +3 -1
- package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +5 -4
- package/src/ui/collection_editor/properties/StoragePropertyField.tsx +47 -52
- package/src/ui/collection_editor/properties/StringPropertyField.tsx +3 -1
- package/src/ui/collection_editor/properties/UrlPropertyField.tsx +12 -10
- package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +23 -4
- package/src/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +866 -0
- package/src/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +28 -0
- package/src/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +599 -0
- package/src/ui/collection_editor/properties/conditions/index.ts +6 -0
- package/src/ui/collection_editor/properties/conditions/property_paths.ts +92 -0
- package/src/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +5 -2
- package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +7 -5
- package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +10 -7
- package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +11 -9
- package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +5 -2
- package/src/useCollectionEditorPlugin.tsx +53 -22
- package/src/utils/validateCollectionJson.ts +380 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Properties, Property, PropertyOrBuilder, isPropertyBuilder } from "@firecms/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Recursively extract all property paths from a Properties object.
|
|
5
|
+
* For nested map properties, creates dot-notation paths like "address.city".
|
|
6
|
+
* Skips PropertyBuilder functions (callbacks) as they cannot be statically analyzed.
|
|
7
|
+
*
|
|
8
|
+
* @param properties - The properties object to extract paths from
|
|
9
|
+
* @param prefix - Optional prefix for nested paths (used in recursion)
|
|
10
|
+
* @returns Array of property path strings
|
|
11
|
+
*/
|
|
12
|
+
export function getPropertyPaths(
|
|
13
|
+
properties: Properties | undefined,
|
|
14
|
+
prefix: string = ""
|
|
15
|
+
): string[] {
|
|
16
|
+
if (!properties) return [];
|
|
17
|
+
|
|
18
|
+
const paths: string[] = [];
|
|
19
|
+
|
|
20
|
+
for (const [key, propertyOrBuilder] of Object.entries(properties)) {
|
|
21
|
+
if (!propertyOrBuilder) continue;
|
|
22
|
+
|
|
23
|
+
// Skip PropertyBuilder functions - they require runtime values to resolve
|
|
24
|
+
if (isPropertyBuilder(propertyOrBuilder)) continue;
|
|
25
|
+
|
|
26
|
+
const property = propertyOrBuilder as Property;
|
|
27
|
+
const fullPath = prefix ? `${prefix}.${key}` : key;
|
|
28
|
+
paths.push(fullPath);
|
|
29
|
+
|
|
30
|
+
// Recursively add nested map properties
|
|
31
|
+
if (property.dataType === "map" && property.properties) {
|
|
32
|
+
const nestedPaths = getPropertyPaths(
|
|
33
|
+
property.properties as Properties,
|
|
34
|
+
fullPath
|
|
35
|
+
);
|
|
36
|
+
paths.push(...nestedPaths);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// For arrays with object items, add the nested paths too
|
|
40
|
+
if (property.dataType === "array" && property.of) {
|
|
41
|
+
const ofPropertyOrBuilder = property.of as PropertyOrBuilder;
|
|
42
|
+
// Skip if the array's 'of' is a PropertyBuilder
|
|
43
|
+
if (!isPropertyBuilder(ofPropertyOrBuilder)) {
|
|
44
|
+
const ofProperty = ofPropertyOrBuilder as Property;
|
|
45
|
+
if (ofProperty.dataType === "map" && ofProperty.properties) {
|
|
46
|
+
const nestedPaths = getPropertyPaths(
|
|
47
|
+
ofProperty.properties as Properties,
|
|
48
|
+
`${fullPath}[]`
|
|
49
|
+
);
|
|
50
|
+
paths.push(...nestedPaths);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return paths;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get property paths grouped by top-level property for UI display.
|
|
61
|
+
* Skips PropertyBuilder functions.
|
|
62
|
+
*
|
|
63
|
+
* @param properties - The properties object
|
|
64
|
+
* @returns Object with top-level keys mapping to their nested paths
|
|
65
|
+
*/
|
|
66
|
+
export function getGroupedPropertyPaths(
|
|
67
|
+
properties: Properties | undefined
|
|
68
|
+
): Record<string, string[]> {
|
|
69
|
+
if (!properties) return {};
|
|
70
|
+
|
|
71
|
+
const grouped: Record<string, string[]> = {};
|
|
72
|
+
|
|
73
|
+
for (const [key, propertyOrBuilder] of Object.entries(properties)) {
|
|
74
|
+
if (!propertyOrBuilder) continue;
|
|
75
|
+
|
|
76
|
+
// Skip PropertyBuilder functions
|
|
77
|
+
if (isPropertyBuilder(propertyOrBuilder)) continue;
|
|
78
|
+
|
|
79
|
+
const property = propertyOrBuilder as Property;
|
|
80
|
+
grouped[key] = [key];
|
|
81
|
+
|
|
82
|
+
if (property.dataType === "map" && property.properties) {
|
|
83
|
+
const nestedPaths = getPropertyPaths(
|
|
84
|
+
property.properties as Properties,
|
|
85
|
+
key
|
|
86
|
+
);
|
|
87
|
+
grouped[key].push(...nestedPaths);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return grouped;
|
|
92
|
+
}
|
|
@@ -3,6 +3,7 @@ import React from "react";
|
|
|
3
3
|
import { getIn, useFormex } from "@firecms/formex";
|
|
4
4
|
import { DebouncedTextField } from "@firecms/ui";
|
|
5
5
|
import { GeneralPropertyValidation } from "./GeneralPropertyValidation";
|
|
6
|
+
import { useTranslation } from "@firecms/core";
|
|
6
7
|
|
|
7
8
|
export function ArrayPropertyValidation({
|
|
8
9
|
max = true,
|
|
@@ -19,6 +20,8 @@ export function ArrayPropertyValidation({
|
|
|
19
20
|
handleChange
|
|
20
21
|
} = useFormex();
|
|
21
22
|
|
|
23
|
+
const { t } = useTranslation();
|
|
24
|
+
|
|
22
25
|
const validationMin = "validation.min";
|
|
23
26
|
const validationMax = "validation.max";
|
|
24
27
|
|
|
@@ -30,7 +33,7 @@ export function ArrayPropertyValidation({
|
|
|
30
33
|
{min && <div className={"col-span-6"}>
|
|
31
34
|
<DebouncedTextField value={getIn(values, validationMin)}
|
|
32
35
|
disabled={disabled}
|
|
33
|
-
label={"
|
|
36
|
+
label={t("min_length")}
|
|
34
37
|
name={validationMin}
|
|
35
38
|
type="number"
|
|
36
39
|
size="small"
|
|
@@ -39,7 +42,7 @@ export function ArrayPropertyValidation({
|
|
|
39
42
|
{max && <div className={"col-span-6"}>
|
|
40
43
|
<DebouncedTextField value={getIn(values, validationMax)}
|
|
41
44
|
disabled={disabled}
|
|
42
|
-
label={"
|
|
45
|
+
label={t("max_length")}
|
|
43
46
|
name={validationMax}
|
|
44
47
|
type="number"
|
|
45
48
|
size="small"
|
|
@@ -3,6 +3,7 @@ import React from "react";
|
|
|
3
3
|
import { Field, FormexFieldProps, getIn, useFormex } from "@firecms/formex";
|
|
4
4
|
import { DebouncedTextField } from "@firecms/ui";
|
|
5
5
|
import { SwitchControl } from "../../SwitchControl";
|
|
6
|
+
import { useTranslation } from "@firecms/core";
|
|
6
7
|
|
|
7
8
|
export function GeneralPropertyValidation({ disabled }: {
|
|
8
9
|
required?: boolean;
|
|
@@ -10,6 +11,7 @@ export function GeneralPropertyValidation({ disabled }: {
|
|
|
10
11
|
}) {
|
|
11
12
|
|
|
12
13
|
const { values, handleChange } = useFormex();
|
|
14
|
+
const { t } = useTranslation();
|
|
13
15
|
|
|
14
16
|
const validationRequired = "validation.required";
|
|
15
17
|
const validationRequiredMessage = "validation.requiredMessage";
|
|
@@ -24,8 +26,8 @@ export function GeneralPropertyValidation({ disabled }: {
|
|
|
24
26
|
{({ field, form }: FormexFieldProps) => {
|
|
25
27
|
return <SwitchControl
|
|
26
28
|
disabled={disabled}
|
|
27
|
-
label={"
|
|
28
|
-
tooltip={
|
|
29
|
+
label={t("required")}
|
|
30
|
+
tooltip={t("required_tooltip")}
|
|
29
31
|
form={form}
|
|
30
32
|
field={field}/>
|
|
31
33
|
}}
|
|
@@ -39,8 +41,8 @@ export function GeneralPropertyValidation({ disabled }: {
|
|
|
39
41
|
{({ field, form }: FormexFieldProps) => {
|
|
40
42
|
return <SwitchControl
|
|
41
43
|
disabled={disabled}
|
|
42
|
-
label={"
|
|
43
|
-
tooltip={"
|
|
44
|
+
label={t("unique")}
|
|
45
|
+
tooltip={t("unique_tooltip")}
|
|
44
46
|
form={form}
|
|
45
47
|
field={field}/>
|
|
46
48
|
}}
|
|
@@ -51,7 +53,7 @@ export function GeneralPropertyValidation({ disabled }: {
|
|
|
51
53
|
<DebouncedTextField
|
|
52
54
|
disabled={disabled}
|
|
53
55
|
value={getIn(values, validationRequiredMessage)}
|
|
54
|
-
label={"
|
|
56
|
+
label={t("required_message")}
|
|
55
57
|
name={validationRequiredMessage}
|
|
56
58
|
size="small"
|
|
57
59
|
onChange={handleChange}/>
|
|
@@ -4,6 +4,7 @@ import { Field, FormexFieldProps, getIn, useFormex } from "@firecms/formex";
|
|
|
4
4
|
import { DebouncedTextField } from "@firecms/ui";
|
|
5
5
|
import { GeneralPropertyValidation } from "./GeneralPropertyValidation";
|
|
6
6
|
import { SwitchControl } from "../../SwitchControl";
|
|
7
|
+
import { useTranslation } from "@firecms/core";
|
|
7
8
|
|
|
8
9
|
export function NumberPropertyValidation({ disabled }: {
|
|
9
10
|
disabled: boolean;
|
|
@@ -14,6 +15,8 @@ export function NumberPropertyValidation({ disabled }: {
|
|
|
14
15
|
handleChange
|
|
15
16
|
} = useFormex();
|
|
16
17
|
|
|
18
|
+
const { t } = useTranslation();
|
|
19
|
+
|
|
17
20
|
const validationMin = "validation.min";
|
|
18
21
|
const validationMax = "validation.max";
|
|
19
22
|
const validationLessThan = "validation.lessThan";
|
|
@@ -30,7 +33,7 @@ export function NumberPropertyValidation({ disabled }: {
|
|
|
30
33
|
|
|
31
34
|
<div className={"col-span-6"}>
|
|
32
35
|
<DebouncedTextField value={getIn(values, validationMin)}
|
|
33
|
-
label={"
|
|
36
|
+
label={t("min_value")}
|
|
34
37
|
name={validationMin}
|
|
35
38
|
type="number"
|
|
36
39
|
size="small"
|
|
@@ -40,7 +43,7 @@ export function NumberPropertyValidation({ disabled }: {
|
|
|
40
43
|
|
|
41
44
|
<div className={"col-span-6"}>
|
|
42
45
|
<DebouncedTextField value={getIn(values, validationMax)}
|
|
43
|
-
label={"
|
|
46
|
+
label={t("max_value")}
|
|
44
47
|
name={validationMax}
|
|
45
48
|
type="number"
|
|
46
49
|
size="small"
|
|
@@ -53,7 +56,7 @@ export function NumberPropertyValidation({ disabled }: {
|
|
|
53
56
|
<div className={"col-span-6"}>
|
|
54
57
|
<DebouncedTextField
|
|
55
58
|
value={getIn(values, validationLessThan)}
|
|
56
|
-
label={"
|
|
59
|
+
label={t("less_than")}
|
|
57
60
|
name={validationLessThan}
|
|
58
61
|
type="number"
|
|
59
62
|
size="small"
|
|
@@ -65,7 +68,7 @@ export function NumberPropertyValidation({ disabled }: {
|
|
|
65
68
|
<div className={"col-span-6"}>
|
|
66
69
|
<DebouncedTextField
|
|
67
70
|
value={getIn(values, validationMoreThan)}
|
|
68
|
-
label={"
|
|
71
|
+
label={t("more_than")}
|
|
69
72
|
name={validationMoreThan}
|
|
70
73
|
type="number"
|
|
71
74
|
size="small"
|
|
@@ -79,7 +82,7 @@ export function NumberPropertyValidation({ disabled }: {
|
|
|
79
82
|
type="checkbox">
|
|
80
83
|
{({ field, form }: FormexFieldProps) => {
|
|
81
84
|
return <SwitchControl
|
|
82
|
-
label={"
|
|
85
|
+
label={t("positive_value")}
|
|
83
86
|
disabled={disabled}
|
|
84
87
|
form={form}
|
|
85
88
|
field={field}/>
|
|
@@ -91,7 +94,7 @@ export function NumberPropertyValidation({ disabled }: {
|
|
|
91
94
|
type="checkbox">
|
|
92
95
|
{({ field, form }: FormexFieldProps) => {
|
|
93
96
|
return <SwitchControl
|
|
94
|
-
label={"
|
|
97
|
+
label={t("negative_value")}
|
|
95
98
|
disabled={disabled}
|
|
96
99
|
form={form}
|
|
97
100
|
field={field}/>
|
|
@@ -103,7 +106,7 @@ export function NumberPropertyValidation({ disabled }: {
|
|
|
103
106
|
type="checkbox">
|
|
104
107
|
{({ field, form }: FormexFieldProps) => {
|
|
105
108
|
return <SwitchControl
|
|
106
|
-
label={"
|
|
109
|
+
label={t("integer_value")}
|
|
107
110
|
disabled={disabled}
|
|
108
111
|
form={form}
|
|
109
112
|
field={field}/>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
import { Field, FormexFieldProps, getIn, useFormex } from "@firecms/formex";
|
|
4
|
-
import { FieldCaption, serializeRegExp } from "@firecms/core";
|
|
4
|
+
import { FieldCaption, serializeRegExp, useTranslation } from "@firecms/core";
|
|
5
5
|
import { DebouncedTextField, } from "@firecms/ui";
|
|
6
6
|
import { GeneralPropertyValidation } from "./GeneralPropertyValidation";
|
|
7
7
|
import { SwitchControl } from "../../SwitchControl";
|
|
@@ -34,6 +34,8 @@ export function StringPropertyValidation({
|
|
|
34
34
|
errors
|
|
35
35
|
} = useFormex();
|
|
36
36
|
|
|
37
|
+
const { t } = useTranslation();
|
|
38
|
+
|
|
37
39
|
const validationLength = "validation.length";
|
|
38
40
|
const validationMin = "validation.min";
|
|
39
41
|
const validationMax = "validation.max";
|
|
@@ -58,7 +60,7 @@ export function StringPropertyValidation({
|
|
|
58
60
|
type="checkbox">
|
|
59
61
|
{({ field, form }: FormexFieldProps) => {
|
|
60
62
|
return <SwitchControl
|
|
61
|
-
label={"
|
|
63
|
+
label={t("lowercase")}
|
|
62
64
|
disabled={disabled}
|
|
63
65
|
form={form}
|
|
64
66
|
field={field}/>
|
|
@@ -71,7 +73,7 @@ export function StringPropertyValidation({
|
|
|
71
73
|
type="checkbox">
|
|
72
74
|
{({ field, form }: FormexFieldProps) => {
|
|
73
75
|
return <SwitchControl
|
|
74
|
-
label={"
|
|
76
|
+
label={t("uppercase")}
|
|
75
77
|
disabled={disabled}
|
|
76
78
|
form={form}
|
|
77
79
|
field={field}/>
|
|
@@ -84,7 +86,7 @@ export function StringPropertyValidation({
|
|
|
84
86
|
type="checkbox">
|
|
85
87
|
{({ field, form }: FormexFieldProps) => {
|
|
86
88
|
return <SwitchControl
|
|
87
|
-
label={"
|
|
89
|
+
label={t("trim")}
|
|
88
90
|
disabled={disabled}
|
|
89
91
|
form={form}
|
|
90
92
|
field={field}/>
|
|
@@ -98,7 +100,7 @@ export function StringPropertyValidation({
|
|
|
98
100
|
{length && <div className={"col-span-4"}>
|
|
99
101
|
<DebouncedTextField
|
|
100
102
|
value={getIn(values, validationLength)}
|
|
101
|
-
label={"
|
|
103
|
+
label={t("exact_length")}
|
|
102
104
|
name={validationLength}
|
|
103
105
|
type="number"
|
|
104
106
|
size="small"
|
|
@@ -109,7 +111,7 @@ export function StringPropertyValidation({
|
|
|
109
111
|
|
|
110
112
|
{min && <div className={"col-span-4"}>
|
|
111
113
|
<DebouncedTextField value={getIn(values, validationMin)}
|
|
112
|
-
label={"
|
|
114
|
+
label={t("min_length")}
|
|
113
115
|
name={validationMin}
|
|
114
116
|
type="number"
|
|
115
117
|
size="small"
|
|
@@ -120,7 +122,7 @@ export function StringPropertyValidation({
|
|
|
120
122
|
|
|
121
123
|
{max && <div className={"col-span-4"}>
|
|
122
124
|
<DebouncedTextField value={getIn(values, validationMax)}
|
|
123
|
-
label={"
|
|
125
|
+
label={t("max_length")}
|
|
124
126
|
name={validationMax}
|
|
125
127
|
type="number"
|
|
126
128
|
size="small"
|
|
@@ -134,13 +136,13 @@ export function StringPropertyValidation({
|
|
|
134
136
|
{matches && <div className={"col-span-12"}>
|
|
135
137
|
<Field name={validationMatches}
|
|
136
138
|
as={DebouncedTextField}
|
|
137
|
-
label={"
|
|
139
|
+
label={t("matches_regex")}
|
|
138
140
|
size="small"
|
|
139
141
|
disabled={disabled}
|
|
140
142
|
value={matchesStringValue}
|
|
141
143
|
error={Boolean(matchesError)}/>
|
|
142
144
|
<FieldCaption error={Boolean(matchesError)}>
|
|
143
|
-
{matchesError ? "
|
|
145
|
+
{matchesError ? t("not_valid_regexp") : t("regex_helper")}
|
|
144
146
|
</FieldCaption>
|
|
145
147
|
</div>}
|
|
146
148
|
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import { PropsWithChildren } from "react";
|
|
2
2
|
|
|
3
3
|
import { ExpandablePanel, RuleIcon, Typography } from "@firecms/ui";
|
|
4
|
+
import { useTranslation } from "@firecms/core";
|
|
4
5
|
|
|
5
6
|
export function ValidationPanel({
|
|
6
7
|
children
|
|
7
8
|
}: PropsWithChildren<{}>) {
|
|
8
9
|
|
|
10
|
+
const { t } = useTranslation();
|
|
11
|
+
|
|
9
12
|
return (
|
|
10
13
|
<ExpandablePanel
|
|
11
14
|
initiallyExpanded={false}
|
|
12
15
|
asField={true}
|
|
13
16
|
innerClassName="p-4"
|
|
14
17
|
title={
|
|
15
|
-
<div className="flex flex-row text-surface-500">
|
|
18
|
+
<div className="flex flex-row text-surface-500 text-text-secondary dark:text-text-secondary-dark">
|
|
16
19
|
<RuleIcon/>
|
|
17
20
|
<Typography variant={"subtitle2"}
|
|
18
21
|
className="ml-4">
|
|
19
|
-
|
|
22
|
+
{t("validation")}
|
|
20
23
|
</Typography>
|
|
21
24
|
</div>
|
|
22
25
|
}>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { FireCMSPlugin, useAuthController, useNavigationController, User } from "@firecms/core";
|
|
2
|
+
import { FireCMSPlugin, useAuthController, useNavigationController, User, useTranslation } from "@firecms/core";
|
|
3
3
|
import { ConfigControllerProvider } from "./ConfigControllerProvider";
|
|
4
4
|
import { CollectionEditorPermissionsBuilder } from "./types/config_permissions";
|
|
5
5
|
import { EditorCollectionAction } from "./ui/EditorCollectionAction";
|
|
@@ -7,6 +7,7 @@ import { HomePageEditorCollectionAction } from "./ui/HomePageEditorCollectionAct
|
|
|
7
7
|
import { PersistedCollection } from "./types/persisted_collection";
|
|
8
8
|
import { CollectionInference } from "./types/collection_inference";
|
|
9
9
|
import { CollectionsConfigController } from "./types/config_controller";
|
|
10
|
+
import { CollectionGenerationCallback } from "./api/generateCollectionApi";
|
|
10
11
|
import { CollectionViewHeaderAction } from "./ui/CollectionViewHeaderAction";
|
|
11
12
|
import { PropertyAddColumnComponent } from "./ui/PropertyAddColumnComponent";
|
|
12
13
|
import { NewCollectionButton } from "./ui/NewCollectionButton";
|
|
@@ -15,6 +16,15 @@ import { useCollectionEditorController } from "./useCollectionEditorController";
|
|
|
15
16
|
import { EditorCollectionActionStart } from "./ui/EditorCollectionActionStart";
|
|
16
17
|
import { NewCollectionCard } from "./ui/NewCollectionCard";
|
|
17
18
|
import { EditorEntityAction } from "./ui/EditorEntityAction";
|
|
19
|
+
import { KanbanSetupAction } from "./ui/KanbanSetupAction";
|
|
20
|
+
import { AddKanbanColumnAction } from "./ui/AddKanbanColumnAction";
|
|
21
|
+
import { collectionEditorTranslationsEn } from "./locales/en";
|
|
22
|
+
import { collectionEditorTranslationsEs } from "./locales/es";
|
|
23
|
+
import { collectionEditorTranslationsDe } from "./locales/de";
|
|
24
|
+
import { collectionEditorTranslationsFr } from "./locales/fr";
|
|
25
|
+
import { collectionEditorTranslationsIt } from "./locales/it";
|
|
26
|
+
import { collectionEditorTranslationsHi } from "./locales/hi";
|
|
27
|
+
import { collectionEditorTranslationsPt } from "./locales/pt";
|
|
18
28
|
|
|
19
29
|
export interface CollectionConfigControllerProps<EC extends PersistedCollection = PersistedCollection, USER extends User = User> {
|
|
20
30
|
|
|
@@ -54,6 +64,12 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
|
|
|
54
64
|
|
|
55
65
|
includeIntroView?: boolean;
|
|
56
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Callback function for generating/modifying collections.
|
|
69
|
+
* The plugin is API-agnostic - the consumer provides the implementation.
|
|
70
|
+
*/
|
|
71
|
+
generateCollection?: CollectionGenerationCallback;
|
|
72
|
+
|
|
57
73
|
}
|
|
58
74
|
|
|
59
75
|
/**
|
|
@@ -68,18 +84,19 @@ export interface CollectionConfigControllerProps<EC extends PersistedCollection
|
|
|
68
84
|
* @param collectionInference
|
|
69
85
|
*/
|
|
70
86
|
export function useCollectionEditorPlugin<EC extends PersistedCollection = PersistedCollection, USER extends User = User>
|
|
71
|
-
({
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
({
|
|
88
|
+
collectionConfigController,
|
|
89
|
+
configPermissions,
|
|
90
|
+
reservedGroups,
|
|
91
|
+
extraView,
|
|
92
|
+
getUser,
|
|
93
|
+
collectionInference,
|
|
94
|
+
getData,
|
|
95
|
+
onAnalyticsEvent,
|
|
96
|
+
includeIntroView = true,
|
|
97
|
+
pathSuggestions,
|
|
98
|
+
generateCollection
|
|
99
|
+
}: CollectionConfigControllerProps<EC, USER>): FireCMSPlugin<any, any, PersistedCollection> {
|
|
83
100
|
|
|
84
101
|
return {
|
|
85
102
|
key: "collection_editor",
|
|
@@ -95,12 +112,13 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
|
|
|
95
112
|
getUser,
|
|
96
113
|
getData,
|
|
97
114
|
onAnalyticsEvent,
|
|
98
|
-
pathSuggestions
|
|
115
|
+
pathSuggestions,
|
|
116
|
+
generateCollection
|
|
99
117
|
}
|
|
100
118
|
},
|
|
101
119
|
homePage: {
|
|
102
|
-
additionalActions: <NewCollectionButton/>,
|
|
103
|
-
additionalChildrenStart: includeIntroView ? <IntroWidget/> : undefined,
|
|
120
|
+
additionalActions: <NewCollectionButton />,
|
|
121
|
+
additionalChildrenStart: includeIntroView ? <IntroWidget /> : undefined,
|
|
104
122
|
CollectionActions: HomePageEditorCollectionAction,
|
|
105
123
|
AdditionalCards: NewCollectionCard,
|
|
106
124
|
allowDragAndDrop: true,
|
|
@@ -111,10 +129,23 @@ export function useCollectionEditorPlugin<EC extends PersistedCollection = Persi
|
|
|
111
129
|
CollectionActionsStart: EditorCollectionActionStart,
|
|
112
130
|
CollectionActions: EditorCollectionAction,
|
|
113
131
|
HeaderAction: CollectionViewHeaderAction,
|
|
114
|
-
AddColumnComponent: PropertyAddColumnComponent
|
|
132
|
+
AddColumnComponent: PropertyAddColumnComponent,
|
|
133
|
+
onColumnsReorder: collectionConfigController.updatePropertiesOrder,
|
|
134
|
+
onKanbanColumnsReorder: collectionConfigController.updateKanbanColumnsOrder,
|
|
135
|
+
KanbanSetupComponent: KanbanSetupAction,
|
|
136
|
+
AddKanbanColumnComponent: AddKanbanColumnAction
|
|
115
137
|
},
|
|
116
138
|
form: {
|
|
117
139
|
ActionsTop: EditorEntityAction,
|
|
140
|
+
},
|
|
141
|
+
i18n: {
|
|
142
|
+
en: collectionEditorTranslationsEn,
|
|
143
|
+
es: collectionEditorTranslationsEs,
|
|
144
|
+
de: collectionEditorTranslationsDe,
|
|
145
|
+
fr: collectionEditorTranslationsFr,
|
|
146
|
+
it: collectionEditorTranslationsIt,
|
|
147
|
+
hi: collectionEditorTranslationsHi,
|
|
148
|
+
pt: collectionEditorTranslationsPt
|
|
118
149
|
}
|
|
119
150
|
};
|
|
120
151
|
}
|
|
@@ -126,6 +157,7 @@ export function IntroWidget() {
|
|
|
126
157
|
throw Error("Navigation not ready in FireCMSHomePage");
|
|
127
158
|
|
|
128
159
|
const authController = useAuthController();
|
|
160
|
+
const { t } = useTranslation();
|
|
129
161
|
|
|
130
162
|
const collectionEditorController = useCollectionEditorController();
|
|
131
163
|
const canCreateCollections = collectionEditorController.configPermissions
|
|
@@ -141,10 +173,9 @@ export function IntroWidget() {
|
|
|
141
173
|
return (
|
|
142
174
|
<Paper
|
|
143
175
|
className={"my-4 px-4 py-6 flex flex-col bg-white dark:bg-surface-accent-800 gap-2"}>
|
|
144
|
-
<Typography variant={"subtitle2"} className={"uppercase"}>
|
|
176
|
+
<Typography variant={"subtitle2"} className={"uppercase"}>{t("no_collections_found")}</Typography>
|
|
145
177
|
<Typography>
|
|
146
|
-
|
|
147
|
-
database data, import from files, or use our templates.
|
|
178
|
+
{t("start_building_collections")}
|
|
148
179
|
</Typography>
|
|
149
180
|
{canCreateCollections && <Button
|
|
150
181
|
onClick={collectionEditorController && canCreateCollections
|
|
@@ -154,10 +185,10 @@ export function IntroWidget() {
|
|
|
154
185
|
sourceClick: "new_collection_card"
|
|
155
186
|
})
|
|
156
187
|
: undefined}>
|
|
157
|
-
<AddIcon/>
|
|
188
|
+
<AddIcon />{t("create_first_collection")}
|
|
158
189
|
</Button>}
|
|
159
190
|
<Typography color={"secondary"}>
|
|
160
|
-
|
|
191
|
+
{t("define_collections_programmatically")}
|
|
161
192
|
</Typography>
|
|
162
193
|
</Paper>
|
|
163
194
|
);
|