@firecms/collection_editor 3.0.0-alpha.5 → 3.0.0-alpha.51

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 (140) hide show
  1. package/dist/ConfigControllerProvider.d.ts +36 -0
  2. package/dist/index.d.ts +11 -0
  3. package/dist/index.es.js +6995 -0
  4. package/dist/index.es.js.map +1 -0
  5. package/dist/index.umd.js +4 -0
  6. package/dist/index.umd.js.map +1 -0
  7. package/dist/types/collection_editor_controller.d.ts +35 -0
  8. package/dist/types/collection_inference.d.ts +2 -0
  9. package/dist/types/config_controller.d.ts +41 -0
  10. package/dist/types/config_permissions.d.ts +19 -0
  11. package/dist/types/persisted_collection.d.ts +6 -0
  12. package/dist/ui/CollectionViewHeaderAction.d.ts +10 -0
  13. package/dist/ui/EditorCollectionAction.d.ts +2 -0
  14. package/dist/ui/HomePageEditorCollectionAction.d.ts +2 -0
  15. package/dist/ui/MissingReferenceWidget.d.ts +3 -0
  16. package/dist/ui/NewCollectionCard.d.ts +2 -0
  17. package/dist/ui/PropertyAddColumnComponent.d.ts +6 -0
  18. package/dist/ui/RootCollectionSuggestions.d.ts +1 -0
  19. package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +9 -0
  20. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +38 -0
  21. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +15 -0
  22. package/dist/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +20 -0
  23. package/dist/ui/collection_editor/CollectionYupValidation.d.ts +14 -0
  24. package/dist/ui/collection_editor/EntityCustomViewsSelectDialog.d.ts +4 -0
  25. package/dist/ui/collection_editor/EnumForm.d.ts +13 -0
  26. package/dist/ui/collection_editor/GetCodeDialog.d.ts +5 -0
  27. package/dist/ui/collection_editor/PropertyEditView.d.ts +40 -0
  28. package/dist/ui/collection_editor/PropertyFieldPreview.d.ts +15 -0
  29. package/dist/ui/collection_editor/PropertySelectItem.d.ts +8 -0
  30. package/dist/ui/collection_editor/PropertyTree.d.ts +32 -0
  31. package/dist/ui/collection_editor/SelectIcons.d.ts +6 -0
  32. package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +12 -0
  33. package/dist/ui/collection_editor/UnsavedChangesDialog.d.ts +9 -0
  34. package/dist/ui/collection_editor/import/CollectionEditorImportDataPreview.d.ts +7 -0
  35. package/dist/ui/collection_editor/import/CollectionEditorImportMapping.d.ts +7 -0
  36. package/dist/ui/collection_editor/import/clean_import_data.d.ts +7 -0
  37. package/dist/ui/collection_editor/properties/BlockPropertyField.d.ts +8 -0
  38. package/dist/ui/collection_editor/properties/BooleanPropertyField.d.ts +3 -0
  39. package/dist/ui/collection_editor/properties/CommonPropertyFields.d.ts +10 -0
  40. package/dist/ui/collection_editor/properties/DateTimePropertyField.d.ts +3 -0
  41. package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +8 -0
  42. package/dist/ui/collection_editor/properties/FieldHelperView.d.ts +4 -0
  43. package/dist/ui/collection_editor/properties/KeyValuePropertyField.d.ts +3 -0
  44. package/dist/ui/collection_editor/properties/MapPropertyField.d.ts +8 -0
  45. package/dist/ui/collection_editor/properties/NumberPropertyField.d.ts +3 -0
  46. package/dist/ui/collection_editor/properties/ReferencePropertyField.d.ts +13 -0
  47. package/dist/ui/collection_editor/properties/RepeatPropertyField.d.ts +10 -0
  48. package/dist/ui/collection_editor/properties/StoragePropertyField.d.ts +5 -0
  49. package/dist/ui/collection_editor/properties/StringPropertyField.d.ts +5 -0
  50. package/dist/ui/collection_editor/properties/UrlPropertyField.d.ts +4 -0
  51. package/dist/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.d.ts +3 -0
  52. package/dist/ui/collection_editor/properties/validation/ArrayPropertyValidation.d.ts +5 -0
  53. package/dist/ui/collection_editor/properties/validation/GeneralPropertyValidation.d.ts +4 -0
  54. package/dist/ui/collection_editor/properties/validation/NumberPropertyValidation.d.ts +3 -0
  55. package/dist/ui/collection_editor/properties/validation/StringPropertyValidation.d.ts +11 -0
  56. package/dist/ui/collection_editor/properties/validation/ValidationPanel.d.ts +2 -0
  57. package/dist/ui/collection_editor/templates/blog_template.d.ts +2 -0
  58. package/dist/ui/collection_editor/templates/products_template.d.ts +2 -0
  59. package/dist/ui/collection_editor/templates/users_template.d.ts +2 -0
  60. package/dist/ui/collection_editor/util.d.ts +4 -0
  61. package/dist/ui/collection_editor/utils/strings.d.ts +1 -0
  62. package/dist/ui/collection_editor/utils/supported_fields.d.ts +3 -0
  63. package/dist/ui/collection_editor/utils/update_property_for_widget.d.ts +2 -0
  64. package/dist/ui/collection_editor/utils/useTraceUpdate.d.ts +1 -0
  65. package/dist/useCollectionEditorController.d.ts +6 -0
  66. package/dist/useCollectionEditorPlugin.d.ts +45 -0
  67. package/dist/useCollectionsConfigController.d.ts +6 -0
  68. package/dist/utils/arrays.d.ts +1 -0
  69. package/dist/utils/entities.d.ts +3 -0
  70. package/dist/utils/icons.d.ts +1 -0
  71. package/dist/utils/synonyms.d.ts +1951 -0
  72. package/package.json +26 -23
  73. package/src/ConfigControllerProvider.tsx +321 -0
  74. package/src/index.ts +35 -0
  75. package/src/types/collection_editor_controller.tsx +42 -0
  76. package/src/types/collection_inference.ts +3 -0
  77. package/src/types/config_controller.tsx +50 -0
  78. package/src/types/config_permissions.ts +20 -0
  79. package/src/types/persisted_collection.ts +9 -0
  80. package/src/ui/CollectionViewHeaderAction.tsx +42 -0
  81. package/src/ui/EditorCollectionAction.tsx +95 -0
  82. package/src/ui/HomePageEditorCollectionAction.tsx +88 -0
  83. package/src/ui/MissingReferenceWidget.tsx +34 -0
  84. package/src/ui/NewCollectionCard.tsx +46 -0
  85. package/src/ui/PropertyAddColumnComponent.tsx +41 -0
  86. package/src/ui/RootCollectionSuggestions.tsx +62 -0
  87. package/src/ui/collection_editor/CollectionDetailsForm.tsx +353 -0
  88. package/src/ui/collection_editor/CollectionEditorDialog.tsx +744 -0
  89. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +212 -0
  90. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +480 -0
  91. package/src/ui/collection_editor/CollectionYupValidation.tsx +7 -0
  92. package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +36 -0
  93. package/src/ui/collection_editor/EnumForm.tsx +356 -0
  94. package/src/ui/collection_editor/GetCodeDialog.tsx +118 -0
  95. package/src/ui/collection_editor/PropertyEditView.tsx +565 -0
  96. package/src/ui/collection_editor/PropertyFieldPreview.tsx +201 -0
  97. package/src/ui/collection_editor/PropertySelectItem.tsx +31 -0
  98. package/src/ui/collection_editor/PropertyTree.tsx +238 -0
  99. package/src/ui/collection_editor/SelectIcons.tsx +72 -0
  100. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +252 -0
  101. package/src/ui/collection_editor/UnsavedChangesDialog.tsx +47 -0
  102. package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +37 -0
  103. package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +275 -0
  104. package/src/ui/collection_editor/import/clean_import_data.ts +53 -0
  105. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +134 -0
  106. package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +36 -0
  107. package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +111 -0
  108. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +86 -0
  109. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +116 -0
  110. package/src/ui/collection_editor/properties/FieldHelperView.tsx +13 -0
  111. package/src/ui/collection_editor/properties/KeyValuePropertyField.tsx +20 -0
  112. package/src/ui/collection_editor/properties/MapPropertyField.tsx +157 -0
  113. package/src/ui/collection_editor/properties/NumberPropertyField.tsx +38 -0
  114. package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +184 -0
  115. package/src/ui/collection_editor/properties/RepeatPropertyField.tsx +107 -0
  116. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +194 -0
  117. package/src/ui/collection_editor/properties/StringPropertyField.tsx +79 -0
  118. package/src/ui/collection_editor/properties/UrlPropertyField.tsx +89 -0
  119. package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +36 -0
  120. package/src/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +50 -0
  121. package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +49 -0
  122. package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +99 -0
  123. package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +131 -0
  124. package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +28 -0
  125. package/src/ui/collection_editor/templates/blog_template.ts +115 -0
  126. package/src/ui/collection_editor/templates/products_template.ts +88 -0
  127. package/src/ui/collection_editor/templates/users_template.ts +34 -0
  128. package/src/ui/collection_editor/util.ts +21 -0
  129. package/src/ui/collection_editor/utils/strings.ts +8 -0
  130. package/src/ui/collection_editor/utils/supported_fields.tsx +29 -0
  131. package/src/ui/collection_editor/utils/update_property_for_widget.ts +271 -0
  132. package/src/ui/collection_editor/utils/useTraceUpdate.tsx +23 -0
  133. package/src/useCollectionEditorController.tsx +9 -0
  134. package/src/useCollectionEditorPlugin.tsx +128 -0
  135. package/src/useCollectionsConfigController.tsx +9 -0
  136. package/src/utils/arrays.ts +3 -0
  137. package/src/utils/entities.ts +38 -0
  138. package/src/utils/icons.ts +17 -0
  139. package/src/utils/synonyms.ts +1952 -0
  140. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,38 @@
1
+ import React from "react";
2
+ import { NumberPropertyValidation } from "./validation/NumberPropertyValidation";
3
+ import { ValidationPanel } from "./validation/ValidationPanel";
4
+ import { TextField } from "@firecms/core";
5
+ import { getIn, useFormikContext } from "formik";
6
+
7
+ export function NumberPropertyField({ disabled }: {
8
+ disabled: boolean;
9
+ }) {
10
+
11
+ const { values, setFieldValue } = useFormikContext();
12
+
13
+ return (
14
+ <>
15
+
16
+ <div className={"col-span-12"}>
17
+
18
+ <ValidationPanel>
19
+ <NumberPropertyValidation disabled={disabled}/>
20
+ </ValidationPanel>
21
+
22
+ </div>
23
+
24
+ <div className={"col-span-12"}>
25
+
26
+ <TextField name={"defaultValue"}
27
+ disabled={disabled}
28
+ type={"number"}
29
+ onChange={(e: any) => {
30
+ setFieldValue("defaultValue", e.target.value === "" ? undefined : parseFloat(e.target.value));
31
+ }}
32
+ label={"Default value"}
33
+ value={getIn(values, "defaultValue") ?? ""}/>
34
+
35
+ </div>
36
+ </>
37
+ );
38
+ }
@@ -0,0 +1,184 @@
1
+ import React from "react";
2
+ import { Field, getIn, useFormikContext } from "formik";
3
+ import {
4
+ CircularProgress,
5
+ getIconForView,
6
+ NumberProperty,
7
+ Select,
8
+ SelectGroup,
9
+ SelectItem,
10
+ StringProperty,
11
+ Typography,
12
+ useNavigationController
13
+ } from "@firecms/core";
14
+ import { FieldHelperView } from "./FieldHelperView";
15
+
16
+ export function ReferencePropertyField({
17
+ existing,
18
+ multiple,
19
+ disabled,
20
+ showErrors
21
+ }: { existing: boolean, multiple: boolean, disabled: boolean, showErrors: boolean }) {
22
+
23
+ const {
24
+ values,
25
+ handleChange,
26
+ errors,
27
+ touched,
28
+ setFieldError,
29
+ setFieldValue
30
+ } = useFormikContext<StringProperty | NumberProperty>();
31
+
32
+ const navigation = useNavigationController();
33
+
34
+ if (!navigation)
35
+ return <div className={"col-span-12"}>
36
+ <CircularProgress/>
37
+ </div>;
38
+
39
+ const pathPath = multiple ? "of.path" : "path";
40
+ const pathValue: string | undefined = getIn(values, pathPath);
41
+ const pathError: string | undefined = showErrors && getIn(errors, pathPath);
42
+
43
+ console.log("pathError", errors, pathError)
44
+
45
+ return (
46
+ <>
47
+ <div className={"col-span-12"}>
48
+ <Field required
49
+ name={pathPath}
50
+ pathPath={pathPath}
51
+ type="select"
52
+ validate={validatePath}
53
+ disabled={existing || disabled}
54
+ value={pathValue}
55
+ error={pathError}
56
+ handleChange={handleChange}
57
+ component={CollectionsSelect}/>
58
+
59
+ </div>
60
+
61
+ </>
62
+ );
63
+ }
64
+
65
+ function validatePath(value?: string) {
66
+ let error;
67
+ if (!value) {
68
+ error = "You must specify a target collection for the field";
69
+ }
70
+ return error;
71
+ }
72
+
73
+ export function CollectionsSelect({
74
+ disabled,
75
+ pathPath,
76
+ value,
77
+ handleChange,
78
+ error,
79
+ ...props
80
+ }: {
81
+ disabled: boolean,
82
+ pathPath: string,
83
+ value?: string,
84
+ handleChange: (event: any) => void,
85
+ error?: string
86
+ }) {
87
+
88
+ console.log("error", error)
89
+
90
+ const navigation = useNavigationController();
91
+
92
+ if (!navigation)
93
+ return <div className={"col-span-12"}>
94
+ <CircularProgress/>
95
+ </div>;
96
+
97
+ const collections = navigation?.collections ?? [];
98
+
99
+ const groups: string[] = Array.from(new Set(
100
+ Object.values(collections).map(e => e.group).filter(Boolean) as string[]
101
+ ).values());
102
+
103
+ const ungroupedCollections = collections.filter((col) => !col.group);
104
+
105
+ return (
106
+ <>
107
+ <Select
108
+ error={Boolean(error)}
109
+ disabled={disabled}
110
+ value={value ?? ""}
111
+ position={"item-aligned"}
112
+ name={pathPath}
113
+ onChange={handleChange}
114
+ label={"Target collection"}
115
+ renderValue={(selected) => {
116
+ const selectedCollection = collections.find(collection => collection.id === selected || collection.path === selected);
117
+ if (!selectedCollection) return null;
118
+ const collectionIcon = getIconForView(selectedCollection);
119
+ return (
120
+ <div className="flex flex-row">
121
+ {collectionIcon}
122
+ <Typography
123
+ variant={"subtitle2"}
124
+ className="font-medium ml-4">
125
+ {selectedCollection?.name.toUpperCase()}
126
+ </Typography>
127
+ </div>)
128
+ }}
129
+ {...props}>
130
+
131
+ {groups.flatMap((group) => (
132
+ <SelectGroup label={group || "Views"}
133
+ key={`group_${group}`}>
134
+ {
135
+ collections.filter(collection => collection.group === group)
136
+ .map((collection) => {
137
+ const collectionIcon = getIconForView(collection);
138
+ return <SelectItem
139
+ key={`${collection.id ?? collection.path}-${group}`}
140
+ value={collection.id ?? collection.path}>
141
+ <div className="flex flex-row">
142
+ {collectionIcon}
143
+ <Typography
144
+ variant={"subtitle2"}
145
+ className="font-medium ml-4">
146
+ {collection?.name.toUpperCase()}
147
+ </Typography>
148
+ </div>
149
+ </SelectItem>;
150
+ })
151
+
152
+ }
153
+ </SelectGroup>
154
+ ))}
155
+
156
+ {ungroupedCollections && <SelectGroup label={"Views"}>
157
+ {ungroupedCollections
158
+ .map((collection) => {
159
+ const collectionIcon = getIconForView(collection);
160
+ return <SelectItem key={collection.id ?? collection.path}
161
+ value={collection.id ?? collection.path}>
162
+ <div className="flex flex-row">
163
+ {collectionIcon}
164
+ <Typography
165
+ variant={"subtitle2"}
166
+ className="font-medium ml-4">
167
+ {collection?.name.toUpperCase()}
168
+ </Typography>
169
+ </div>
170
+ </SelectItem>;
171
+ })
172
+
173
+ }
174
+ </SelectGroup>}
175
+
176
+ </Select>
177
+
178
+ <FieldHelperView>
179
+ You can only edit the reference collection upon field
180
+ creation.
181
+ </FieldHelperView>
182
+ </>
183
+ );
184
+ }
@@ -0,0 +1,107 @@
1
+ import React, { useCallback, useState } from "react";
2
+ import { ArrayProperty, Button, getFieldConfig, Paper, Property, PropertyConfig, Typography } from "@firecms/core";
3
+ import { Field, getIn, useFormikContext } from "formik";
4
+ import { PropertyFormDialog } from "../PropertyEditView";
5
+ import { PropertyFieldPreview } from "../PropertyFieldPreview";
6
+ import { ArrayPropertyValidation } from "./validation/ArrayPropertyValidation";
7
+ import { ValidationPanel } from "./validation/ValidationPanel";
8
+
9
+ export function RepeatPropertyField({
10
+ showErrors,
11
+ existing,
12
+ disabled,
13
+ getData,
14
+ allowDataInference,
15
+ propertyConfigs,
16
+ collectionEditable
17
+ }: {
18
+ showErrors: boolean,
19
+ existing: boolean,
20
+ disabled: boolean,
21
+ getData?: () => Promise<object[]>;
22
+ allowDataInference: boolean;
23
+ propertyConfigs: Record<string, PropertyConfig>,
24
+ collectionEditable: boolean;
25
+ }) {
26
+
27
+ const {
28
+ values,
29
+ handleChange,
30
+ errors,
31
+ setFieldValue,
32
+ touched
33
+ } = useFormikContext<ArrayProperty>();
34
+
35
+ const [propertyDialogOpen, setPropertyDialogOpen] = useState(false);
36
+ const ofProperty = getIn(values, "of");
37
+ const ofPropertyError = getIn(touched, "of") && getIn(errors, "of");
38
+
39
+ const onPropertyChanged = useCallback(({ id, property, namespace }:
40
+ { id?: string, property: Property, namespace?: string }) => {
41
+ setFieldValue("of", property);
42
+ }, []);
43
+
44
+ const widget = ofProperty && getFieldConfig(ofProperty, propertyConfigs);
45
+ return (
46
+ <>
47
+ <div className={"col-span-12"}>
48
+ <Typography variant={"subtitle2"}>
49
+ Repeat component
50
+ </Typography>
51
+ <Field
52
+ name={"of"}
53
+ value={ofProperty}
54
+ validate={(property: Property) => {
55
+ return property?.dataType ? undefined : "You need to specify a repeat field";
56
+ }}
57
+ >
58
+ {() => (
59
+ <Paper className="p-2 mt-4">
60
+
61
+ {ofProperty && <PropertyFieldPreview
62
+ property={ofProperty}
63
+ onClick={disabled ? undefined : () => setPropertyDialogOpen(true)}
64
+ includeName={false}
65
+ includeEditButton={true}
66
+ selected={false}
67
+ hasError={false}/>}
68
+
69
+ {!disabled && !ofProperty && <Button variant={"text"}
70
+ size={"large"}
71
+ color={ofPropertyError ? "error" : "primary"}
72
+ onClick={() => setPropertyDialogOpen(true)}>
73
+ Edit {`${widget ? widget.name : "repeat component"}`}
74
+ </Button>}
75
+
76
+ <PropertyFormDialog
77
+ inArray={true}
78
+ open={propertyDialogOpen}
79
+ existingProperty={existing}
80
+ getData={getData}
81
+ autoUpdateId={!existing}
82
+ autoOpenTypeSelect={!existing}
83
+ onOkClicked={() => setPropertyDialogOpen(false)}
84
+ allowDataInference={allowDataInference}
85
+ property={ofProperty}
86
+ includeIdAndName={false}
87
+ onPropertyChanged={onPropertyChanged}
88
+ forceShowErrors={showErrors}
89
+ propertyConfigs={propertyConfigs}
90
+ collectionEditable={collectionEditable}
91
+ />
92
+ </Paper>
93
+ )}
94
+ </Field>
95
+
96
+ </div>
97
+
98
+ <div className={"col-span-12"}>
99
+
100
+ <ValidationPanel>
101
+ <ArrayPropertyValidation disabled={disabled}/>
102
+ </ValidationPanel>
103
+
104
+ </div>
105
+ </>
106
+ );
107
+ }
@@ -0,0 +1,194 @@
1
+ import React from "react";
2
+ import {
3
+ Button,
4
+ Checkbox,
5
+ DebouncedTextField,
6
+ ExpandablePanel,
7
+ FileUploadIcon,
8
+ MultiSelect,
9
+ MultiSelectItem,
10
+ SwitchControl,
11
+ Typography
12
+ } from "@firecms/core";
13
+
14
+ import { Field, getIn, useFormikContext } from "formik";
15
+ import { GeneralPropertyValidation } from "./validation/GeneralPropertyValidation";
16
+ import { ArrayPropertyValidation } from "./validation/ArrayPropertyValidation";
17
+ import { ValidationPanel } from "./validation/ValidationPanel";
18
+
19
+ const fileTypes: Record<string, string> = {
20
+ "image/*": "Images",
21
+ "video/*": "Videos",
22
+ "audio/*": "Audio files",
23
+ "application/*": "Files (pdf, zip, csv, excel...)",
24
+ "text/*": "Text files"
25
+ }
26
+
27
+ export function StoragePropertyField({
28
+ multiple,
29
+ existing,
30
+ disabled
31
+ }: {
32
+ multiple: boolean;
33
+ existing: boolean;
34
+ disabled: boolean;
35
+ }) {
36
+
37
+ const {
38
+ values,
39
+ setFieldValue
40
+ } = useFormikContext();
41
+
42
+ const baseStoragePath = multiple ? "of.storage" : "storage";
43
+ const acceptedFiles = `${baseStoragePath}.acceptedFiles`;
44
+
45
+ const metadata = `${baseStoragePath}.metadata`;
46
+ const fileName = `${baseStoragePath}.fileName`;
47
+ const storagePath = `${baseStoragePath}.storagePath`;
48
+ const storeUrl = `${baseStoragePath}.storeUrl`;
49
+
50
+ const fileNameValue = getIn(values, fileName) ?? "{rand}_{file}";
51
+ const storagePathValue = getIn(values, storagePath) ?? "/";
52
+
53
+ const storedValue = getIn(values, acceptedFiles);
54
+ const fileTypesValue: string[] | undefined = Array.isArray(storedValue) ? storedValue : undefined;
55
+ const allFileTypesSelected = !fileTypesValue || fileTypesValue.length === 0;
56
+
57
+ const handleTypesChange = (value: string[]) => {
58
+ if (!value) setFieldValue(acceptedFiles, undefined);
59
+ else if (value.includes("all")) setFieldValue(acceptedFiles, undefined);
60
+ else if (value.length >= Object.keys(fileTypes).length) setFieldValue(acceptedFiles, undefined);
61
+ else if (allFileTypesSelected)
62
+ setFieldValue(acceptedFiles, Object.keys(fileTypes).filter((v) => !value.includes(v)));
63
+ else setFieldValue(acceptedFiles, value);
64
+ };
65
+
66
+ const hasFilenameCallback = typeof fileNameValue === "function";
67
+ const hasStoragePathCallback = typeof storagePathValue === "function";
68
+
69
+ return (
70
+ <>
71
+
72
+ <div className={"col-span-12"}>
73
+
74
+ <ExpandablePanel
75
+ title={
76
+ <div className="flex flex-row text-gray-500">
77
+ <FileUploadIcon/>
78
+ <Typography variant={"subtitle2"}
79
+ className="ml-2">
80
+ File upload config
81
+ </Typography>
82
+ </div>
83
+ }>
84
+
85
+ <div className={"grid grid-cols-12 gap-2 p-4"}>
86
+
87
+ <div className={"col-span-12"}>
88
+
89
+ <MultiSelect
90
+ disabled={disabled}
91
+ name={acceptedFiles}
92
+ value={fileTypesValue ?? []}
93
+ onMultiValueChange={handleTypesChange}
94
+ label={allFileTypesSelected ? undefined : "Allowed file types"}
95
+ renderValues={(selected) => {
96
+ if (!selected || selected.length === 0) return "All file types allowed";
97
+ return selected.map((v: string) => fileTypes[v])
98
+ .filter((v: string) => Boolean(v))
99
+ .join(", ");
100
+ }}>
101
+
102
+ <MultiSelectItem key={"all"} value={"all"} className={"flex items-center gap-2"}>
103
+ <Checkbox
104
+ checked={!fileTypesValue}/>
105
+ All
106
+ </MultiSelectItem>
107
+
108
+ {Object.entries(fileTypes).map(([value, label]) => (
109
+ <MultiSelectItem key={value} value={value} className={"flex items-center gap-2"}>
110
+ <Checkbox
111
+ checked={allFileTypesSelected || fileTypesValue.indexOf(value) > -1}/>
112
+ <div className={"flex-grow"}>
113
+ {label}
114
+ </div>
115
+ <Button size={"small"}
116
+ variant={"outlined"}
117
+ onClick={(e) => {
118
+ e.preventDefault();
119
+ e.stopPropagation();
120
+ return setFieldValue(acceptedFiles, [value]);
121
+ }}>
122
+ Only
123
+ </Button>
124
+ </MultiSelectItem>
125
+ ))}
126
+
127
+ </MultiSelect>
128
+ </div>
129
+
130
+ <div className={"col-span-12"}>
131
+ <Field name={fileName}
132
+ as={DebouncedTextField}
133
+ label={"File name"}
134
+ size={"small"}
135
+ disabled={hasFilenameCallback || disabled}
136
+ value={hasFilenameCallback ? "-" : fileNameValue}
137
+ />
138
+ </div>
139
+ <div className={"col-span-12"}>
140
+ <Field name={storagePath}
141
+ as={DebouncedTextField}
142
+ label={"Storage path"}
143
+ disabled={hasStoragePathCallback || disabled}
144
+ size={"small"}
145
+ value={hasStoragePathCallback ? "-" : storagePathValue}
146
+ />
147
+ <Typography variant={"caption"} className={"ml-3.5 mt-1 mb-2"}>
148
+ <p>You can use the following placeholders in
149
+ the file name
150
+ and storage path values:</p>
151
+ <ul>
152
+ <li>{"{file} - Full name of the uploaded file"}</li>
153
+ <li>{"{file.name} - Name of the uploaded file without extension"}</li>
154
+ <li>{"{file.ext} - Extension of the uploaded file"}</li>
155
+ <li>{"{entityId} - ID of the entity"}</li>
156
+ <li>{"{propertyKey} - ID of this field"}</li>
157
+ <li>{"{path} - Path of this entity"}</li>
158
+ <li>{"{rand} - Random value used to avoid name collisions"}</li>
159
+ </ul>
160
+ </Typography>
161
+ <Field type="checkbox"
162
+ name={storeUrl}
163
+ label={"Save URL instead of storage path"}
164
+ disabled={existing || disabled}
165
+ component={SwitchControl}/>
166
+ <br/>
167
+ <Typography variant={"caption"} className={"ml-3.5 mt-1 mb-2"}>
168
+ Turn this setting on, if you prefer to save
169
+ the download
170
+ URL of the uploaded file instead of the
171
+ storage path.
172
+ You can only change this prop upon creation.
173
+ </Typography>
174
+ </div>
175
+ </div>
176
+ </ExpandablePanel>
177
+
178
+ </div>
179
+
180
+ <div className={"col-span-12"}>
181
+
182
+ <ValidationPanel>
183
+ {!multiple && <div className={"grid grid-cols-12 gap-2"}>
184
+ <GeneralPropertyValidation disabled={disabled}/>
185
+ </div>}
186
+ {multiple && <div className={"col-span-12"}>
187
+ <ArrayPropertyValidation disabled={disabled}/>
188
+ </div>}
189
+ </ValidationPanel>
190
+
191
+ </div>
192
+ </>
193
+ );
194
+ }
@@ -0,0 +1,79 @@
1
+ import React from "react";
2
+ import { StringPropertyValidation } from "./validation/StringPropertyValidation";
3
+ import { ValidationPanel } from "./validation/ValidationPanel";
4
+ import { getIn, useFormikContext } from "formik";
5
+
6
+ import { TextField } from "@firecms/core";
7
+
8
+ export function StringPropertyField({
9
+ widgetId,
10
+ disabled,
11
+ showErrors
12
+ }: {
13
+ widgetId: "text_field" | "multiline" | "markdown" | "email";
14
+ disabled: boolean;
15
+ showErrors: boolean;
16
+ }) {
17
+
18
+ const { values, setFieldValue } = useFormikContext();
19
+
20
+ return (
21
+ <>
22
+ <div className={"col-span-12"}>
23
+
24
+ <ValidationPanel>
25
+
26
+ {widgetId === "text_field" &&
27
+ <StringPropertyValidation disabled={disabled}
28
+ length={true}
29
+ lowercase={true}
30
+ matches={true}
31
+ max={true}
32
+ min={true}
33
+ trim={true}
34
+ uppercase={true}
35
+ showErrors={showErrors}/>}
36
+ {widgetId === "multiline" &&
37
+ <StringPropertyValidation disabled={disabled}
38
+ length={true}
39
+ lowercase={true}
40
+ max={true}
41
+ min={true}
42
+ trim={true}
43
+ uppercase={true}
44
+ showErrors={showErrors}/>}
45
+ {widgetId === "markdown" &&
46
+ <StringPropertyValidation disabled={disabled}
47
+ length={true}
48
+ lowercase={true}
49
+ max={true}
50
+ min={true}
51
+ trim={true}
52
+ uppercase={true}
53
+ showErrors={showErrors}/>}
54
+
55
+ {widgetId === "email" &&
56
+ <StringPropertyValidation disabled={disabled}
57
+ max={true}
58
+ min={true}
59
+ trim={true}
60
+ showErrors={showErrors}/>}
61
+
62
+ </ValidationPanel>
63
+
64
+ </div>
65
+
66
+ <div className={"col-span-12"}>
67
+
68
+ <TextField name={"defaultValue"}
69
+ disabled={disabled}
70
+ onChange={(e: any) => {
71
+ setFieldValue("defaultValue", e.target.value === "" ? undefined : e.target.value);
72
+ }}
73
+ label={"Default value"}
74
+ value={getIn(values, "defaultValue") ?? ""}/>
75
+
76
+ </div>
77
+ </>
78
+ );
79
+ }