@firecms/core 3.0.0-canary.197 → 3.0.0-canary.199
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 +3 -1
- package/dist/core/EntityEditViewFormActions.d.ts +1 -1
- package/dist/form/EntityForm.d.ts +13 -5
- package/dist/form/EntityFormActions.d.ts +1 -0
- package/dist/index.es.js +105 -74
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +105 -74
- package/dist/index.umd.js.map +1 -1
- package/dist/types/side_entity_controller.d.ts +5 -0
- package/dist/util/navigation_from_path.d.ts +1 -0
- package/package.json +5 -5
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +1 -1
- package/src/core/EntityEditView.tsx +26 -10
- package/src/core/EntityEditViewFormActions.tsx +6 -5
- package/src/core/EntitySidePanel.tsx +1 -2
- package/src/form/EntityForm.tsx +94 -82
- package/src/form/EntityFormActions.tsx +1 -0
- package/src/internal/useBuildSideEntityController.tsx +1 -2
- package/src/routes/FireCMSRoute.tsx +14 -1
- package/src/types/side_dialogs_controller.tsx +2 -0
- package/src/types/side_entity_controller.tsx +5 -0
- package/src/util/navigation_from_path.ts +4 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EntityCollection } from "./collections";
|
|
2
2
|
import { ResolvedEntityCollection } from "./resolved_entities";
|
|
3
3
|
import { Entity } from "./entities";
|
|
4
|
+
import { EntityFormProps } from "../form";
|
|
4
5
|
/**
|
|
5
6
|
* Props used to open a side dialog
|
|
6
7
|
* @group Hooks and utilities
|
|
@@ -55,6 +56,10 @@ export interface EntitySidePanelProps<M extends Record<string, any> = any> {
|
|
|
55
56
|
* Should this panel close when saving
|
|
56
57
|
*/
|
|
57
58
|
closeOnSave?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Override some form properties
|
|
61
|
+
*/
|
|
62
|
+
formProps?: Partial<EntityFormProps<M>>;
|
|
58
63
|
}
|
|
59
64
|
/**
|
|
60
65
|
* Controller to open the side dialog displaying entity forms
|
|
@@ -18,6 +18,7 @@ export interface NavigationViewEntityCustomInternal<M extends Record<string, any
|
|
|
18
18
|
type: "custom_view";
|
|
19
19
|
path: string;
|
|
20
20
|
fullPath: string;
|
|
21
|
+
entityId: string;
|
|
21
22
|
view: EntityCustomView<M>;
|
|
22
23
|
}
|
|
23
24
|
export declare function getNavigationEntriesFromPath(props: {
|
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.199",
|
|
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.199",
|
|
54
|
+
"@firecms/formex": "^3.0.0-canary.199",
|
|
55
|
+
"@firecms/ui": "^3.0.0-canary.199",
|
|
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": "c61e0a8c9aaf3e671612490547db2254b4729b50",
|
|
108
108
|
"publishConfig": {
|
|
109
109
|
"access": "public"
|
|
110
110
|
},
|
|
@@ -348,7 +348,7 @@ export const EntityCollectionView = React.memo(
|
|
|
348
348
|
const updatedValues = setIn({ ...entity.values }, propertyKey, value);
|
|
349
349
|
|
|
350
350
|
const saveProps: SaveEntityProps = {
|
|
351
|
-
path: fullPath,
|
|
351
|
+
path: entity.path ?? fullPath,
|
|
352
352
|
entityId: entity.id,
|
|
353
353
|
values: updatedValues,
|
|
354
354
|
previousValues: entity.values,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
} from "../hooks";
|
|
14
14
|
import { CircularProgress, cls, defaultBorderMixin, Tab, Tabs, Typography } from "@firecms/ui";
|
|
15
15
|
import { getEntityFromCache } from "../util/entity_cache";
|
|
16
|
-
import { EntityForm, FormLayoutInner } from "../form";
|
|
16
|
+
import { EntityForm, EntityFormProps, FormLayoutInner } from "../form";
|
|
17
17
|
import { EntityEditViewFormActions } from "./EntityEditViewFormActions";
|
|
18
18
|
|
|
19
19
|
const MAIN_TAB_VALUE = "main_##Q$SC^#S6";
|
|
@@ -47,6 +47,7 @@ export interface EntityEditViewProps<M extends Record<string, any>> {
|
|
|
47
47
|
onTabChange?: (props: OnTabChangeParams<M>) => void;
|
|
48
48
|
layout?: "side_panel" | "full_screen";
|
|
49
49
|
barActions?: React.ReactNode;
|
|
50
|
+
formProps?: Partial<EntityFormProps<M>>
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
/**
|
|
@@ -172,6 +173,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
172
173
|
barActions,
|
|
173
174
|
status,
|
|
174
175
|
setStatus,
|
|
176
|
+
formProps,
|
|
175
177
|
}: EntityEditViewProps<M> & {
|
|
176
178
|
entity?: Entity<M>,
|
|
177
179
|
cachedDirtyValues?: Partial<M>, // dirty cached entity in memory
|
|
@@ -331,20 +333,34 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
331
333
|
path={path}
|
|
332
334
|
entityId={entityId ?? usedEntity?.id}
|
|
333
335
|
onValuesModified={onValuesModified}
|
|
334
|
-
onSaved={onSaved ? (params) => onSaved({
|
|
335
|
-
...params,
|
|
336
|
-
selectedTab: MAIN_TAB_VALUE === selectedTab ? undefined : selectedTab,
|
|
337
|
-
}) : undefined}
|
|
338
336
|
entity={entity}
|
|
339
|
-
|
|
337
|
+
initialDirtyValues={cachedDirtyValues}
|
|
340
338
|
openEntityMode={layout}
|
|
341
|
-
onFormContextReady={setFormContext}
|
|
342
339
|
forceActionsAtTheBottom={actionsAtTheBottom}
|
|
343
340
|
initialStatus={status}
|
|
344
|
-
|
|
345
|
-
className={!mainViewVisible ? "hidden" : ""}
|
|
341
|
+
className={cls(!mainViewVisible ? "hidden" : "", formProps?.className)}
|
|
346
342
|
EntityFormActionsComponent={EntityEditViewFormActions}
|
|
347
|
-
|
|
343
|
+
{...formProps}
|
|
344
|
+
onEntityChange={(entity) => {
|
|
345
|
+
setUsedEntity(entity);
|
|
346
|
+
formProps?.onEntityChange?.(entity);
|
|
347
|
+
}}
|
|
348
|
+
onStatusChange={(status) => {
|
|
349
|
+
setStatus(status);
|
|
350
|
+
formProps?.onStatusChange?.(status);
|
|
351
|
+
}}
|
|
352
|
+
onFormContextReady={(formContext) => {
|
|
353
|
+
setFormContext(formContext);
|
|
354
|
+
formProps?.onFormContextReady?.(formContext);
|
|
355
|
+
}}
|
|
356
|
+
onSaved={(params) => {
|
|
357
|
+
const res = {
|
|
358
|
+
...params,
|
|
359
|
+
selectedTab: MAIN_TAB_VALUE === selectedTab ? undefined : selectedTab,
|
|
360
|
+
};
|
|
361
|
+
onSaved?.(res);
|
|
362
|
+
formProps?.onSaved?.(res);
|
|
363
|
+
}}
|
|
348
364
|
/>;
|
|
349
365
|
|
|
350
366
|
const subcollectionTabs = subcollections && subcollections.map((subcollection) =>
|
|
@@ -18,7 +18,8 @@ export function EntityEditViewFormActions({
|
|
|
18
18
|
disabled,
|
|
19
19
|
status,
|
|
20
20
|
pluginActions,
|
|
21
|
-
openEntityMode
|
|
21
|
+
openEntityMode,
|
|
22
|
+
showDefaultActions = true
|
|
22
23
|
}: EntityFormActionsProps) {
|
|
23
24
|
|
|
24
25
|
const authController = useAuthController();
|
|
@@ -40,7 +41,7 @@ export function EntityEditViewFormActions({
|
|
|
40
41
|
return actions;
|
|
41
42
|
}, [authController, collection, path]);
|
|
42
43
|
|
|
43
|
-
const formActions = entityActions.filter(a => a.includeInForm === undefined || a.includeInForm);
|
|
44
|
+
const formActions = showDefaultActions ? entityActions.filter(a => a.includeInForm === undefined || a.includeInForm) : [];
|
|
44
45
|
|
|
45
46
|
return layout === "bottom"
|
|
46
47
|
? buildBottomActions({
|
|
@@ -55,7 +56,7 @@ export function EntityEditViewFormActions({
|
|
|
55
56
|
status,
|
|
56
57
|
sideDialogContext,
|
|
57
58
|
pluginActions,
|
|
58
|
-
openEntityMode
|
|
59
|
+
openEntityMode,
|
|
59
60
|
})
|
|
60
61
|
: buildSideActions({
|
|
61
62
|
savingError,
|
|
@@ -69,7 +70,7 @@ export function EntityEditViewFormActions({
|
|
|
69
70
|
disabled,
|
|
70
71
|
status,
|
|
71
72
|
pluginActions,
|
|
72
|
-
openEntityMode
|
|
73
|
+
openEntityMode,
|
|
73
74
|
});
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -100,7 +101,7 @@ function buildBottomActions<M extends object>({
|
|
|
100
101
|
status,
|
|
101
102
|
sideDialogContext,
|
|
102
103
|
pluginActions,
|
|
103
|
-
openEntityMode
|
|
104
|
+
openEntityMode,
|
|
104
105
|
}: ActionsViewProps<M>) {
|
|
105
106
|
|
|
106
107
|
const canClose = openEntityMode === "side_panel";
|
|
@@ -33,8 +33,6 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
33
33
|
const navigationController = useNavigationController();
|
|
34
34
|
const sideDialogsController = useSideDialogContext();
|
|
35
35
|
|
|
36
|
-
console.log("sideDialogsController", sideDialogsController);
|
|
37
|
-
|
|
38
36
|
const onClose = () => {
|
|
39
37
|
if (props.onClose) {
|
|
40
38
|
props.onClose();
|
|
@@ -153,6 +151,7 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
153
151
|
collection
|
|
154
152
|
});
|
|
155
153
|
}}
|
|
154
|
+
formProps={props.formProps}
|
|
156
155
|
/>
|
|
157
156
|
</ErrorBoundary>
|
|
158
157
|
|
package/src/form/EntityForm.tsx
CHANGED
|
@@ -25,11 +25,9 @@ import {
|
|
|
25
25
|
|
|
26
26
|
import {
|
|
27
27
|
saveEntityWithCallbacks,
|
|
28
|
-
useAuthController,
|
|
29
28
|
useCustomizationController,
|
|
30
29
|
useDataSource,
|
|
31
|
-
useFireCMSContext,
|
|
32
|
-
useSideEntityController,
|
|
30
|
+
useFireCMSContext,
|
|
33
31
|
useSnackbarController
|
|
34
32
|
} from "../hooks";
|
|
35
33
|
import { Alert, CheckIcon, Chip, cls, EditIcon, NotesIcon, paperMixin, Tooltip, Typography } from "@firecms/ui";
|
|
@@ -42,7 +40,6 @@ import { CustomIdField } from "../form/components/CustomIdField";
|
|
|
42
40
|
import { ErrorFocus } from "../form/components/ErrorFocus";
|
|
43
41
|
import { CustomFieldValidator, getYupEntitySchema } from "../form/validation";
|
|
44
42
|
import { EntityFormActions, EntityFormActionsProps } from "./EntityFormActions";
|
|
45
|
-
import { useSideDialogContext } from "../core";
|
|
46
43
|
|
|
47
44
|
export type OnUpdateParams = {
|
|
48
45
|
entity: Entity<any>,
|
|
@@ -53,7 +50,7 @@ export type OnUpdateParams = {
|
|
|
53
50
|
collection: EntityCollection<any>
|
|
54
51
|
};
|
|
55
52
|
|
|
56
|
-
type EntityFormProps<M extends Record<string, any>> = {
|
|
53
|
+
export type EntityFormProps<M extends Record<string, any>> = {
|
|
57
54
|
path: string;
|
|
58
55
|
collection: EntityCollection<M>;
|
|
59
56
|
entityId?: string;
|
|
@@ -62,7 +59,7 @@ type EntityFormProps<M extends Record<string, any>> = {
|
|
|
62
59
|
onIdChange?: (id: string) => void;
|
|
63
60
|
onValuesModified?: (modified: boolean) => void;
|
|
64
61
|
onSaved?: (params: OnUpdateParams) => void;
|
|
65
|
-
|
|
62
|
+
initialDirtyValues?: Partial<M>; // dirty cached entity in memory
|
|
66
63
|
onFormContextReady?: (formContext: FormContext) => void;
|
|
67
64
|
forceActionsAtTheBottom?: boolean;
|
|
68
65
|
className?: string;
|
|
@@ -71,6 +68,16 @@ type EntityFormProps<M extends Record<string, any>> = {
|
|
|
71
68
|
onEntityChange?: (entity: Entity<M>) => void;
|
|
72
69
|
formex?: FormexController<M>;
|
|
73
70
|
openEntityMode?: "side_panel" | "full_screen";
|
|
71
|
+
/**
|
|
72
|
+
* Include the copy and delete actions in the form
|
|
73
|
+
*/
|
|
74
|
+
showDefaultActions?: boolean;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Display the entity path in the form
|
|
78
|
+
*/
|
|
79
|
+
showEntityPath?: boolean;
|
|
80
|
+
|
|
74
81
|
EntityFormActionsComponent?: React.FC<EntityFormActionsProps>;
|
|
75
82
|
};
|
|
76
83
|
|
|
@@ -82,7 +89,7 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
82
89
|
onIdChange,
|
|
83
90
|
onSaved,
|
|
84
91
|
entity,
|
|
85
|
-
|
|
92
|
+
initialDirtyValues,
|
|
86
93
|
onFormContextReady,
|
|
87
94
|
forceActionsAtTheBottom,
|
|
88
95
|
initialStatus,
|
|
@@ -91,7 +98,9 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
91
98
|
onEntityChange,
|
|
92
99
|
openEntityMode = "full_screen",
|
|
93
100
|
formex: formexProp,
|
|
94
|
-
EntityFormActionsComponent = EntityFormActions
|
|
101
|
+
EntityFormActionsComponent = EntityFormActions,
|
|
102
|
+
showDefaultActions = true,
|
|
103
|
+
showEntityPath = true
|
|
95
104
|
}: EntityFormProps<M>) {
|
|
96
105
|
|
|
97
106
|
if (collection.customId && collection.formAutoSave) {
|
|
@@ -186,8 +195,8 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
186
195
|
};
|
|
187
196
|
|
|
188
197
|
const formex: FormexController<M> = formexProp ?? useCreateFormex<M>({
|
|
189
|
-
initialValues: (
|
|
190
|
-
initialDirty: Boolean(
|
|
198
|
+
initialValues: (initialDirtyValues ?? getInitialEntityValues(collection, path, status, entity)) as M,
|
|
199
|
+
initialDirty: Boolean(initialDirtyValues),
|
|
191
200
|
onSubmit,
|
|
192
201
|
onReset: () => {
|
|
193
202
|
clearDirtyCache();
|
|
@@ -485,77 +494,76 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
485
494
|
const formFieldKeys = getFormFieldKeys(resolvedCollection);
|
|
486
495
|
|
|
487
496
|
const formFields = () => (
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
497
|
+
<FormLayout>
|
|
498
|
+
{formFieldKeys.map((key) => {
|
|
499
|
+
const property = resolvedCollection.properties[key];
|
|
500
|
+
if (property) {
|
|
501
|
+
const underlyingValueHasChanged: boolean =
|
|
502
|
+
!!underlyingChanges &&
|
|
503
|
+
Object.keys(underlyingChanges).includes(key) &&
|
|
504
|
+
formex.touched[key];
|
|
505
|
+
const disabled = (!autoSave && formex.isSubmitting) || isReadOnly(property) || Boolean(property.disabled);
|
|
506
|
+
const hidden = isHidden(property);
|
|
507
|
+
if (hidden) return null;
|
|
508
|
+
const widthPercentage = property.widthPercentage ?? 100;
|
|
509
|
+
const cmsFormFieldProps: PropertyFieldBindingProps<any, M> = {
|
|
510
|
+
propertyKey: key,
|
|
511
|
+
disabled,
|
|
512
|
+
property,
|
|
513
|
+
includeDescription: property.description || property.longDescription,
|
|
514
|
+
underlyingValueHasChanged: underlyingValueHasChanged && !autoSave,
|
|
515
|
+
context: formContext,
|
|
516
|
+
partOfArray: false,
|
|
517
|
+
minimalistView: false,
|
|
518
|
+
autoFocus: false
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
return (
|
|
522
|
+
<FormEntry propertyKey={key}
|
|
523
|
+
widthPercentage={widthPercentage}
|
|
524
|
+
key={`field_${key}`}>
|
|
525
|
+
<PropertyFieldBinding {...cmsFormFieldProps} />
|
|
526
|
+
</FormEntry>
|
|
527
|
+
);
|
|
528
|
+
}
|
|
520
529
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
}
|
|
527
|
-
const child = Builder
|
|
528
|
-
? <Builder entity={entity} context={context}/>
|
|
529
|
-
: <div className={"w-full"}>
|
|
530
|
-
{additionalField.value?.({
|
|
531
|
-
entity,
|
|
532
|
-
context
|
|
533
|
-
})?.toString()}
|
|
534
|
-
</div>;
|
|
535
|
-
|
|
536
|
-
return (
|
|
537
|
-
<div key={`additional_${key}`} className={"w-full"}>
|
|
538
|
-
<LabelWithIconAndTooltip
|
|
539
|
-
propertyKey={key}
|
|
540
|
-
icon={<NotesIcon size={"small"}/>}
|
|
541
|
-
title={additionalField.name}
|
|
542
|
-
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
543
|
-
<div
|
|
544
|
-
className={cls(paperMixin, "w-full min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
|
|
545
|
-
<ErrorBoundary>
|
|
546
|
-
{child}
|
|
547
|
-
</ErrorBoundary>
|
|
548
|
-
</div>
|
|
549
|
-
</div>
|
|
550
|
-
);
|
|
530
|
+
const additionalField = resolvedCollection.additionalFields?.find(f => f.key === key);
|
|
531
|
+
if (additionalField && entity) {
|
|
532
|
+
const Builder = additionalField.Builder;
|
|
533
|
+
if (!Builder && !additionalField.value) {
|
|
534
|
+
throw new Error("When using additional fields you need to provide a Builder or a value");
|
|
551
535
|
}
|
|
536
|
+
const child = Builder
|
|
537
|
+
? <Builder entity={entity} context={context}/>
|
|
538
|
+
: <div className={"w-full"}>
|
|
539
|
+
{additionalField.value?.({
|
|
540
|
+
entity,
|
|
541
|
+
context
|
|
542
|
+
})?.toString()}
|
|
543
|
+
</div>;
|
|
544
|
+
|
|
545
|
+
return (
|
|
546
|
+
<div key={`additional_${key}`} className={"w-full"}>
|
|
547
|
+
<LabelWithIconAndTooltip
|
|
548
|
+
propertyKey={key}
|
|
549
|
+
icon={<NotesIcon size={"small"}/>}
|
|
550
|
+
title={additionalField.name}
|
|
551
|
+
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
552
|
+
<div
|
|
553
|
+
className={cls(paperMixin, "w-full min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
|
|
554
|
+
<ErrorBoundary>
|
|
555
|
+
{child}
|
|
556
|
+
</ErrorBoundary>
|
|
557
|
+
</div>
|
|
558
|
+
</div>
|
|
559
|
+
);
|
|
560
|
+
}
|
|
552
561
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
;
|
|
562
|
+
console.warn(`Property ${key} not found in collection ${resolvedCollection.name} in properties or additional fields. Skipping.`);
|
|
563
|
+
return null;
|
|
564
|
+
}).filter(Boolean)}
|
|
565
|
+
</FormLayout>
|
|
566
|
+
);
|
|
559
567
|
|
|
560
568
|
const formRef = useRef<HTMLDivElement>(null);
|
|
561
569
|
|
|
@@ -567,12 +575,12 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
567
575
|
variant={"h4"}>
|
|
568
576
|
{title ?? collection.singularName ?? collection.name}
|
|
569
577
|
</Typography>
|
|
570
|
-
<Alert color={"base"} className={"w-full"} size={"small"}>
|
|
578
|
+
{showEntityPath && <Alert color={"base"} className={"w-full"} size={"small"}>
|
|
571
579
|
<code
|
|
572
580
|
className={"text-xs select-all text-text-secondary dark:text-text-secondary-dark"}>
|
|
573
581
|
{entity?.path ?? path}/{entityId}
|
|
574
582
|
</code>
|
|
575
|
-
</Alert>
|
|
583
|
+
</Alert>}
|
|
576
584
|
</div>
|
|
577
585
|
|
|
578
586
|
{!collection.hideIdFromForm &&
|
|
@@ -608,7 +616,8 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
608
616
|
pluginActions={pluginActions}
|
|
609
617
|
forceActionsAtTheBottom={forceActionsAtTheBottom}
|
|
610
618
|
EntityFormActionsComponent={EntityFormActionsComponent}
|
|
611
|
-
formContext={formContext}
|
|
619
|
+
formContext={formContext}
|
|
620
|
+
showDefaultActions={showDefaultActions}>
|
|
612
621
|
{formView}
|
|
613
622
|
</FormLayoutInner>
|
|
614
623
|
);
|
|
@@ -661,7 +670,8 @@ export function FormLayoutInner({
|
|
|
661
670
|
className,
|
|
662
671
|
forceActionsAtTheBottom,
|
|
663
672
|
pluginActions,
|
|
664
|
-
EntityFormActionsComponent
|
|
673
|
+
EntityFormActionsComponent,
|
|
674
|
+
showDefaultActions
|
|
665
675
|
}: {
|
|
666
676
|
id?: string,
|
|
667
677
|
formContext: FormContext,
|
|
@@ -670,6 +680,7 @@ export function FormLayoutInner({
|
|
|
670
680
|
forceActionsAtTheBottom?: boolean,
|
|
671
681
|
pluginActions?: React.ReactNode[],
|
|
672
682
|
EntityFormActionsComponent: React.FC<EntityFormActionsProps>;
|
|
683
|
+
showDefaultActions?: boolean;
|
|
673
684
|
}) {
|
|
674
685
|
|
|
675
686
|
const formex = formContext.formex;
|
|
@@ -696,6 +707,7 @@ export function FormLayoutInner({
|
|
|
696
707
|
status={status}
|
|
697
708
|
pluginActions={pluginActions ?? []}
|
|
698
709
|
openEntityMode={openEntityMode}
|
|
710
|
+
showDefaultActions={showDefaultActions}
|
|
699
711
|
/>;
|
|
700
712
|
|
|
701
713
|
return (
|
|
@@ -104,12 +104,10 @@ export const useBuildSideEntityController = (navigation: NavigationController,
|
|
|
104
104
|
const panelsFromUrl = buildSidePanelsFromUrl(entityOrCollectionPath, navigation.collections ?? [], newFlag);
|
|
105
105
|
for (let i = 0; i < panelsFromUrl.length; i++) {
|
|
106
106
|
const props = panelsFromUrl[i];
|
|
107
|
-
// setTimeout(() => {
|
|
108
107
|
if (i === 0)
|
|
109
108
|
sideDialogsController.replace(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout));
|
|
110
109
|
else
|
|
111
110
|
sideDialogsController.open(propsToSidePanel(props, navigation.buildUrlCollectionPath, navigation.resolveIdsFrom, smallLayout))
|
|
112
|
-
// }, 1);
|
|
113
111
|
}
|
|
114
112
|
}
|
|
115
113
|
initialised.current = true;
|
|
@@ -260,6 +258,7 @@ const propsToSidePanel = (props: EntitySidePanelProps,
|
|
|
260
258
|
const resolvedPanelProps: EntitySidePanelProps<any> = {
|
|
261
259
|
...props,
|
|
262
260
|
path: resolvedPath,
|
|
261
|
+
formProps: props.formProps
|
|
263
262
|
};
|
|
264
263
|
|
|
265
264
|
const entityViewWidth = getEntityViewWidth(props, smallLayout);
|
|
@@ -107,6 +107,19 @@ export function FireCMSRoute() {
|
|
|
107
107
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
function getSelectedTabFromUrl(isNew: boolean, lastCustomView: NavigationViewCollectionInternal<any> | NavigationViewEntityCustomInternal<any> | undefined) {
|
|
111
|
+
if (isNew) {
|
|
112
|
+
return undefined;
|
|
113
|
+
} else if (lastCustomView) {
|
|
114
|
+
if (lastCustomView.type === "custom_view") {
|
|
115
|
+
return lastCustomView.view.key;
|
|
116
|
+
} else if (lastCustomView.type === "collection") {
|
|
117
|
+
return lastCustomView.id ?? lastCustomView.path;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
110
123
|
function EntityFullScreenRoute({
|
|
111
124
|
pathname,
|
|
112
125
|
navigationEntries,
|
|
@@ -136,7 +149,7 @@ function EntityFullScreenRoute({
|
|
|
136
149
|
|
|
137
150
|
const entityId = lastEntityEntry?.entityId;
|
|
138
151
|
|
|
139
|
-
const urlTab = isNew
|
|
152
|
+
const urlTab = getSelectedTabFromUrl(isNew, lastCustomView);
|
|
140
153
|
const [selectedTab, setSelectedTab] = useState<string | undefined>(urlTab);
|
|
141
154
|
|
|
142
155
|
const parentCollectionIds = navigation.getParentCollectionIds(navigationPath);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { EntityFormProps } from "../form";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Controller to open the side dialog
|
|
@@ -78,4 +79,5 @@ export interface SideDialogPanelProps {
|
|
|
78
79
|
* Use this prop to store additional data in the panel
|
|
79
80
|
*/
|
|
80
81
|
additional?: any;
|
|
82
|
+
|
|
81
83
|
}
|
|
@@ -2,6 +2,7 @@ import { EntityCollection } from "./collections";
|
|
|
2
2
|
import { ResolvedEntityCollection } from "./resolved_entities";
|
|
3
3
|
import { Entity } from "./entities";
|
|
4
4
|
import { EntityOverrides } from "./entity_overrides";
|
|
5
|
+
import { EntityFormProps } from "../form";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Props used to open a side dialog
|
|
@@ -66,6 +67,10 @@ export interface EntitySidePanelProps<M extends Record<string, any> = any> {
|
|
|
66
67
|
*/
|
|
67
68
|
closeOnSave?: boolean;
|
|
68
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Override some form properties
|
|
72
|
+
*/
|
|
73
|
+
formProps?: Partial<EntityFormProps<M>>;
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
/**
|
|
@@ -27,6 +27,7 @@ export interface NavigationViewEntityCustomInternal<M extends Record<string, any
|
|
|
27
27
|
type: "custom_view";
|
|
28
28
|
path: string;
|
|
29
29
|
fullPath: string;
|
|
30
|
+
entityId: string;
|
|
30
31
|
view: EntityCustomView<M>;
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -88,13 +89,11 @@ export function getNavigationEntriesFromPath(props: {
|
|
|
88
89
|
.filter(Boolean)
|
|
89
90
|
.find((entry) => entry!.key === newPath);
|
|
90
91
|
if (customView) {
|
|
91
|
-
const path = currentFullPath && currentFullPath.length > 0
|
|
92
|
-
? (currentFullPath + "/" + customView.key)
|
|
93
|
-
: customView.key;
|
|
94
92
|
result.push({
|
|
95
93
|
type: "custom_view",
|
|
96
|
-
path,
|
|
97
|
-
|
|
94
|
+
path: collectionPath,
|
|
95
|
+
entityId: entityId,
|
|
96
|
+
fullPath: fullPath + "/" + customView.key,
|
|
98
97
|
view: customView
|
|
99
98
|
});
|
|
100
99
|
} else if (collection.subcollections) {
|