@firecms/core 3.0.0-canary.203 → 3.0.0-canary.205
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/form/EntityForm.d.ts +3 -12
- package/dist/index.es.js +205 -485
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +205 -485
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildSideEntityController.d.ts +2 -2
- package/dist/util/resolutions.d.ts +6 -1
- package/package.json +5 -5
- package/src/core/EntityEditView.tsx +17 -69
- package/src/core/EntitySidePanel.tsx +2 -2
- package/src/form/EntityForm.tsx +138 -165
- package/src/internal/useBuildSideEntityController.tsx +28 -14
- package/src/util/resolutions.ts +26 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityCollection, EntitySidePanelProps, NavigationController, SideDialogsController, SideEntityController } from "../types";
|
|
2
|
-
export declare function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean): string;
|
|
1
|
+
import { CustomizationController, EntityCollection, EntitySidePanelProps, NavigationController, SideDialogsController, SideEntityController } from "../types";
|
|
2
|
+
export declare function getEntityViewWidth(props: EntitySidePanelProps<any>, small: boolean, customizationController: CustomizationController): string;
|
|
3
3
|
export declare const useBuildSideEntityController: (navigation: NavigationController, sideDialogsController: SideDialogsController) => SideEntityController;
|
|
4
4
|
export declare function buildSidePanelsFromUrl(path: string, collections: EntityCollection[], newFlag: boolean): EntitySidePanelProps<any>[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrayProperty, CMSType, EntityCollection, EntityCustomView, EntityValues, EnumValueConfig, EnumValues, NumberProperty, PropertiesOrBuilders, PropertyConfig, PropertyOrBuilder, ResolvedArrayProperty, ResolvedEntityCollection, ResolvedNumberProperty, ResolvedProperties, ResolvedProperty, ResolvedStringProperty, StringProperty, UserConfigurationPersistence } from "../types";
|
|
1
|
+
import { ArrayProperty, CMSType, CustomizationController, EntityCollection, EntityCustomView, EntityValues, EnumValueConfig, EnumValues, NumberProperty, PropertiesOrBuilders, PropertyConfig, PropertyOrBuilder, ResolvedArrayProperty, ResolvedEntityCollection, ResolvedNumberProperty, ResolvedProperties, ResolvedProperty, ResolvedStringProperty, StringProperty, UserConfigurationPersistence } from "../types";
|
|
2
2
|
export declare const resolveCollection: <M extends Record<string, any>>({ collection, path, entityId, values, previousValues, userConfigPersistence, propertyConfigs, ignoreMissingFields }: {
|
|
3
3
|
collection: EntityCollection<M> | ResolvedEntityCollection<M>;
|
|
4
4
|
path: string;
|
|
@@ -76,3 +76,8 @@ export declare function resolveProperties<M extends Record<string, any>>({ prope
|
|
|
76
76
|
export declare function resolvePropertyEnum(property: StringProperty | NumberProperty, fromBuilder?: boolean): ResolvedStringProperty | ResolvedNumberProperty;
|
|
77
77
|
export declare function resolveEnumValues(input: EnumValues): EnumValueConfig[] | undefined;
|
|
78
78
|
export declare function resolveEntityView(entityView: string | EntityCustomView<any>, contextEntityViews?: EntityCustomView<any>[]): EntityCustomView<any> | undefined;
|
|
79
|
+
export declare function resolvedSelectedEntityView<M extends Record<string, any>>(customViews: (string | EntityCustomView<M>)[] | undefined, customizationController: CustomizationController, selectedTab?: string): {
|
|
80
|
+
resolvedEntityViews: EntityCustomView[];
|
|
81
|
+
selectedEntityView: EntityCustomView | undefined;
|
|
82
|
+
selectedSecondaryForm: EntityCustomView | undefined;
|
|
83
|
+
};
|
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.205",
|
|
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.205",
|
|
54
|
+
"@firecms/formex": "^3.0.0-canary.205",
|
|
55
|
+
"@firecms/ui": "^3.0.0-canary.205",
|
|
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": "b3a2a795ce5eb7edc68efea5caa69b8d477901be",
|
|
108
108
|
"publishConfig": {
|
|
109
109
|
"access": "public"
|
|
110
110
|
},
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import React, { useEffect, useMemo, useState } from "react";
|
|
2
|
-
import { Entity, EntityCollection,
|
|
2
|
+
import { Entity, EntityCollection, EntityStatus, FireCMSPlugin, FormContext, User } from "../types";
|
|
3
3
|
|
|
4
4
|
import { CircularProgressCenter, EntityCollectionView, EntityView, ErrorBoundary } from "../components";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
canEditEntity,
|
|
7
|
+
removeInitialAndTrailingSlashes,
|
|
8
|
+
resolveDefaultSelectedView,
|
|
9
|
+
resolvedSelectedEntityView
|
|
10
|
+
} from "../util";
|
|
6
11
|
|
|
7
12
|
import {
|
|
8
13
|
useAuthController,
|
|
@@ -13,7 +18,7 @@ import {
|
|
|
13
18
|
} from "../hooks";
|
|
14
19
|
import { CircularProgress, cls, defaultBorderMixin, Tab, Tabs, Typography } from "@firecms/ui";
|
|
15
20
|
import { getEntityFromCache } from "../util/entity_cache";
|
|
16
|
-
import { EntityForm, EntityFormProps
|
|
21
|
+
import { EntityForm, EntityFormProps } from "../form";
|
|
17
22
|
import { EntityEditViewFormActions } from "./EntityEditViewFormActions";
|
|
18
23
|
|
|
19
24
|
const MAIN_TAB_VALUE = "main_##Q$SC^#S6";
|
|
@@ -120,43 +125,6 @@ export function EntityEditView<M extends Record<string, any>, USER extends User>
|
|
|
120
125
|
/>;
|
|
121
126
|
}
|
|
122
127
|
|
|
123
|
-
function SecondaryForm<M extends object>({
|
|
124
|
-
collection,
|
|
125
|
-
className,
|
|
126
|
-
customView,
|
|
127
|
-
entity,
|
|
128
|
-
formContext,
|
|
129
|
-
forceActionsAtTheBottom,
|
|
130
|
-
}: {
|
|
131
|
-
className?: string,
|
|
132
|
-
customView: EntityCustomView,
|
|
133
|
-
formContext: FormContext<M>,
|
|
134
|
-
collection: EntityCollection<M>,
|
|
135
|
-
forceActionsAtTheBottom?: boolean,
|
|
136
|
-
entity: Entity<M> | undefined,
|
|
137
|
-
}) {
|
|
138
|
-
|
|
139
|
-
if (!customView.Builder) {
|
|
140
|
-
console.error("customView.Builder is not defined");
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return <FormLayoutInner
|
|
145
|
-
className={className}
|
|
146
|
-
forceActionsAtTheBottom={forceActionsAtTheBottom}
|
|
147
|
-
formContext={formContext}
|
|
148
|
-
EntityFormActionsComponent={EntityEditViewFormActions}>
|
|
149
|
-
<ErrorBoundary>
|
|
150
|
-
{formContext && <customView.Builder
|
|
151
|
-
collection={collection}
|
|
152
|
-
entity={entity}
|
|
153
|
-
modifiedValues={formContext.formex.values ?? entity?.values}
|
|
154
|
-
formContext={formContext}
|
|
155
|
-
/>}
|
|
156
|
-
</ErrorBoundary>
|
|
157
|
-
</FormLayoutInner>;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
128
|
export function EntityEditViewInner<M extends Record<string, any>>({
|
|
161
129
|
path,
|
|
162
130
|
entityId,
|
|
@@ -214,42 +182,21 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
214
182
|
}
|
|
215
183
|
}, [selectedTabProp]);
|
|
216
184
|
|
|
217
|
-
const mainViewVisible = selectedTab === MAIN_TAB_VALUE;
|
|
218
|
-
|
|
219
185
|
const subcollections = (collection.subcollections ?? []).filter(c => !c.hideFromNavigation);
|
|
220
186
|
const subcollectionsCount = subcollections?.length ?? 0;
|
|
221
187
|
const customViews = collection.entityViews;
|
|
222
188
|
const customViewsCount = customViews?.length ?? 0;
|
|
223
189
|
const hasAdditionalViews = customViewsCount > 0 || subcollectionsCount > 0;
|
|
224
190
|
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
191
|
+
const {
|
|
192
|
+
resolvedEntityViews,
|
|
193
|
+
selectedEntityView,
|
|
194
|
+
selectedSecondaryForm
|
|
195
|
+
} = resolvedSelectedEntityView(customViews, customizationController, selectedTab);
|
|
229
196
|
|
|
230
|
-
const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
|
|
231
197
|
const actionsAtTheBottom = !largeLayout || layout === "side_panel" || selectedEntityView?.includeActions === "bottom";
|
|
232
198
|
|
|
233
|
-
const
|
|
234
|
-
.filter(e => e.includeActions)
|
|
235
|
-
.map((customView) => {
|
|
236
|
-
if (!customView || !formContext)
|
|
237
|
-
return null;
|
|
238
|
-
|
|
239
|
-
if (!customView.Builder) {
|
|
240
|
-
console.error("customView.Builder is not defined");
|
|
241
|
-
return null;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return <SecondaryForm key={`custom_view_${customView.key}`}
|
|
245
|
-
className={selectedTab !== customView.key ? "hidden" : ""}
|
|
246
|
-
customView={customView}
|
|
247
|
-
formContext={formContext}
|
|
248
|
-
collection={collection}
|
|
249
|
-
forceActionsAtTheBottom={!largeLayout || layout === "side_panel" || customView.includeActions === "bottom"}
|
|
250
|
-
entity={usedEntity}/>;
|
|
251
|
-
|
|
252
|
-
}).filter(Boolean);
|
|
199
|
+
const mainViewVisible = selectedTab === MAIN_TAB_VALUE || Boolean(selectedSecondaryForm);
|
|
253
200
|
|
|
254
201
|
const customViewsView: React.ReactNode[] | undefined = customViews && resolvedEntityViews
|
|
255
202
|
.filter(e => !e.includeActions)
|
|
@@ -322,7 +269,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
322
269
|
path,
|
|
323
270
|
entityId,
|
|
324
271
|
selectedTab: value === MAIN_TAB_VALUE ? undefined : value,
|
|
325
|
-
collection
|
|
272
|
+
collection,
|
|
326
273
|
});
|
|
327
274
|
}
|
|
328
275
|
};
|
|
@@ -361,6 +308,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
361
308
|
onSaved?.(res);
|
|
362
309
|
formProps?.onSaved?.(res);
|
|
363
310
|
}}
|
|
311
|
+
Builder={selectedSecondaryForm?.Builder}
|
|
364
312
|
/>;
|
|
365
313
|
|
|
366
314
|
const subcollectionTabs = subcollections && subcollections.map((subcollection) =>
|
|
@@ -421,7 +369,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
421
369
|
</div>
|
|
422
370
|
: entityView}
|
|
423
371
|
|
|
424
|
-
{secondaryForms}
|
|
372
|
+
{/*{secondaryForms}*/}
|
|
425
373
|
|
|
426
374
|
{customViewsView}
|
|
427
375
|
|
|
@@ -141,14 +141,14 @@ export function EntitySidePanel(props: EntitySidePanelProps) {
|
|
|
141
141
|
path,
|
|
142
142
|
entityId,
|
|
143
143
|
selectedTab,
|
|
144
|
-
collection
|
|
144
|
+
collection,
|
|
145
145
|
}) => {
|
|
146
146
|
sideEntityController.replace({
|
|
147
147
|
path,
|
|
148
148
|
entityId,
|
|
149
149
|
selectedTab,
|
|
150
150
|
updateUrl: true,
|
|
151
|
-
collection
|
|
151
|
+
collection,
|
|
152
152
|
});
|
|
153
153
|
}}
|
|
154
154
|
formProps={props.formProps}
|
package/src/form/EntityForm.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
CMSAnalyticsEvent,
|
|
4
4
|
Entity,
|
|
5
5
|
EntityCollection,
|
|
6
|
+
EntityCustomViewParams,
|
|
6
7
|
EntityStatus,
|
|
7
8
|
EntityValues,
|
|
8
9
|
FormContext,
|
|
@@ -82,6 +83,8 @@ export type EntityFormProps<M extends Record<string, any>> = {
|
|
|
82
83
|
|
|
83
84
|
EntityFormActionsComponent?: React.FC<EntityFormActionsProps>;
|
|
84
85
|
|
|
86
|
+
Builder?: React.ComponentType<EntityCustomViewParams<M>>;
|
|
87
|
+
|
|
85
88
|
children?: React.ReactNode;
|
|
86
89
|
};
|
|
87
90
|
|
|
@@ -102,6 +105,7 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
102
105
|
onEntityChange,
|
|
103
106
|
openEntityMode = "full_screen",
|
|
104
107
|
formex: formexProp,
|
|
108
|
+
Builder,
|
|
105
109
|
EntityFormActionsComponent = EntityFormActions,
|
|
106
110
|
showDefaultActions = true,
|
|
107
111
|
showEntityPath = true,
|
|
@@ -498,83 +502,94 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
498
502
|
|
|
499
503
|
const formFieldKeys = getFormFieldKeys(resolvedCollection);
|
|
500
504
|
|
|
501
|
-
const formFields = () =>
|
|
502
|
-
<FormLayout>
|
|
503
|
-
{formFieldKeys.map((key) => {
|
|
504
|
-
const property = resolvedCollection.properties[key];
|
|
505
|
-
if (property) {
|
|
506
|
-
const underlyingValueHasChanged: boolean =
|
|
507
|
-
!!underlyingChanges &&
|
|
508
|
-
Object.keys(underlyingChanges).includes(key) &&
|
|
509
|
-
formex.touched[key];
|
|
510
|
-
const disabled = (!autoSave && formex.isSubmitting) || isReadOnly(property) || Boolean(property.disabled);
|
|
511
|
-
const hidden = isHidden(property);
|
|
512
|
-
if (hidden) return null;
|
|
513
|
-
const widthPercentage = property.widthPercentage ?? 100;
|
|
514
|
-
const cmsFormFieldProps: PropertyFieldBindingProps<any, M> = {
|
|
515
|
-
propertyKey: key,
|
|
516
|
-
disabled,
|
|
517
|
-
property,
|
|
518
|
-
includeDescription: property.description || property.longDescription,
|
|
519
|
-
underlyingValueHasChanged: underlyingValueHasChanged && !autoSave,
|
|
520
|
-
context: formContext,
|
|
521
|
-
partOfArray: false,
|
|
522
|
-
minimalistView: false,
|
|
523
|
-
autoFocus: false
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
return (
|
|
527
|
-
<FormEntry propertyKey={key}
|
|
528
|
-
widthPercentage={widthPercentage}
|
|
529
|
-
key={`field_${key}`}>
|
|
530
|
-
<PropertyFieldBinding {...cmsFormFieldProps} />
|
|
531
|
-
</FormEntry>
|
|
532
|
-
);
|
|
533
|
-
}
|
|
505
|
+
const formFields = () => {
|
|
534
506
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
507
|
+
if (Builder) {
|
|
508
|
+
return <Builder
|
|
509
|
+
collection={collection}
|
|
510
|
+
entity={entity}
|
|
511
|
+
modifiedValues={formex.values}
|
|
512
|
+
formContext={formContext}
|
|
513
|
+
/>;
|
|
514
|
+
}
|
|
515
|
+
return (
|
|
516
|
+
<FormLayout>
|
|
517
|
+
{formFieldKeys.map((key) => {
|
|
518
|
+
const property = resolvedCollection.properties[key];
|
|
519
|
+
if (property) {
|
|
520
|
+
const underlyingValueHasChanged: boolean =
|
|
521
|
+
!!underlyingChanges &&
|
|
522
|
+
Object.keys(underlyingChanges).includes(key) &&
|
|
523
|
+
formex.touched[key];
|
|
524
|
+
const disabled = (!autoSave && formex.isSubmitting) || isReadOnly(property) || Boolean(property.disabled);
|
|
525
|
+
const hidden = isHidden(property);
|
|
526
|
+
if (hidden) return null;
|
|
527
|
+
const widthPercentage = property.widthPercentage ?? 100;
|
|
528
|
+
const cmsFormFieldProps: PropertyFieldBindingProps<any, M> = {
|
|
529
|
+
propertyKey: key,
|
|
530
|
+
disabled,
|
|
531
|
+
property,
|
|
532
|
+
includeDescription: property.description || property.longDescription,
|
|
533
|
+
underlyingValueHasChanged: underlyingValueHasChanged && !autoSave,
|
|
534
|
+
context: formContext,
|
|
535
|
+
partOfArray: false,
|
|
536
|
+
minimalistView: false,
|
|
537
|
+
autoFocus: false
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
return (
|
|
541
|
+
<FormEntry propertyKey={key}
|
|
542
|
+
widthPercentage={widthPercentage}
|
|
543
|
+
key={`field_${key}`}>
|
|
544
|
+
<PropertyFieldBinding {...cmsFormFieldProps} />
|
|
545
|
+
</FormEntry>
|
|
546
|
+
);
|
|
540
547
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
<
|
|
560
|
-
{
|
|
561
|
-
|
|
548
|
+
|
|
549
|
+
const additionalField = resolvedCollection.additionalFields?.find(f => f.key === key);
|
|
550
|
+
if (additionalField && entity) {
|
|
551
|
+
const Builder = additionalField.Builder;
|
|
552
|
+
if (!Builder && !additionalField.value) {
|
|
553
|
+
throw new Error("When using additional fields you need to provide a Builder or a value");
|
|
554
|
+
}
|
|
555
|
+
const child = Builder
|
|
556
|
+
? <Builder entity={entity} context={context}/>
|
|
557
|
+
: <div className={"w-full"}>
|
|
558
|
+
{additionalField.value?.({
|
|
559
|
+
entity,
|
|
560
|
+
context
|
|
561
|
+
})?.toString()}
|
|
562
|
+
</div>;
|
|
563
|
+
|
|
564
|
+
return (
|
|
565
|
+
<div key={`additional_${key}`} className={"w-full"}>
|
|
566
|
+
<LabelWithIconAndTooltip
|
|
567
|
+
propertyKey={key}
|
|
568
|
+
icon={<NotesIcon size={"small"}/>}
|
|
569
|
+
title={additionalField.name}
|
|
570
|
+
className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
|
|
571
|
+
<div
|
|
572
|
+
className={cls(paperMixin, "w-full min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
|
|
573
|
+
<ErrorBoundary>
|
|
574
|
+
{child}
|
|
575
|
+
</ErrorBoundary>
|
|
576
|
+
</div>
|
|
562
577
|
</div>
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
}
|
|
578
|
+
);
|
|
579
|
+
}
|
|
566
580
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
581
|
+
console.warn(`Property ${key} not found in collection ${resolvedCollection.name} in properties or additional fields. Skipping.`);
|
|
582
|
+
return null;
|
|
583
|
+
}).filter(Boolean)}
|
|
584
|
+
</FormLayout>
|
|
585
|
+
);
|
|
586
|
+
};
|
|
572
587
|
|
|
573
588
|
const formRef = useRef<HTMLDivElement>(null);
|
|
574
589
|
|
|
575
590
|
const formView = <ErrorBoundary>
|
|
576
591
|
<>
|
|
577
|
-
<div className={"w-full py-2 flex flex-col items-start my-4 lg:my-6"}>
|
|
592
|
+
{!Builder && <div className={"w-full py-2 flex flex-col items-start my-4 lg:my-6"}>
|
|
578
593
|
<Typography
|
|
579
594
|
className={"py-4 flex-grow line-clamp-1 " + (collection.hideIdFromForm ? "mb-2" : "mb-0")}
|
|
580
595
|
variant={"h4"}>
|
|
@@ -586,11 +601,11 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
586
601
|
{entity?.path ?? path}/{entityId}
|
|
587
602
|
</code>
|
|
588
603
|
</Alert>}
|
|
589
|
-
</div>
|
|
604
|
+
</div>}
|
|
590
605
|
|
|
591
606
|
{children}
|
|
592
607
|
|
|
593
|
-
{!collection.hideIdFromForm &&
|
|
608
|
+
{!Builder && !collection.hideIdFromForm &&
|
|
594
609
|
<CustomIdField customId={collection.customId}
|
|
595
610
|
entityId={entityId}
|
|
596
611
|
status={status}
|
|
@@ -616,104 +631,14 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
616
631
|
onIdChange(entityId);
|
|
617
632
|
}, [entityId, onIdChange]);
|
|
618
633
|
|
|
619
|
-
return (
|
|
620
|
-
<FormLayoutInner
|
|
621
|
-
className={className}
|
|
622
|
-
id={`form_${path}`}
|
|
623
|
-
pluginActions={pluginActions}
|
|
624
|
-
forceActionsAtTheBottom={forceActionsAtTheBottom}
|
|
625
|
-
EntityFormActionsComponent={EntityFormActionsComponent}
|
|
626
|
-
formContext={formContext}
|
|
627
|
-
showDefaultActions={showDefaultActions}>
|
|
628
|
-
{formView}
|
|
629
|
-
</FormLayoutInner>
|
|
630
|
-
);
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
function getInitialEntityValues<M extends object>(
|
|
634
|
-
collection: EntityCollection,
|
|
635
|
-
path: string,
|
|
636
|
-
status: "new" | "existing" | "copy",
|
|
637
|
-
entity: Entity<M> | undefined,
|
|
638
|
-
propertyConfigs?: Record<string, PropertyConfig>
|
|
639
|
-
): Partial<EntityValues<M>> {
|
|
640
|
-
const resolvedCollection = resolveCollection({
|
|
641
|
-
collection,
|
|
642
|
-
path,
|
|
643
|
-
values: entity?.values,
|
|
644
|
-
propertyConfigs
|
|
645
|
-
});
|
|
646
|
-
const properties = resolvedCollection.properties;
|
|
647
|
-
if ((status === "existing" || status === "copy") && entity) {
|
|
648
|
-
if (!collection.alwaysApplyDefaultValues) {
|
|
649
|
-
return entity.values ?? getDefaultValuesFor(properties);
|
|
650
|
-
} else {
|
|
651
|
-
const defaultValues = getDefaultValuesFor(properties);
|
|
652
|
-
return mergeDeep(defaultValues, entity.values ?? {});
|
|
653
|
-
}
|
|
654
|
-
} else if (status === "new") {
|
|
655
|
-
return getDefaultValuesFor(properties);
|
|
656
|
-
} else {
|
|
657
|
-
console.error({
|
|
658
|
-
status,
|
|
659
|
-
entity
|
|
660
|
-
});
|
|
661
|
-
throw new Error("Form has not been initialised with the correct parameters");
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
export function yupToFormErrors(yupError: ValidationError): Record<string, any> {
|
|
666
|
-
let errors: Record<string, any> = {};
|
|
667
|
-
if (yupError.inner) {
|
|
668
|
-
if (yupError.inner.length === 0) {
|
|
669
|
-
return setIn(errors, yupError.path!, yupError.message);
|
|
670
|
-
}
|
|
671
|
-
for (const err of yupError.inner) {
|
|
672
|
-
if (!getIn(errors, err.path!)) {
|
|
673
|
-
errors = setIn(errors, err.path!, err.message);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
return errors;
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
export function FormLayoutInner({
|
|
681
|
-
id,
|
|
682
|
-
formContext,
|
|
683
|
-
children,
|
|
684
|
-
className,
|
|
685
|
-
forceActionsAtTheBottom,
|
|
686
|
-
pluginActions,
|
|
687
|
-
EntityFormActionsComponent,
|
|
688
|
-
showDefaultActions,
|
|
689
|
-
}: {
|
|
690
|
-
id?: string,
|
|
691
|
-
formContext: FormContext,
|
|
692
|
-
children: React.ReactNode,
|
|
693
|
-
className?: string,
|
|
694
|
-
forceActionsAtTheBottom?: boolean,
|
|
695
|
-
pluginActions?: React.ReactNode[],
|
|
696
|
-
EntityFormActionsComponent: React.FC<EntityFormActionsProps>;
|
|
697
|
-
showDefaultActions?: boolean;
|
|
698
|
-
}) {
|
|
699
|
-
|
|
700
|
-
const formex = formContext.formex;
|
|
701
|
-
const collection = formContext.collection;
|
|
702
|
-
const path = formContext.path;
|
|
703
|
-
const entity = formContext.entity;
|
|
704
|
-
const savingError = formContext.savingError;
|
|
705
|
-
const status = formContext.status;
|
|
706
|
-
const openEntityMode = formContext.openEntityMode;
|
|
707
634
|
const disabled = formex.isSubmitting || (!formex.dirty && status === "existing");
|
|
708
635
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
if (!collection || !path) {
|
|
636
|
+
if (!resolvedCollection || !path) {
|
|
712
637
|
throw Error("INTERNAL: Collection and path must be defined in form context");
|
|
713
638
|
}
|
|
714
639
|
|
|
715
640
|
const dialogActions = <EntityFormActionsComponent
|
|
716
|
-
collection={
|
|
641
|
+
collection={resolvedCollection}
|
|
717
642
|
path={path}
|
|
718
643
|
entity={entity}
|
|
719
644
|
layout={forceActionsAtTheBottom ? "bottom" : "side"}
|
|
@@ -731,12 +656,12 @@ export function FormLayoutInner({
|
|
|
731
656
|
<form
|
|
732
657
|
onSubmit={formContext.formex.handleSubmit}
|
|
733
658
|
onReset={() => formex.resetForm({
|
|
734
|
-
values: getInitialEntityValues(collection, path, status, entity, customizationController.propertyConfigs),
|
|
659
|
+
values: getInitialEntityValues(collection, path, status, entity, customizationController.propertyConfigs) as M,
|
|
735
660
|
})}
|
|
736
661
|
noValidate
|
|
737
662
|
className={cls("flex-1 flex flex-row w-full overflow-y-auto justify-center", className)}>
|
|
738
663
|
<div
|
|
739
|
-
id={
|
|
664
|
+
id={`form_${path}`}
|
|
740
665
|
className={cls("relative flex flex-row max-w-4xl lg:max-w-3xl xl:max-w-4xl 2xl:max-w-6xl w-full h-fit")}>
|
|
741
666
|
|
|
742
667
|
<div className={cls("flex flex-col w-full pt-12 pb-16 px-4 sm:px-8 md:px-10")}>
|
|
@@ -754,7 +679,8 @@ export function FormLayoutInner({
|
|
|
754
679
|
<CheckIcon size={"smallest"}/>
|
|
755
680
|
</Chip>
|
|
756
681
|
</Tooltip>}
|
|
757
|
-
|
|
682
|
+
|
|
683
|
+
{formView}
|
|
758
684
|
|
|
759
685
|
</div>
|
|
760
686
|
|
|
@@ -766,6 +692,53 @@ export function FormLayoutInner({
|
|
|
766
692
|
);
|
|
767
693
|
}
|
|
768
694
|
|
|
695
|
+
function getInitialEntityValues<M extends object>(
|
|
696
|
+
collection: EntityCollection,
|
|
697
|
+
path: string,
|
|
698
|
+
status: "new" | "existing" | "copy",
|
|
699
|
+
entity: Entity<M> | undefined,
|
|
700
|
+
propertyConfigs?: Record<string, PropertyConfig>
|
|
701
|
+
): Partial<EntityValues<M>> {
|
|
702
|
+
const resolvedCollection = resolveCollection({
|
|
703
|
+
collection,
|
|
704
|
+
path,
|
|
705
|
+
values: entity?.values,
|
|
706
|
+
propertyConfigs
|
|
707
|
+
});
|
|
708
|
+
const properties = resolvedCollection.properties;
|
|
709
|
+
if ((status === "existing" || status === "copy") && entity) {
|
|
710
|
+
if (!collection.alwaysApplyDefaultValues) {
|
|
711
|
+
return entity.values ?? getDefaultValuesFor(properties);
|
|
712
|
+
} else {
|
|
713
|
+
const defaultValues = getDefaultValuesFor(properties);
|
|
714
|
+
return mergeDeep(defaultValues, entity.values ?? {});
|
|
715
|
+
}
|
|
716
|
+
} else if (status === "new") {
|
|
717
|
+
return getDefaultValuesFor(properties);
|
|
718
|
+
} else {
|
|
719
|
+
console.error({
|
|
720
|
+
status,
|
|
721
|
+
entity
|
|
722
|
+
});
|
|
723
|
+
throw new Error("Form has not been initialised with the correct parameters");
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export function yupToFormErrors(yupError: ValidationError): Record<string, any> {
|
|
728
|
+
let errors: Record<string, any> = {};
|
|
729
|
+
if (yupError.inner) {
|
|
730
|
+
if (yupError.inner.length === 0) {
|
|
731
|
+
return setIn(errors, yupError.path!, yupError.message);
|
|
732
|
+
}
|
|
733
|
+
for (const err of yupError.inner) {
|
|
734
|
+
if (!getIn(errors, err.path!)) {
|
|
735
|
+
errors = setIn(errors, err.path!, err.message);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return errors;
|
|
740
|
+
}
|
|
741
|
+
|
|
769
742
|
function useOnAutoSave(autoSave: undefined | boolean, formex: FormexController<any>, lastSavedValues: any, save: (values: EntityValues<any>) => Promise<void>) {
|
|
770
743
|
if (!autoSave) return;
|
|
771
744
|
useEffect(() => {
|