@firecms/core 3.0.0-canary.190 → 3.0.0-canary.192
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/core/EntityEditView.d.ts +1 -2
- package/dist/core/EntityEditViewFormActions.d.ts +2 -0
- package/dist/core/SideDialogs.d.ts +4 -2
- package/dist/{core → form}/EntityForm.d.ts +6 -4
- package/dist/form/EntityFormActions.d.ts +16 -0
- package/dist/form/index.d.ts +16 -16
- package/dist/index.es.js +2391 -2292
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +2783 -2684
- package/dist/index.umd.js.map +1 -1
- package/dist/types/fields.d.ts +0 -6
- package/package.json +5 -5
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -10
- package/src/core/EntityEditView.tsx +14 -85
- package/src/core/EntityEditViewFormActions.tsx +198 -0
- package/src/core/EntitySidePanel.tsx +8 -1
- package/src/core/SideDialogs.tsx +16 -12
- package/src/{core → form}/EntityForm.tsx +37 -243
- package/src/form/EntityFormActions.tsx +168 -0
- package/src/form/index.tsx +16 -32
- package/src/internal/useBuildSideEntityController.tsx +0 -52
- package/src/types/fields.tsx +0 -7
package/dist/types/fields.d.ts
CHANGED
|
@@ -137,12 +137,6 @@ export interface FormContext<M extends Record<string, any> = any> {
|
|
|
137
137
|
entity?: Entity<M>;
|
|
138
138
|
savingError?: Error;
|
|
139
139
|
openEntityMode: "side_panel" | "full_screen";
|
|
140
|
-
/**
|
|
141
|
-
* If pending close is set to true, the form will close when the user
|
|
142
|
-
* saves the entity
|
|
143
|
-
* @param pendingClose
|
|
144
|
-
*/
|
|
145
|
-
setPendingClose?: (pendingClose: boolean) => void;
|
|
146
140
|
/**
|
|
147
141
|
* This is the underlying formex controller that powers the form
|
|
148
142
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.0.0-canary.
|
|
4
|
+
"version": "3.0.0-canary.192",
|
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/firecmsco"
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"./package.json": "./package.json"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@firecms/editor": "^3.0.0-canary.
|
|
54
|
-
"@firecms/formex": "^3.0.0-canary.
|
|
55
|
-
"@firecms/ui": "^3.0.0-canary.
|
|
53
|
+
"@firecms/editor": "^3.0.0-canary.192",
|
|
54
|
+
"@firecms/formex": "^3.0.0-canary.192",
|
|
55
|
+
"@firecms/ui": "^3.0.0-canary.192",
|
|
56
56
|
"@hello-pangea/dnd": "^17.0.0",
|
|
57
57
|
"@radix-ui/react-portal": "^1.1.3",
|
|
58
58
|
"clsx": "^2.1.1",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"dist",
|
|
105
105
|
"src"
|
|
106
106
|
],
|
|
107
|
-
"gitHead": "
|
|
107
|
+
"gitHead": "ec1250125ee49075f94237f0e34c82cb6d624c1c",
|
|
108
108
|
"publishConfig": {
|
|
109
109
|
"access": "public"
|
|
110
110
|
},
|
|
@@ -20,10 +20,9 @@ import { useWindowSize } from "./useWindowSize";
|
|
|
20
20
|
import { ElementResizeListener } from "./ElementResizeListener";
|
|
21
21
|
import { getPropertyInPath, isReadOnly, resolveCollection } from "../../../../util";
|
|
22
22
|
import { Button, CloseIcon, DialogActions, IconButton, Typography } from "@firecms/ui";
|
|
23
|
-
import { PropertyFieldBinding } from "../../../../form";
|
|
23
|
+
import { PropertyFieldBinding, yupToFormErrors } from "../../../../form";
|
|
24
24
|
import { useCustomizationController, useDataSource, useFireCMSContext } from "../../../../hooks";
|
|
25
25
|
import { OnCellValueChangeParams } from "../../../common";
|
|
26
|
-
import { yupToFormErrors } from "../../../../core/EntityForm";
|
|
27
26
|
|
|
28
27
|
interface PopupFormFieldProps<M extends Record<string, any>> {
|
|
29
28
|
customFieldValidator?: CustomFieldValidator;
|
|
@@ -240,14 +239,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
|
|
|
240
239
|
validation: (values) => {
|
|
241
240
|
return validationSchema?.validate(values, { abortEarly: false })
|
|
242
241
|
.then(() => ({}))
|
|
243
|
-
.catch(
|
|
244
|
-
// const errors: Record<string, string> = {};
|
|
245
|
-
// e.inner.forEach((error: any) => {
|
|
246
|
-
// errors[error.path] = error.message;
|
|
247
|
-
// });
|
|
248
|
-
// return errors;
|
|
249
|
-
return yupToFormErrors(e);
|
|
250
|
-
});
|
|
242
|
+
.catch(yupToFormErrors);
|
|
251
243
|
},
|
|
252
244
|
validateOnInitialRender: true,
|
|
253
245
|
onSubmit: (values, actions) => {
|
|
@@ -1,88 +1,20 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
CMSAnalyticsEvent,
|
|
4
|
-
Entity,
|
|
5
|
-
EntityAction,
|
|
6
|
-
EntityCollection,
|
|
7
|
-
EntityCustomView,
|
|
8
|
-
EntityStatus,
|
|
9
|
-
EntityValues,
|
|
10
|
-
FireCMSContext,
|
|
11
|
-
FireCMSPlugin,
|
|
12
|
-
FormContext,
|
|
13
|
-
PluginFormActionProps,
|
|
14
|
-
PropertyFieldBindingProps,
|
|
15
|
-
ResolvedEntityCollection,
|
|
16
|
-
SideEntityController,
|
|
17
|
-
User
|
|
18
|
-
} from "../types";
|
|
19
|
-
import equal from "react-fast-compare";
|
|
1
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { Entity, EntityCollection, EntityCustomView, EntityStatus, FireCMSPlugin, FormContext, User } from "../types";
|
|
20
3
|
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
copyEntityAction,
|
|
24
|
-
deleteEntityAction,
|
|
25
|
-
EntityCollectionView,
|
|
26
|
-
EntityView,
|
|
27
|
-
ErrorBoundary,
|
|
28
|
-
getFormFieldKeys
|
|
29
|
-
} from "../components";
|
|
30
|
-
import {
|
|
31
|
-
canCreateEntity,
|
|
32
|
-
canDeleteEntity,
|
|
33
|
-
canEditEntity,
|
|
34
|
-
getDefaultValuesFor,
|
|
35
|
-
getEntityTitlePropertyKey,
|
|
36
|
-
getValueInPath,
|
|
37
|
-
isHidden,
|
|
38
|
-
isReadOnly,
|
|
39
|
-
mergeEntityActions,
|
|
40
|
-
removeInitialAndTrailingSlashes,
|
|
41
|
-
resolveCollection,
|
|
42
|
-
resolveDefaultSelectedView,
|
|
43
|
-
resolveEntityView,
|
|
44
|
-
useDebouncedCallback
|
|
45
|
-
} from "../util";
|
|
4
|
+
import { CircularProgressCenter, EntityCollectionView, EntityView, ErrorBoundary } from "../components";
|
|
5
|
+
import { canEditEntity, removeInitialAndTrailingSlashes, resolveDefaultSelectedView, resolveEntityView } from "../util";
|
|
46
6
|
|
|
47
7
|
import {
|
|
48
|
-
saveEntityWithCallbacks,
|
|
49
8
|
useAuthController,
|
|
50
9
|
useCustomizationController,
|
|
51
|
-
useDataSource,
|
|
52
10
|
useEntityFetch,
|
|
53
11
|
useFireCMSContext,
|
|
54
|
-
useLargeLayout
|
|
55
|
-
useSideEntityController,
|
|
56
|
-
useSnackbarController
|
|
12
|
+
useLargeLayout
|
|
57
13
|
} from "../hooks";
|
|
58
|
-
import {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
Chip,
|
|
63
|
-
CircularProgress,
|
|
64
|
-
cls,
|
|
65
|
-
defaultBorderMixin,
|
|
66
|
-
DialogActions,
|
|
67
|
-
EditIcon,
|
|
68
|
-
IconButton,
|
|
69
|
-
LoadingButton,
|
|
70
|
-
NotesIcon,
|
|
71
|
-
paperMixin,
|
|
72
|
-
Tab,
|
|
73
|
-
Tabs,
|
|
74
|
-
Tooltip,
|
|
75
|
-
Typography
|
|
76
|
-
} from "@firecms/ui";
|
|
77
|
-
import { Formex, FormexController, getIn, setIn, useCreateFormex } from "@firecms/formex";
|
|
78
|
-
import { useAnalyticsController } from "../hooks/useAnalyticsController";
|
|
79
|
-
import { FormEntry, FormLayout, LabelWithIconAndTooltip, PropertyFieldBinding } from "../form";
|
|
80
|
-
import { ValidationError } from "yup";
|
|
81
|
-
import { getEntityFromCache, removeEntityFromCache, saveEntityToCache } from "../util/entity_cache";
|
|
82
|
-
import { CustomIdField } from "../form/components/CustomIdField";
|
|
83
|
-
import { ErrorFocus } from "../form/components/ErrorFocus";
|
|
84
|
-
import { CustomFieldValidator, getYupEntitySchema } from "../form/validation";
|
|
85
|
-
import { EntityForm, FormLayoutInner } from "./EntityForm";
|
|
14
|
+
import { CircularProgress, cls, defaultBorderMixin, Tab, Tabs, Typography } from "@firecms/ui";
|
|
15
|
+
import { getEntityFromCache } from "../util/entity_cache";
|
|
16
|
+
import { EntityForm, FormLayoutInner } from "../form";
|
|
17
|
+
import { EntityEditViewFormActions } from "./EntityEditViewFormActions";
|
|
86
18
|
|
|
87
19
|
const MAIN_TAB_VALUE = "main_##Q$SC^#S6";
|
|
88
20
|
|
|
@@ -112,7 +44,6 @@ export interface EntityEditViewProps<M extends Record<string, any>> {
|
|
|
112
44
|
parentCollectionIds: string[];
|
|
113
45
|
onValuesModified?: (modified: boolean) => void;
|
|
114
46
|
onSaved?: (params: OnUpdateParams) => void;
|
|
115
|
-
onClose?: () => void;
|
|
116
47
|
onTabChange?: (props: OnTabChangeParams<M>) => void;
|
|
117
48
|
layout?: "side_panel" | "full_screen";
|
|
118
49
|
barActions?: React.ReactNode;
|
|
@@ -188,21 +119,20 @@ export function EntityEditView<M extends Record<string, any>, USER extends User>
|
|
|
188
119
|
/>;
|
|
189
120
|
}
|
|
190
121
|
|
|
191
|
-
|
|
192
122
|
function SecondaryForm<M extends object>({
|
|
193
123
|
collection,
|
|
194
124
|
className,
|
|
195
125
|
customView,
|
|
196
126
|
entity,
|
|
197
127
|
formContext,
|
|
198
|
-
forceActionsAtTheBottom
|
|
128
|
+
forceActionsAtTheBottom,
|
|
199
129
|
}: {
|
|
200
130
|
className?: string,
|
|
201
131
|
customView: EntityCustomView,
|
|
202
132
|
formContext: FormContext<M>,
|
|
203
133
|
collection: EntityCollection<M>,
|
|
204
134
|
forceActionsAtTheBottom?: boolean,
|
|
205
|
-
entity: Entity<M> | undefined
|
|
135
|
+
entity: Entity<M> | undefined,
|
|
206
136
|
}) {
|
|
207
137
|
|
|
208
138
|
if (!customView.Builder) {
|
|
@@ -213,7 +143,8 @@ function SecondaryForm<M extends object>({
|
|
|
213
143
|
return <FormLayoutInner
|
|
214
144
|
className={className}
|
|
215
145
|
forceActionsAtTheBottom={forceActionsAtTheBottom}
|
|
216
|
-
formContext={formContext}
|
|
146
|
+
formContext={formContext}
|
|
147
|
+
EntityFormActionsComponent={EntityEditViewFormActions}>
|
|
217
148
|
<ErrorBoundary>
|
|
218
149
|
{formContext && <customView.Builder
|
|
219
150
|
collection={collection}
|
|
@@ -229,12 +160,10 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
229
160
|
path,
|
|
230
161
|
entityId,
|
|
231
162
|
selectedTab: selectedTabProp,
|
|
232
|
-
copy,
|
|
233
163
|
collection,
|
|
234
164
|
parentCollectionIds,
|
|
235
165
|
onValuesModified,
|
|
236
166
|
onSaved,
|
|
237
|
-
onClose,
|
|
238
167
|
onTabChange,
|
|
239
168
|
entity,
|
|
240
169
|
cachedDirtyValues,
|
|
@@ -406,7 +335,6 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
406
335
|
...params,
|
|
407
336
|
selectedTab: MAIN_TAB_VALUE === selectedTab ? undefined : selectedTab,
|
|
408
337
|
}) : undefined}
|
|
409
|
-
onClose={onClose}
|
|
410
338
|
entity={entity}
|
|
411
339
|
cachedDirtyValues={cachedDirtyValues}
|
|
412
340
|
openEntityMode={layout}
|
|
@@ -415,6 +343,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
415
343
|
initialStatus={status}
|
|
416
344
|
onStatusChange={setStatus}
|
|
417
345
|
className={!mainViewVisible ? "hidden" : ""}
|
|
346
|
+
EntityFormActionsComponent={EntityEditViewFormActions}
|
|
418
347
|
onEntityChange={setUsedEntity}
|
|
419
348
|
/>;
|
|
420
349
|
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import { Entity, EntityAction, FireCMSContext, ResolvedEntityCollection, SideEntityController } from "../types";
|
|
3
|
+
|
|
4
|
+
import { copyEntityAction, deleteEntityAction } from "../components";
|
|
5
|
+
import { canCreateEntity, canDeleteEntity, mergeEntityActions } from "../util";
|
|
6
|
+
import { Button, cls, defaultBorderMixin, DialogActions, IconButton, LoadingButton, Typography } from "@firecms/ui";
|
|
7
|
+
import { useAuthController, useFireCMSContext, useSideEntityController } from "../hooks";
|
|
8
|
+
import { EntityFormActionsProps } from "../form/EntityFormActions";
|
|
9
|
+
import { SideDialogController, useSideDialogContext } from "./SideDialogs";
|
|
10
|
+
|
|
11
|
+
export function EntityEditViewFormActions({
|
|
12
|
+
collection,
|
|
13
|
+
path,
|
|
14
|
+
entity,
|
|
15
|
+
layout,
|
|
16
|
+
savingError,
|
|
17
|
+
formex,
|
|
18
|
+
disabled,
|
|
19
|
+
status,
|
|
20
|
+
pluginActions,
|
|
21
|
+
openEntityMode
|
|
22
|
+
}: EntityFormActionsProps) {
|
|
23
|
+
|
|
24
|
+
const authController = useAuthController();
|
|
25
|
+
const context = useFireCMSContext();
|
|
26
|
+
const sideEntityController = useSideEntityController();
|
|
27
|
+
const sideDialogContext = useSideDialogContext();
|
|
28
|
+
|
|
29
|
+
const entityActions = useMemo((): EntityAction[] => {
|
|
30
|
+
const customEntityActions = collection.entityActions
|
|
31
|
+
const createEnabled = canCreateEntity(collection, authController, path, null);
|
|
32
|
+
const deleteEnabled = entity ? canDeleteEntity(collection, authController, path, entity) : false;
|
|
33
|
+
const actions: EntityAction[] = [];
|
|
34
|
+
if (createEnabled)
|
|
35
|
+
actions.push(copyEntityAction);
|
|
36
|
+
if (deleteEnabled)
|
|
37
|
+
actions.push(deleteEntityAction);
|
|
38
|
+
if (customEntityActions)
|
|
39
|
+
return mergeEntityActions(actions, customEntityActions);
|
|
40
|
+
return actions;
|
|
41
|
+
}, [authController, collection, path]);
|
|
42
|
+
|
|
43
|
+
const formActions = entityActions.filter(a => a.includeInForm === undefined || a.includeInForm);
|
|
44
|
+
|
|
45
|
+
return layout === "bottom"
|
|
46
|
+
? buildBottomActions({
|
|
47
|
+
savingError,
|
|
48
|
+
entity,
|
|
49
|
+
formActions,
|
|
50
|
+
collection,
|
|
51
|
+
context,
|
|
52
|
+
sideEntityController,
|
|
53
|
+
isSubmitting: formex.isSubmitting,
|
|
54
|
+
disabled,
|
|
55
|
+
status,
|
|
56
|
+
sideDialogContext,
|
|
57
|
+
pluginActions,
|
|
58
|
+
openEntityMode
|
|
59
|
+
})
|
|
60
|
+
: buildSideActions({
|
|
61
|
+
savingError,
|
|
62
|
+
entity,
|
|
63
|
+
formActions,
|
|
64
|
+
collection,
|
|
65
|
+
context,
|
|
66
|
+
sideEntityController,
|
|
67
|
+
isSubmitting: formex.isSubmitting,
|
|
68
|
+
sideDialogContext,
|
|
69
|
+
disabled,
|
|
70
|
+
status,
|
|
71
|
+
pluginActions,
|
|
72
|
+
openEntityMode
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
type ActionsViewProps<M extends object> = {
|
|
77
|
+
savingError: Error | undefined,
|
|
78
|
+
entity: Entity<M> | undefined,
|
|
79
|
+
formActions: EntityAction[],
|
|
80
|
+
collection: ResolvedEntityCollection,
|
|
81
|
+
context: FireCMSContext,
|
|
82
|
+
sideEntityController: SideEntityController,
|
|
83
|
+
isSubmitting: boolean,
|
|
84
|
+
disabled: boolean,
|
|
85
|
+
status: "new" | "existing" | "copy",
|
|
86
|
+
sideDialogContext: SideDialogController,
|
|
87
|
+
pluginActions?: React.ReactNode[],
|
|
88
|
+
openEntityMode: "side_panel" | "full_screen";
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
function buildBottomActions<M extends object>({
|
|
92
|
+
savingError,
|
|
93
|
+
entity,
|
|
94
|
+
formActions,
|
|
95
|
+
collection,
|
|
96
|
+
context,
|
|
97
|
+
sideEntityController,
|
|
98
|
+
isSubmitting,
|
|
99
|
+
disabled,
|
|
100
|
+
status,
|
|
101
|
+
sideDialogContext,
|
|
102
|
+
pluginActions,
|
|
103
|
+
openEntityMode
|
|
104
|
+
}: ActionsViewProps<M>) {
|
|
105
|
+
|
|
106
|
+
const canClose = openEntityMode === "side_panel";
|
|
107
|
+
return <DialogActions position={"absolute"}>
|
|
108
|
+
{savingError &&
|
|
109
|
+
<div className="text-right">
|
|
110
|
+
<Typography color={"error"}>{savingError.message}</Typography>
|
|
111
|
+
</div>
|
|
112
|
+
}
|
|
113
|
+
{entity && formActions.length > 0 && <div className="flex-grow flex overflow-auto no-scrollbar">
|
|
114
|
+
{formActions.map(action => (
|
|
115
|
+
<IconButton
|
|
116
|
+
key={action.name}
|
|
117
|
+
color="primary"
|
|
118
|
+
onClick={(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
119
|
+
event.stopPropagation();
|
|
120
|
+
if (entity)
|
|
121
|
+
action.onClick({
|
|
122
|
+
entity,
|
|
123
|
+
fullPath: collection.path,
|
|
124
|
+
collection: collection,
|
|
125
|
+
context,
|
|
126
|
+
sideEntityController,
|
|
127
|
+
openEntityMode: openEntityMode
|
|
128
|
+
});
|
|
129
|
+
}}>
|
|
130
|
+
{action.icon}
|
|
131
|
+
</IconButton>
|
|
132
|
+
))}
|
|
133
|
+
</div>}
|
|
134
|
+
{pluginActions}
|
|
135
|
+
<Button variant="text" disabled={disabled || isSubmitting} type="reset">
|
|
136
|
+
{status === "existing" ? "Discard" : "Clear"}
|
|
137
|
+
</Button>
|
|
138
|
+
<Button variant={canClose ? "text" : "filled"} color="primary" type="submit"
|
|
139
|
+
disabled={disabled || isSubmitting}
|
|
140
|
+
onClick={() => {
|
|
141
|
+
sideDialogContext.setPendingClose(false);
|
|
142
|
+
}}>
|
|
143
|
+
{status === "existing" && "Save"}
|
|
144
|
+
{status === "copy" && "Create copy"}
|
|
145
|
+
{status === "new" && "Create"}
|
|
146
|
+
</Button>
|
|
147
|
+
{canClose && <LoadingButton variant="filled"
|
|
148
|
+
color="primary"
|
|
149
|
+
type="submit"
|
|
150
|
+
loading={isSubmitting}
|
|
151
|
+
disabled={disabled}
|
|
152
|
+
onClick={() => {
|
|
153
|
+
sideDialogContext.setPendingClose?.(true);
|
|
154
|
+
}}>
|
|
155
|
+
{status === "existing" && "Save and close"}
|
|
156
|
+
{status === "copy" && "Create copy and close"}
|
|
157
|
+
{status === "new" && "Create and close"}
|
|
158
|
+
</LoadingButton>}
|
|
159
|
+
</DialogActions>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function buildSideActions<M extends object>({
|
|
163
|
+
savingError,
|
|
164
|
+
entity,
|
|
165
|
+
formActions,
|
|
166
|
+
collection,
|
|
167
|
+
context,
|
|
168
|
+
sideEntityController,
|
|
169
|
+
isSubmitting,
|
|
170
|
+
disabled,
|
|
171
|
+
status,
|
|
172
|
+
sideDialogContext,
|
|
173
|
+
pluginActions
|
|
174
|
+
}: ActionsViewProps<M>) {
|
|
175
|
+
|
|
176
|
+
return <div
|
|
177
|
+
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)}>
|
|
178
|
+
<LoadingButton fullWidth={true} variant="filled" color="primary" type="submit" size={"large"}
|
|
179
|
+
disabled={disabled || isSubmitting} onClick={() => {
|
|
180
|
+
sideDialogContext.setPendingClose?.(false);
|
|
181
|
+
}}>
|
|
182
|
+
{status === "existing" && "Save"}
|
|
183
|
+
{status === "copy" && "Create copy"}
|
|
184
|
+
{status === "new" && "Create"}
|
|
185
|
+
</LoadingButton>
|
|
186
|
+
<Button fullWidth={true} variant="text" disabled={disabled || isSubmitting} type="reset">
|
|
187
|
+
{status === "existing" ? "Discard" : "Clear"}
|
|
188
|
+
</Button>
|
|
189
|
+
|
|
190
|
+
{pluginActions}
|
|
191
|
+
|
|
192
|
+
{savingError &&
|
|
193
|
+
<div className="text-right">
|
|
194
|
+
<Typography color={"error"}>{savingError.message}</Typography>
|
|
195
|
+
</div>
|
|
196
|
+
}
|
|
197
|
+
</div>;
|
|
198
|
+
}
|
|
@@ -31,6 +31,9 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
31
31
|
|
|
32
32
|
const sideEntityController = useSideEntityController();
|
|
33
33
|
const navigationController = useNavigationController();
|
|
34
|
+
const sideDialogsController = useSideDialogContext();
|
|
35
|
+
|
|
36
|
+
console.log("sideDialogsController", sideDialogsController);
|
|
34
37
|
|
|
35
38
|
const onClose = () => {
|
|
36
39
|
if (props.onClose) {
|
|
@@ -55,6 +58,11 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
55
58
|
});
|
|
56
59
|
}
|
|
57
60
|
|
|
61
|
+
if (sideDialogsController.pendingClose) {
|
|
62
|
+
sideDialogsController.setPendingClose(false);
|
|
63
|
+
onClose();
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
const parentCollectionIds = useMemo(() => {
|
|
@@ -113,7 +121,6 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
113
121
|
collection={collection}
|
|
114
122
|
parentCollectionIds={parentCollectionIds}
|
|
115
123
|
onValuesModified={onValuesModified}
|
|
116
|
-
onClose={onClose}
|
|
117
124
|
onSaved={onUpdate}
|
|
118
125
|
barActions={<>
|
|
119
126
|
<IconButton
|
package/src/core/SideDialogs.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useContext, useEffect, useState } from "react";
|
|
1
|
+
import React, { useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
2
2
|
import { useSideDialogsController } from "../hooks";
|
|
3
3
|
import { SideDialogPanelProps } from "../types";
|
|
4
4
|
import { Sheet } from "@firecms/ui";
|
|
@@ -6,15 +6,17 @@ import { useNavigationUnsavedChangesDialog } from "../internal/useUnsavedChanges
|
|
|
6
6
|
import { ErrorBoundary } from "../components";
|
|
7
7
|
import { UnsavedChangesDialog } from "../components/UnsavedChangesDialog";
|
|
8
8
|
|
|
9
|
-
export type
|
|
9
|
+
export type SideDialogController = {
|
|
10
10
|
blocked: boolean,
|
|
11
11
|
setBlocked: (blocked: boolean) => void,
|
|
12
12
|
setBlockedNavigationMessage: (message?: React.ReactNode) => void,
|
|
13
13
|
width?: string,
|
|
14
|
-
close: (force?: boolean) => void
|
|
14
|
+
close: (force?: boolean) => void;
|
|
15
|
+
pendingClose: boolean,
|
|
16
|
+
setPendingClose: (pendingClose: boolean) => void
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
const SideDialogContext = React.createContext<
|
|
19
|
+
const SideDialogContext = React.createContext<SideDialogController>({
|
|
18
20
|
width: "",
|
|
19
21
|
blocked: false,
|
|
20
22
|
setBlocked: (blocked: boolean) => {
|
|
@@ -22,6 +24,10 @@ const SideDialogContext = React.createContext<SideDialogContextProps>({
|
|
|
22
24
|
setBlockedNavigationMessage: (message?: React.ReactNode) => {
|
|
23
25
|
},
|
|
24
26
|
close: () => {
|
|
27
|
+
},
|
|
28
|
+
pendingClose: false,
|
|
29
|
+
setPendingClose: () => {
|
|
30
|
+
|
|
25
31
|
}
|
|
26
32
|
});
|
|
27
33
|
|
|
@@ -30,7 +36,7 @@ const SideDialogContext = React.createContext<SideDialogContextProps>({
|
|
|
30
36
|
* in contrast with {@link useSideDialogsController} which handles the
|
|
31
37
|
* state of all the dialogs.
|
|
32
38
|
*/
|
|
33
|
-
export const useSideDialogContext = () => useContext<
|
|
39
|
+
export const useSideDialogContext = () => useContext<SideDialogController>(SideDialogContext);
|
|
34
40
|
|
|
35
41
|
/**
|
|
36
42
|
* This is the component in charge of rendering the side dialogs used
|
|
@@ -73,6 +79,8 @@ function SideDialogView({
|
|
|
73
79
|
const [blocked, setBlocked] = useState(false);
|
|
74
80
|
const [blockedNavigationMessage, setBlockedNavigationMessage] = useState<React.ReactNode | undefined>();
|
|
75
81
|
|
|
82
|
+
const [pendingClose, setPendingClose] = useState(false);
|
|
83
|
+
|
|
76
84
|
const widthRef = React.useRef<string | undefined>(panel?.width);
|
|
77
85
|
const width = widthRef.current;
|
|
78
86
|
|
|
@@ -119,19 +127,15 @@ function SideDialogView({
|
|
|
119
127
|
setBlocked,
|
|
120
128
|
setBlockedNavigationMessage,
|
|
121
129
|
width,
|
|
122
|
-
close: onCloseRequest
|
|
130
|
+
close: onCloseRequest,
|
|
131
|
+
pendingClose,
|
|
132
|
+
setPendingClose
|
|
123
133
|
}}>
|
|
124
134
|
|
|
125
135
|
<Sheet
|
|
126
136
|
open={Boolean(panel)}
|
|
127
137
|
onOpenChange={(open) => !open && onCloseRequest()}
|
|
128
138
|
title={"Side dialog " + panel?.key}
|
|
129
|
-
// style={{
|
|
130
|
-
// zIndex: offsetPosition * 20 + 20,
|
|
131
|
-
// }}
|
|
132
|
-
// overlayStyle={{
|
|
133
|
-
// zIndex: offsetPosition * 20 + 10,
|
|
134
|
-
// }}
|
|
135
139
|
>
|
|
136
140
|
{panel &&
|
|
137
141
|
<div
|