@firecms/core 3.0.0-beta.11 → 3.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ArrayContainer.d.ts +7 -3
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +2 -2
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +15 -1
- package/dist/components/EntityCollectionTable/index.d.ts +1 -1
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +4 -0
- package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
- package/dist/components/SelectableTable/SelectableTable.d.ts +12 -2
- package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +1 -1
- package/dist/components/UnsavedChangesDialog.d.ts +8 -0
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -0
- package/dist/components/common/default_entity_actions.d.ts +0 -2
- package/dist/components/common/index.d.ts +1 -1
- package/dist/components/common/useColumnsIds.d.ts +1 -0
- package/dist/components/common/{useDataSourceEntityCollectionTableController.d.ts → useDataSourceTableController.d.ts} +10 -2
- package/dist/components/common/useDebouncedCallback.d.ts +1 -0
- package/dist/components/common/useScrollRestoration.d.ts +14 -0
- package/dist/contexts/BreacrumbsContext.d.ts +8 -0
- package/dist/core/EntityEditView.d.ts +29 -21
- package/dist/core/EntityEditViewFormActions.d.ts +2 -0
- package/dist/core/FireCMSRouter.d.ts +4 -0
- package/dist/core/NavigationRoutes.d.ts +0 -1
- package/dist/core/SideDialogs.d.ts +4 -2
- package/dist/core/index.d.ts +2 -1
- package/dist/form/EntityForm.d.ts +45 -0
- package/dist/form/EntityFormActions.d.ts +17 -0
- package/dist/form/PropertyFieldBinding.d.ts +1 -1
- package/dist/form/components/FormEntry.d.ts +6 -0
- package/dist/form/components/FormLayout.d.ts +5 -0
- package/dist/form/components/index.d.ts +2 -0
- package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/BlockFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/RepeatFieldBinding.d.ts +1 -1
- package/dist/form/index.d.ts +16 -16
- package/dist/hooks/data/useEntityFetch.d.ts +2 -1
- package/dist/hooks/useBreadcrumbsController.d.ts +26 -0
- package/dist/hooks/useBuildNavigationController.d.ts +4 -1
- package/dist/hooks/useModeController.d.ts +1 -2
- package/dist/index.es.js +18213 -16819
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +18164 -16771
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildSideEntityController.d.ts +2 -2
- package/dist/internal/useUnsavedChangesDialog.d.ts +7 -9
- package/dist/routes/CustomCMSRoute.d.ts +4 -0
- package/dist/routes/FireCMSRoute.d.ts +1 -0
- package/dist/routes/HomePageRoute.d.ts +3 -0
- package/dist/types/collections.d.ts +30 -10
- package/dist/types/datasource.d.ts +2 -2
- package/dist/types/dialogs_controller.d.ts +7 -3
- package/dist/types/entities.d.ts +1 -1
- package/dist/types/entity_actions.d.ts +10 -0
- package/dist/types/fields.d.ts +9 -2
- package/dist/types/navigation.d.ts +29 -12
- package/dist/types/plugins.d.ts +1 -0
- package/dist/types/properties.d.ts +18 -3
- package/dist/types/side_entity_controller.d.ts +6 -1
- package/dist/util/builders.d.ts +1 -1
- package/dist/util/entity_actions.d.ts +2 -0
- package/dist/util/entity_cache.d.ts +23 -0
- package/dist/util/index.d.ts +1 -0
- package/dist/util/navigation_from_path.d.ts +6 -1
- package/dist/util/navigation_utils.d.ts +12 -1
- package/dist/util/resolutions.d.ts +6 -1
- package/package.json +19 -21
- package/src/components/ArrayContainer.tsx +48 -29
- package/src/components/CircularProgressCenter.tsx +1 -1
- package/src/components/DeleteEntityDialog.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +40 -19
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +10 -4
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +18 -1
- package/src/components/EntityCollectionTable/index.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +5 -11
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +83 -41
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +4 -2
- package/src/components/NotFoundPage.tsx +2 -2
- package/src/components/PropertyIdCopyTooltip.tsx +2 -3
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +11 -6
- package/src/components/SelectableTable/SelectableTable.tsx +18 -3
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +7 -7
- package/src/components/UnsavedChangesDialog.tsx +42 -0
- package/src/components/VirtualTable/VirtualTable.tsx +19 -2
- package/src/components/VirtualTable/VirtualTableProps.tsx +15 -0
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +1 -1
- package/src/components/common/default_entity_actions.tsx +26 -37
- package/src/components/common/index.ts +1 -1
- package/src/components/common/useColumnsIds.tsx +1 -1
- package/src/components/common/useDataSourceTableController.tsx +420 -0
- package/src/components/common/useDebouncedCallback.tsx +20 -0
- package/src/components/common/useScrollRestoration.tsx +68 -0
- package/src/contexts/BreacrumbsContext.tsx +38 -0
- package/src/contexts/DialogsProvider.tsx +3 -2
- package/src/contexts/ModeController.tsx +1 -3
- package/src/core/DefaultAppBar.tsx +44 -14
- package/src/core/DefaultDrawer.tsx +1 -1
- package/src/core/EntityEditView.tsx +278 -1000
- package/src/core/EntityEditViewFormActions.tsx +199 -0
- package/src/core/EntitySidePanel.tsx +85 -15
- package/src/core/FireCMS.tsx +7 -4
- package/src/core/FireCMSRouter.tsx +17 -0
- package/src/core/NavigationRoutes.tsx +23 -32
- package/src/core/SideDialogs.tsx +20 -11
- package/src/core/index.tsx +4 -2
- package/src/form/EntityForm.tsx +774 -0
- package/src/form/EntityFormActions.tsx +169 -0
- package/src/form/PropertyFieldBinding.tsx +13 -11
- package/src/form/components/FormEntry.tsx +22 -0
- package/src/form/components/FormLayout.tsx +16 -0
- package/src/form/components/LabelWithIcon.tsx +6 -3
- package/src/form/components/StorageUploadProgress.tsx +1 -1
- package/src/form/components/index.tsx +2 -0
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +4 -4
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +4 -2
- package/src/form/field_bindings/BlockFieldBinding.tsx +4 -2
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -0
- package/src/form/field_bindings/MapFieldBinding.tsx +14 -16
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +9 -6
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +2 -2
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -1
- package/src/form/field_bindings/RepeatFieldBinding.tsx +5 -2
- package/src/form/field_bindings/SelectFieldBinding.tsx +1 -1
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +6 -4
- package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -0
- package/src/form/field_bindings/TextFieldBinding.tsx +1 -0
- package/src/form/index.tsx +16 -32
- package/src/form/validation.ts +12 -6
- package/src/hooks/data/save.ts +1 -1
- package/src/hooks/data/useCollectionFetch.tsx +1 -1
- package/src/hooks/data/useEntityFetch.tsx +5 -1
- package/src/hooks/useBreadcrumbsController.tsx +31 -0
- package/src/hooks/useBuildModeController.tsx +15 -28
- package/src/hooks/useBuildNavigationController.tsx +70 -24
- package/src/hooks/useLargeLayout.tsx +0 -35
- package/src/hooks/useModeController.tsx +1 -2
- package/src/hooks/useResolvedNavigationFrom.tsx +4 -6
- package/src/internal/useBuildSideDialogsController.tsx +3 -2
- package/src/internal/useBuildSideEntityController.tsx +124 -83
- package/src/internal/useUnsavedChangesDialog.tsx +126 -92
- package/src/preview/PropertyPreview.tsx +8 -8
- package/src/preview/components/UrlComponentPreview.tsx +17 -18
- package/src/preview/property_previews/MapPropertyPreview.tsx +3 -2
- package/src/routes/CustomCMSRoute.tsx +21 -0
- package/src/routes/FireCMSRoute.tsx +235 -0
- package/src/routes/HomePageRoute.tsx +17 -0
- package/src/types/collections.ts +38 -13
- package/src/types/datasource.ts +2 -1
- package/src/types/dialogs_controller.tsx +7 -3
- package/src/types/entities.ts +1 -1
- package/src/types/entity_actions.tsx +12 -0
- package/src/types/fields.tsx +13 -2
- package/src/types/navigation.ts +36 -16
- package/src/types/plugins.tsx +1 -0
- package/src/types/properties.ts +21 -3
- package/src/types/side_dialogs_controller.tsx +2 -0
- package/src/types/side_entity_controller.tsx +6 -1
- package/src/util/builders.ts +5 -3
- package/src/util/entity_actions.ts +28 -0
- package/src/util/entity_cache.ts +204 -0
- package/src/util/index.ts +1 -0
- package/src/util/join_collections.ts +3 -0
- package/src/util/navigation_from_path.ts +13 -6
- package/src/util/navigation_utils.ts +53 -1
- package/src/util/objects.ts +4 -1
- package/src/util/parent_references_from_path.ts +3 -3
- package/src/util/resolutions.ts +26 -5
- package/src/util/useStorageUploadController.tsx +39 -21
- package/src/components/common/useDataSourceEntityCollectionTableController.tsx +0 -236
- /package/src/util/{common.tsx → common.ts} +0 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Entity, EntityAction, FireCMSContext, ResolvedEntityCollection, SideEntityController } from "../types";
|
|
3
|
+
import { Button, cls, defaultBorderMixin, DialogActions, IconButton, LoadingButton, Typography } from "@firecms/ui";
|
|
4
|
+
import { FormexController } from "@firecms/formex";
|
|
5
|
+
import { useFireCMSContext, useSideEntityController } from "../hooks";
|
|
6
|
+
|
|
7
|
+
export interface EntityFormActionsProps {
|
|
8
|
+
collection: ResolvedEntityCollection;
|
|
9
|
+
path: string;
|
|
10
|
+
entity?: Entity;
|
|
11
|
+
layout: "bottom" | "side";
|
|
12
|
+
savingError?: Error;
|
|
13
|
+
formex: FormexController<any>;
|
|
14
|
+
disabled: boolean;
|
|
15
|
+
status: "new" | "existing" | "copy";
|
|
16
|
+
pluginActions: React.ReactNode[];
|
|
17
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
18
|
+
showDefaultActions?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function EntityFormActions({
|
|
22
|
+
collection,
|
|
23
|
+
entity,
|
|
24
|
+
layout,
|
|
25
|
+
savingError,
|
|
26
|
+
formex,
|
|
27
|
+
disabled,
|
|
28
|
+
status,
|
|
29
|
+
pluginActions,
|
|
30
|
+
openEntityMode
|
|
31
|
+
}: EntityFormActionsProps) {
|
|
32
|
+
|
|
33
|
+
const context = useFireCMSContext();
|
|
34
|
+
const sideEntityController = useSideEntityController();
|
|
35
|
+
|
|
36
|
+
return layout === "bottom"
|
|
37
|
+
? buildBottomActions({
|
|
38
|
+
savingError,
|
|
39
|
+
entity,
|
|
40
|
+
collection,
|
|
41
|
+
context,
|
|
42
|
+
sideEntityController,
|
|
43
|
+
isSubmitting: formex.isSubmitting,
|
|
44
|
+
disabled,
|
|
45
|
+
status,
|
|
46
|
+
pluginActions,
|
|
47
|
+
openEntityMode
|
|
48
|
+
})
|
|
49
|
+
: buildSideActions({
|
|
50
|
+
savingError,
|
|
51
|
+
entity,
|
|
52
|
+
collection,
|
|
53
|
+
context,
|
|
54
|
+
sideEntityController,
|
|
55
|
+
isSubmitting: formex.isSubmitting,
|
|
56
|
+
disabled,
|
|
57
|
+
status,
|
|
58
|
+
pluginActions,
|
|
59
|
+
openEntityMode
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type ActionsViewProps<M extends object> = {
|
|
64
|
+
savingError: Error | undefined,
|
|
65
|
+
entity: Entity<M> | undefined,
|
|
66
|
+
formActions?: EntityAction[],
|
|
67
|
+
collection: ResolvedEntityCollection,
|
|
68
|
+
context: FireCMSContext,
|
|
69
|
+
sideEntityController: SideEntityController,
|
|
70
|
+
isSubmitting: boolean,
|
|
71
|
+
disabled: boolean,
|
|
72
|
+
status: "new" | "existing" | "copy",
|
|
73
|
+
pluginActions?: React.ReactNode[],
|
|
74
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
function buildBottomActions<M extends object>({
|
|
78
|
+
savingError,
|
|
79
|
+
entity,
|
|
80
|
+
formActions,
|
|
81
|
+
collection,
|
|
82
|
+
context,
|
|
83
|
+
sideEntityController,
|
|
84
|
+
isSubmitting,
|
|
85
|
+
disabled,
|
|
86
|
+
status,
|
|
87
|
+
pluginActions,
|
|
88
|
+
openEntityMode
|
|
89
|
+
}: ActionsViewProps<M>) {
|
|
90
|
+
|
|
91
|
+
return <DialogActions position={"absolute"}>
|
|
92
|
+
{savingError &&
|
|
93
|
+
<div className="text-right">
|
|
94
|
+
<Typography color={"error"}>{savingError.message}</Typography>
|
|
95
|
+
</div>
|
|
96
|
+
}
|
|
97
|
+
{entity && (formActions ?? []).length > 0 && <div className="flex-grow flex overflow-auto no-scrollbar">
|
|
98
|
+
{(formActions ?? []).map(action => (
|
|
99
|
+
<IconButton
|
|
100
|
+
key={action.name}
|
|
101
|
+
color="primary"
|
|
102
|
+
onClick={(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
103
|
+
event.stopPropagation();
|
|
104
|
+
if (entity)
|
|
105
|
+
action.onClick({
|
|
106
|
+
entity,
|
|
107
|
+
fullPath: collection.path,
|
|
108
|
+
collection: collection,
|
|
109
|
+
context,
|
|
110
|
+
sideEntityController,
|
|
111
|
+
openEntityMode: openEntityMode
|
|
112
|
+
});
|
|
113
|
+
}}>
|
|
114
|
+
{action.icon}
|
|
115
|
+
</IconButton>
|
|
116
|
+
))}
|
|
117
|
+
</div>}
|
|
118
|
+
{pluginActions}
|
|
119
|
+
<Button variant="text" disabled={disabled || isSubmitting} type="reset">
|
|
120
|
+
{status === "existing" ? "Discard" : "Clear"}
|
|
121
|
+
</Button>
|
|
122
|
+
<Button variant={"filled"} color="primary" type="submit"
|
|
123
|
+
disabled={disabled || isSubmitting}>
|
|
124
|
+
{status === "existing" && "Save"}
|
|
125
|
+
{status === "copy" && "Create copy"}
|
|
126
|
+
{status === "new" && "Create"}
|
|
127
|
+
</Button>
|
|
128
|
+
|
|
129
|
+
</DialogActions>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function buildSideActions<M extends object>({
|
|
133
|
+
savingError,
|
|
134
|
+
entity,
|
|
135
|
+
formActions,
|
|
136
|
+
collection,
|
|
137
|
+
context,
|
|
138
|
+
sideEntityController,
|
|
139
|
+
isSubmitting,
|
|
140
|
+
disabled,
|
|
141
|
+
status,
|
|
142
|
+
pluginActions
|
|
143
|
+
}: ActionsViewProps<M>) {
|
|
144
|
+
|
|
145
|
+
return <div
|
|
146
|
+
className={cls("overflow-auto h-full flex flex-col gap-2 w-80 2xl:w-96 px-4 py-16 sticky top-0 border-l", defaultBorderMixin)}>
|
|
147
|
+
<LoadingButton fullWidth={true}
|
|
148
|
+
variant="filled"
|
|
149
|
+
color="primary"
|
|
150
|
+
type="submit"
|
|
151
|
+
size={"large"}
|
|
152
|
+
disabled={disabled || isSubmitting}>
|
|
153
|
+
{status === "existing" && "Save"}
|
|
154
|
+
{status === "copy" && "Create copy"}
|
|
155
|
+
{status === "new" && "Create"}
|
|
156
|
+
</LoadingButton>
|
|
157
|
+
<Button fullWidth={true} variant="text" disabled={disabled || isSubmitting} type="reset">
|
|
158
|
+
{status === "existing" ? "Discard" : "Clear"}
|
|
159
|
+
</Button>
|
|
160
|
+
|
|
161
|
+
{pluginActions}
|
|
162
|
+
|
|
163
|
+
{savingError &&
|
|
164
|
+
<div className="text-right">
|
|
165
|
+
<Typography color={"error"}>{savingError.message}</Typography>
|
|
166
|
+
</div>
|
|
167
|
+
}
|
|
168
|
+
</div>;
|
|
169
|
+
}
|
|
@@ -5,13 +5,13 @@ import { Field, FieldProps as FormexFieldProps, getIn } from "@firecms/formex";
|
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
CMSType,
|
|
8
|
-
EntityCollection,
|
|
9
8
|
FieldProps,
|
|
10
9
|
FireCMSPlugin,
|
|
11
10
|
PluginFieldBuilderParams,
|
|
12
11
|
Property,
|
|
13
12
|
PropertyFieldBindingProps,
|
|
14
13
|
PropertyOrBuilder,
|
|
14
|
+
ResolvedEntityCollection,
|
|
15
15
|
ResolvedProperty
|
|
16
16
|
} from "../types";
|
|
17
17
|
import { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
|
|
@@ -74,7 +74,7 @@ export const PropertyFieldBinding = React.memo(PropertyFieldBindingInternal, (a:
|
|
|
74
74
|
return false;
|
|
75
75
|
}) as typeof PropertyFieldBindingInternal;
|
|
76
76
|
|
|
77
|
-
function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Record<string, any> =
|
|
77
|
+
function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Record<string, any> = any>
|
|
78
78
|
({
|
|
79
79
|
propertyKey,
|
|
80
80
|
property,
|
|
@@ -147,7 +147,9 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
|
|
|
147
147
|
console.warn(`No field component found for property ${propertyKey}`);
|
|
148
148
|
console.warn("Property:", property);
|
|
149
149
|
return (
|
|
150
|
-
<div
|
|
150
|
+
<div className={"w-full"}>
|
|
151
|
+
{`Currently the field ${resolvedProperty.dataType} is not supported`}
|
|
152
|
+
</div>
|
|
151
153
|
);
|
|
152
154
|
}
|
|
153
155
|
|
|
@@ -175,7 +177,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
|
|
|
175
177
|
|
|
176
178
|
}
|
|
177
179
|
|
|
178
|
-
type ResolvedPropertyFieldBindingProps<T extends CMSType = CMSType, M extends Record<string, any> =
|
|
180
|
+
type ResolvedPropertyFieldBindingProps<T extends CMSType = CMSType, M extends Record<string, any> = any> =
|
|
179
181
|
Omit<PropertyFieldBindingProps<T, M>, "property">
|
|
180
182
|
& {
|
|
181
183
|
property: ResolvedProperty<T>
|
|
@@ -199,11 +201,11 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
|
|
|
199
201
|
},
|
|
200
202
|
formexFieldProps
|
|
201
203
|
}:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
{
|
|
205
|
+
Component: ComponentType<FieldProps<T, any, M>>,
|
|
206
|
+
componentProps: ResolvedPropertyFieldBindingProps<T, M>,
|
|
207
|
+
formexFieldProps: FormexFieldProps<T, any>
|
|
208
|
+
}) {
|
|
207
209
|
|
|
208
210
|
const { plugins } = useCustomizationController();
|
|
209
211
|
|
|
@@ -296,7 +298,7 @@ const shouldPropertyReRender = (property: PropertyOrBuilder | ResolvedProperty,
|
|
|
296
298
|
|
|
297
299
|
interface UseWrappedComponentParams<T extends CMSType = CMSType, M extends Record<string, any> = any> {
|
|
298
300
|
path?: string,
|
|
299
|
-
collection?:
|
|
301
|
+
collection?: ResolvedEntityCollection<M>,
|
|
300
302
|
propertyKey: string,
|
|
301
303
|
property: ResolvedProperty<T>,
|
|
302
304
|
Component: ComponentType<FieldProps<T, any, M>>,
|
|
@@ -327,7 +329,7 @@ function useWrappedComponent<T extends CMSType = CMSType, M extends Record<strin
|
|
|
327
329
|
Field: Component,
|
|
328
330
|
plugin,
|
|
329
331
|
path,
|
|
330
|
-
collection
|
|
332
|
+
collection,
|
|
331
333
|
};
|
|
332
334
|
const enabled = plugin.form?.fieldBuilderEnabled?.(params);
|
|
333
335
|
if (enabled === undefined || enabled)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ErrorBoundary } from "../../components";
|
|
3
|
+
|
|
4
|
+
export function FormEntry({
|
|
5
|
+
propertyKey,
|
|
6
|
+
widthPercentage = 100,
|
|
7
|
+
children
|
|
8
|
+
}: {
|
|
9
|
+
propertyKey: string;
|
|
10
|
+
widthPercentage?: number;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}) {
|
|
13
|
+
return (
|
|
14
|
+
<div id={`form_field_${propertyKey}`}
|
|
15
|
+
className={"relative"}
|
|
16
|
+
style={{ width: widthPercentage === 100 ? "100%" : `calc(${widthPercentage}% - 8px)` }}>
|
|
17
|
+
<ErrorBoundary>
|
|
18
|
+
{children}
|
|
19
|
+
</ErrorBoundary>
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cls } from "@firecms/ui";
|
|
3
|
+
|
|
4
|
+
export function FormLayout({
|
|
5
|
+
children,
|
|
6
|
+
className
|
|
7
|
+
}: {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
}) {
|
|
11
|
+
return (
|
|
12
|
+
<div className={cls("flex flex-wrap gap-x-4 w-full space-y-8", className)}>
|
|
13
|
+
{children}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { forwardRef } from "react";
|
|
2
|
+
import { cls } from "@firecms/ui";
|
|
2
3
|
|
|
3
4
|
interface LabelWithIconProps {
|
|
4
5
|
icon: React.ReactNode;
|
|
@@ -23,9 +24,11 @@ export const LabelWithIcon = forwardRef<HTMLDivElement, LabelWithIconProps>(
|
|
|
23
24
|
return (
|
|
24
25
|
<div
|
|
25
26
|
ref={ref}
|
|
26
|
-
className={
|
|
27
|
+
className={cls("inline-flex items-center my-0.5",
|
|
28
|
+
small ? "gap-1" : "gap-2",
|
|
29
|
+
className)}
|
|
27
30
|
>
|
|
28
|
-
|
|
31
|
+
{icon}
|
|
29
32
|
<span
|
|
30
33
|
className={`text-start font-medium text-${small ? "base" : "sm"} origin-top-left transform ${
|
|
31
34
|
small ? "translate-x-2 scale-75" : ""
|
|
@@ -33,7 +36,7 @@ export const LabelWithIcon = forwardRef<HTMLDivElement, LabelWithIconProps>(
|
|
|
33
36
|
>
|
|
34
37
|
{(title ?? "") + (required ? " *" : "")}
|
|
35
38
|
</span>
|
|
36
|
-
|
|
39
|
+
</div>
|
|
37
40
|
);
|
|
38
41
|
}
|
|
39
42
|
);
|
|
@@ -92,7 +92,7 @@ export function StorageUploadProgress({
|
|
|
92
92
|
`min-w-[${imageSize}px] min-h-[${imageSize}px]`)}>
|
|
93
93
|
|
|
94
94
|
{loading &&
|
|
95
|
-
<Skeleton className="w-full h-full"/>}
|
|
95
|
+
<Skeleton className="m-4 w-full h-full"/>}
|
|
96
96
|
|
|
97
97
|
{error && <ErrorView title={"Error uploading file"}
|
|
98
98
|
error={error}/>}
|
|
@@ -20,14 +20,15 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
|
|
|
20
20
|
showError,
|
|
21
21
|
isSubmitting,
|
|
22
22
|
setValue,
|
|
23
|
-
minimalistView,
|
|
23
|
+
minimalistView: minimalistViewProp,
|
|
24
24
|
property,
|
|
25
25
|
includeDescription,
|
|
26
|
-
underlyingValueHasChanged,
|
|
27
26
|
context,
|
|
28
27
|
disabled
|
|
29
28
|
}: FieldProps<T, any, any>) {
|
|
30
29
|
|
|
30
|
+
const minimalistView = minimalistViewProp || property.minimalistView;
|
|
31
|
+
|
|
31
32
|
let resolvedProperties = "resolvedProperties" in property ? property.resolvedProperties : undefined;
|
|
32
33
|
if (!resolvedProperties) {
|
|
33
34
|
resolvedProperties = getArrayResolvedProperties({
|
|
@@ -52,7 +53,7 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
|
|
|
52
53
|
icon={getIconForProperty(property, "small")}
|
|
53
54
|
required={property.validation?.required}
|
|
54
55
|
title={property.name}
|
|
55
|
-
className={"flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
|
|
56
|
+
className={"h-8 flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
|
|
56
57
|
{Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
|
|
57
58
|
</>);
|
|
58
59
|
|
|
@@ -63,7 +64,6 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
|
|
|
63
64
|
disabled: disabled || thisDisabled,
|
|
64
65
|
property: childProperty,
|
|
65
66
|
includeDescription,
|
|
66
|
-
underlyingValueHasChanged,
|
|
67
67
|
context,
|
|
68
68
|
partOfArray: true,
|
|
69
69
|
minimalistView: false,
|
|
@@ -25,13 +25,15 @@ export function ArrayOfReferencesFieldBinding({
|
|
|
25
25
|
showError,
|
|
26
26
|
disabled,
|
|
27
27
|
isSubmitting,
|
|
28
|
-
minimalistView,
|
|
28
|
+
minimalistView: minimalistViewProp,
|
|
29
29
|
property,
|
|
30
30
|
includeDescription,
|
|
31
31
|
setValue,
|
|
32
32
|
setFieldValue
|
|
33
33
|
}: ArrayOfReferencesFieldProps) {
|
|
34
34
|
|
|
35
|
+
const minimalistView = minimalistViewProp || property.minimalistView;
|
|
36
|
+
|
|
35
37
|
const ofProperty = property.of as ResolvedProperty;
|
|
36
38
|
if (ofProperty.dataType !== "reference") {
|
|
37
39
|
throw Error("ArrayOfReferencesField expected a property containing references");
|
|
@@ -104,7 +106,7 @@ export function ArrayOfReferencesFieldBinding({
|
|
|
104
106
|
icon={getIconForProperty(property, "small")}
|
|
105
107
|
required={property.validation?.required}
|
|
106
108
|
title={property.name}
|
|
107
|
-
className={"flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
|
|
109
|
+
className={"h-8 flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
|
|
108
110
|
{Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
|
|
109
111
|
</>);
|
|
110
112
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { Field, useFormex } from "@firecms/formex";
|
|
4
4
|
|
|
@@ -28,7 +28,7 @@ export function BlockFieldBinding<T extends Array<any>>({
|
|
|
28
28
|
isSubmitting,
|
|
29
29
|
setValue,
|
|
30
30
|
setFieldValue,
|
|
31
|
-
minimalistView,
|
|
31
|
+
minimalistView: minimalistViewProp,
|
|
32
32
|
property,
|
|
33
33
|
includeDescription,
|
|
34
34
|
underlyingValueHasChanged,
|
|
@@ -36,6 +36,8 @@ export function BlockFieldBinding<T extends Array<any>>({
|
|
|
36
36
|
disabled
|
|
37
37
|
}: FieldProps<T>) {
|
|
38
38
|
|
|
39
|
+
const minimalistView = minimalistViewProp || property.minimalistView;
|
|
40
|
+
|
|
39
41
|
if (!property.oneOf)
|
|
40
42
|
throw Error("ArrayOneOfField misconfiguration. Property `oneOf` not set");
|
|
41
43
|
|
|
@@ -5,7 +5,7 @@ import { ErrorBoundary } from "../../components";
|
|
|
5
5
|
import { getIconForProperty, isHidden, isReadOnly, pick } from "../../util";
|
|
6
6
|
import { FieldHelperText, LabelWithIconAndTooltip } from "../components";
|
|
7
7
|
import { PropertyFieldBinding } from "../PropertyFieldBinding";
|
|
8
|
-
import { ExpandablePanel, InputLabel, Select, SelectItem } from "@firecms/ui";
|
|
8
|
+
import { cls, ExpandablePanel, InputLabel, Select, SelectItem } from "@firecms/ui";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Field that renders the children property fields
|
|
@@ -21,9 +21,8 @@ export function MapFieldBinding({
|
|
|
21
21
|
error,
|
|
22
22
|
disabled,
|
|
23
23
|
property,
|
|
24
|
-
minimalistView,
|
|
24
|
+
minimalistView: minimalistViewProp,
|
|
25
25
|
includeDescription,
|
|
26
|
-
underlyingValueHasChanged,
|
|
27
26
|
autoFocus,
|
|
28
27
|
context,
|
|
29
28
|
onPropertyChange
|
|
@@ -31,6 +30,7 @@ export function MapFieldBinding({
|
|
|
31
30
|
|
|
32
31
|
const pickOnlySomeKeys = property.pickOnlySomeKeys || false;
|
|
33
32
|
const expanded = property.expanded === undefined ? true : property.expanded;
|
|
33
|
+
const minimalistView = minimalistViewProp || property.minimalistView;
|
|
34
34
|
|
|
35
35
|
if (!property.properties) {
|
|
36
36
|
throw Error(`You need to specify a 'properties' prop (or specify a custom field) in your map property ${propertyKey}`);
|
|
@@ -51,7 +51,7 @@ export function MapFieldBinding({
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
const mapFormView = <>
|
|
54
|
-
<div className="py-1 flex flex-col space-y-2">
|
|
54
|
+
<div className={cls("py-1 flex flex-col space-y-2", minimalistView && property.widthPercentage !== undefined ? "mt-8" : undefined)}>
|
|
55
55
|
{Object.entries(mapProperties)
|
|
56
56
|
.filter(([_, property]) => !isHidden(property))
|
|
57
57
|
.map(([entryKey, childProperty], index) => {
|
|
@@ -61,7 +61,6 @@ export function MapFieldBinding({
|
|
|
61
61
|
disabled: disabled || thisDisabled,
|
|
62
62
|
property: childProperty,
|
|
63
63
|
includeDescription,
|
|
64
|
-
underlyingValueHasChanged,
|
|
65
64
|
context,
|
|
66
65
|
partOfArray: false,
|
|
67
66
|
minimalistView: false,
|
|
@@ -76,7 +75,7 @@ export function MapFieldBinding({
|
|
|
76
75
|
};
|
|
77
76
|
|
|
78
77
|
return (
|
|
79
|
-
<div key={`map-${propertyKey}-${index}`}>
|
|
78
|
+
<div key={`map-${propertyKey}-${index}`} className={"relative"}>
|
|
80
79
|
<ErrorBoundary>
|
|
81
80
|
<PropertyFieldBinding
|
|
82
81
|
{...fieldBindingProps}/>
|
|
@@ -94,15 +93,6 @@ export function MapFieldBinding({
|
|
|
94
93
|
</>
|
|
95
94
|
;
|
|
96
95
|
|
|
97
|
-
const title = (
|
|
98
|
-
<LabelWithIconAndTooltip
|
|
99
|
-
propertyKey={propertyKey}
|
|
100
|
-
icon={getIconForProperty(property, "small")}
|
|
101
|
-
required={property.validation?.required}
|
|
102
|
-
title={property.name}
|
|
103
|
-
className={"text-text-secondary dark:text-text-secondary-dark"}/>
|
|
104
|
-
);
|
|
105
|
-
|
|
106
96
|
return (
|
|
107
97
|
<ErrorBoundary>
|
|
108
98
|
|
|
@@ -112,8 +102,16 @@ export function MapFieldBinding({
|
|
|
112
102
|
expanded
|
|
113
103
|
});
|
|
114
104
|
}}
|
|
105
|
+
className={property.widthPercentage !== undefined ? "mt-8" : undefined}
|
|
115
106
|
innerClassName={"px-2 md:px-4 pb-2 md:pb-4 pt-1 md:pt-2 bg-white dark:bg-surface-900"}
|
|
116
|
-
title={
|
|
107
|
+
title={<LabelWithIconAndTooltip
|
|
108
|
+
propertyKey={propertyKey}
|
|
109
|
+
icon={getIconForProperty(property, "small")}
|
|
110
|
+
required={property.validation?.required}
|
|
111
|
+
title={property.name}
|
|
112
|
+
className={"text-text-secondary dark:text-text-secondary-dark"}/>}>
|
|
113
|
+
{mapFormView}
|
|
114
|
+
</ExpandablePanel>}
|
|
117
115
|
|
|
118
116
|
{minimalistView && mapFormView}
|
|
119
117
|
|
|
@@ -3,13 +3,14 @@ import {
|
|
|
3
3
|
FieldHelperText,
|
|
4
4
|
FieldProps,
|
|
5
5
|
getIconForProperty,
|
|
6
|
-
LabelWithIconAndTooltip,
|
|
6
|
+
LabelWithIconAndTooltip,
|
|
7
|
+
PropertyOrBuilder,
|
|
7
8
|
randomString,
|
|
8
9
|
ResolvedArrayProperty,
|
|
9
10
|
ResolvedStringProperty,
|
|
10
11
|
useStorageSource
|
|
11
12
|
} from "../../index";
|
|
12
|
-
import { cls, fieldBackgroundHoverMixin, fieldBackgroundMixin } from "@firecms/ui";
|
|
13
|
+
import { cls, fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundMixin } from "@firecms/ui";
|
|
13
14
|
import { FireCMSEditor, FireCMSEditorProps } from "@firecms/editor";
|
|
14
15
|
import { resolveProperty, resolveStorageFilenameString, resolveStoragePathString } from "../../util";
|
|
15
16
|
|
|
@@ -27,11 +28,13 @@ export function MarkdownEditorFieldBinding({
|
|
|
27
28
|
showError,
|
|
28
29
|
error,
|
|
29
30
|
minimalistView,
|
|
31
|
+
disabled: disabledProp,
|
|
30
32
|
isSubmitting,
|
|
31
33
|
context,
|
|
32
34
|
customProps,
|
|
33
35
|
}: FieldProps<string, MarkdownEditorFieldProps>) {
|
|
34
36
|
|
|
37
|
+
const disabled = disabledProp || isSubmitting;
|
|
35
38
|
const highlight = customProps?.highlight;
|
|
36
39
|
const editorProps = customProps?.editorProps;
|
|
37
40
|
const storageSource = useStorageSource();
|
|
@@ -54,11 +57,9 @@ export function MarkdownEditorFieldBinding({
|
|
|
54
57
|
if (internalValue.current !== value) {
|
|
55
58
|
internalValue.current = value;
|
|
56
59
|
setFieldVersion(fieldVersion + 1);
|
|
57
|
-
// fieldVersion.current = fieldVersion.current + 1;
|
|
58
60
|
}
|
|
59
61
|
}, [value]);
|
|
60
62
|
|
|
61
|
-
|
|
62
63
|
const resolvedProperty = resolveProperty({
|
|
63
64
|
propertyOrBuilder: property as PropertyOrBuilder,
|
|
64
65
|
values: entityValues
|
|
@@ -107,6 +108,7 @@ export function MarkdownEditorFieldBinding({
|
|
|
107
108
|
onMarkdownContentChange={onContentChange}
|
|
108
109
|
version={context.formex.version + fieldVersion}
|
|
109
110
|
highlight={highlight}
|
|
111
|
+
disabled={disabled}
|
|
110
112
|
handleImageUpload={async (file: File) => {
|
|
111
113
|
const storagePath = storagePathBuilder(file);
|
|
112
114
|
const fileName = await fileNameBuilder(file);
|
|
@@ -135,8 +137,9 @@ export function MarkdownEditorFieldBinding({
|
|
|
135
137
|
icon={getIconForProperty(property, "small")}
|
|
136
138
|
required={property.validation?.required}
|
|
137
139
|
title={property.name}
|
|
138
|
-
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
139
|
-
<div
|
|
140
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
141
|
+
<div
|
|
142
|
+
className={cls("rounded-md", fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin)}>
|
|
140
143
|
{editor}
|
|
141
144
|
</div>
|
|
142
145
|
<FieldHelperText includeDescription={includeDescription}
|
|
@@ -92,7 +92,7 @@ export function MultiSelectFieldBinding({
|
|
|
92
92
|
icon={getIconForProperty(property, "small")}
|
|
93
93
|
required={property.validation?.required}
|
|
94
94
|
title={property.name}
|
|
95
|
-
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
95
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
96
96
|
onValueChange={(updatedValue: string[]) => {
|
|
97
97
|
let newValue: EnumType[] | null;
|
|
98
98
|
if (of && (of as ResolvedProperty)?.dataType === "number") {
|
|
@@ -39,11 +39,11 @@ export function ReadOnlyFieldBinding({
|
|
|
39
39
|
icon={getIconForProperty(property, "small")}
|
|
40
40
|
required={property.validation?.required}
|
|
41
41
|
title={property.name}
|
|
42
|
-
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
42
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
<div
|
|
46
|
-
className={cls(paperMixin, "min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
|
|
46
|
+
className={cls(paperMixin, "w-full min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
|
|
47
47
|
|
|
48
48
|
<ErrorBoundary>
|
|
49
49
|
<PropertyPreview propertyKey={propertyKey}
|
|
@@ -90,7 +90,7 @@ function ReferenceFieldBindingInternal({
|
|
|
90
90
|
icon={getIconForProperty(property, "small")}
|
|
91
91
|
required={property.validation?.required}
|
|
92
92
|
title={property.name}
|
|
93
|
-
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
93
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>}
|
|
94
94
|
|
|
95
95
|
{!collection && <ErrorView
|
|
96
96
|
error={"The specified collection does not exist. Check console"}/>}
|
|
@@ -23,7 +23,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
|
|
|
23
23
|
isSubmitting,
|
|
24
24
|
setValue,
|
|
25
25
|
setFieldValue,
|
|
26
|
-
minimalistView,
|
|
26
|
+
minimalistView: minimalistViewProp,
|
|
27
27
|
property,
|
|
28
28
|
includeDescription,
|
|
29
29
|
underlyingValueHasChanged,
|
|
@@ -31,6 +31,8 @@ export function RepeatFieldBinding<T extends Array<any>>({
|
|
|
31
31
|
disabled
|
|
32
32
|
}: FieldProps<T>) {
|
|
33
33
|
|
|
34
|
+
const minimalistView = minimalistViewProp || property.minimalistView;
|
|
35
|
+
|
|
34
36
|
if (!property.of)
|
|
35
37
|
throw Error("RepeatFieldBinding misconfiguration. Property `of` not set");
|
|
36
38
|
|
|
@@ -88,6 +90,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
|
|
|
88
90
|
includeAddButton={!property.disabled}
|
|
89
91
|
newDefaultEntry={getDefaultValueFor(property.of)}
|
|
90
92
|
onValueChange={(value) => setFieldValue(propertyKey, value)}
|
|
93
|
+
className={property.widthPercentage !== undefined ? "mt-8" : undefined}
|
|
91
94
|
/>;
|
|
92
95
|
|
|
93
96
|
const title = (<>
|
|
@@ -96,7 +99,7 @@ export function RepeatFieldBinding<T extends Array<any>>({
|
|
|
96
99
|
icon={getIconForProperty(property, "small")}
|
|
97
100
|
required={property.validation?.required}
|
|
98
101
|
title={property.name}
|
|
99
|
-
className={"flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
|
|
102
|
+
className={"h-8 flex flex-grow text-text-secondary dark:text-text-secondary-dark"}/>
|
|
100
103
|
{Array.isArray(value) && <Typography variant={"caption"} className={"px-4"}>({value.length})</Typography>}
|
|
101
104
|
</>);
|
|
102
105
|
|
|
@@ -62,7 +62,7 @@ export function SelectFieldBinding<T extends EnumType>({
|
|
|
62
62
|
icon={getIconForProperty(property, "small")}
|
|
63
63
|
required={property.validation?.required}
|
|
64
64
|
title={property.name}
|
|
65
|
-
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}
|
|
65
|
+
className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5 my-0"}
|
|
66
66
|
/>
|
|
67
67
|
</PropertyIdCopyTooltip>}
|
|
68
68
|
endAdornment={
|