@firecms/core 3.0.0-canary.202 → 3.0.0-canary.204
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 +4 -2
- package/dist/index.es.js +58 -104
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +58 -104
- package/dist/index.umd.js.map +1 -1
- package/package.json +5 -5
- package/src/components/ArrayContainer.tsx +1 -1
- package/src/core/EntityEditView.tsx +7 -23
- package/src/form/EntityForm.tsx +89 -69
- package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
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.204",
|
|
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.204",
|
|
54
|
+
"@firecms/formex": "^3.0.0-canary.204",
|
|
55
|
+
"@firecms/ui": "^3.0.0-canary.204",
|
|
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": "2fb107e78d8fc3ade463adaf00908e3a8c812a0f",
|
|
108
108
|
"publishConfig": {
|
|
109
109
|
"access": "public"
|
|
110
110
|
},
|
|
@@ -289,7 +289,7 @@ export function ArrayContainerItem({
|
|
|
289
289
|
ref={provided.innerRef}
|
|
290
290
|
{...provided.draggableProps}
|
|
291
291
|
style={provided.draggableProps.style}
|
|
292
|
-
className={
|
|
292
|
+
className={`relative ${
|
|
293
293
|
!isDragging ? "hover:bg-surface-accent-50 dark:hover:bg-surface-800 dark:hover:bg-opacity-20" : ""
|
|
294
294
|
} rounded-md opacity-100`}
|
|
295
295
|
>
|
|
@@ -214,8 +214,6 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
214
214
|
}
|
|
215
215
|
}, [selectedTabProp]);
|
|
216
216
|
|
|
217
|
-
const mainViewVisible = selectedTab === MAIN_TAB_VALUE;
|
|
218
|
-
|
|
219
217
|
const subcollections = (collection.subcollections ?? []).filter(c => !c.hideFromNavigation);
|
|
220
218
|
const subcollectionsCount = subcollections?.length ?? 0;
|
|
221
219
|
const customViews = collection.entityViews;
|
|
@@ -228,28 +226,13 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
228
226
|
: [];
|
|
229
227
|
|
|
230
228
|
const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
.filter(e => e.includeActions)
|
|
235
|
-
.map((customView) => {
|
|
236
|
-
if (!customView || !formContext)
|
|
237
|
-
return null;
|
|
229
|
+
const selectedSecondaryForm = formContext
|
|
230
|
+
&& customViews
|
|
231
|
+
&& resolvedEntityViews.filter(e => e.includeActions).find(e => e.key === selectedTab);
|
|
238
232
|
|
|
239
|
-
|
|
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}/>;
|
|
233
|
+
const actionsAtTheBottom = !largeLayout || layout === "side_panel" || selectedEntityView?.includeActions === "bottom";
|
|
251
234
|
|
|
252
|
-
|
|
235
|
+
const mainViewVisible = selectedTab === MAIN_TAB_VALUE || Boolean(selectedSecondaryForm);
|
|
253
236
|
|
|
254
237
|
const customViewsView: React.ReactNode[] | undefined = customViews && resolvedEntityViews
|
|
255
238
|
.filter(e => !e.includeActions)
|
|
@@ -361,6 +344,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
361
344
|
onSaved?.(res);
|
|
362
345
|
formProps?.onSaved?.(res);
|
|
363
346
|
}}
|
|
347
|
+
Builder={selectedSecondaryForm?.Builder}
|
|
364
348
|
/>;
|
|
365
349
|
|
|
366
350
|
const subcollectionTabs = subcollections && subcollections.map((subcollection) =>
|
|
@@ -421,7 +405,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
421
405
|
</div>
|
|
422
406
|
: entityView}
|
|
423
407
|
|
|
424
|
-
{secondaryForms}
|
|
408
|
+
{/*{secondaryForms}*/}
|
|
425
409
|
|
|
426
410
|
{customViewsView}
|
|
427
411
|
|
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,
|
|
@@ -81,6 +82,10 @@ export type EntityFormProps<M extends Record<string, any>> = {
|
|
|
81
82
|
showEntityPath?: boolean;
|
|
82
83
|
|
|
83
84
|
EntityFormActionsComponent?: React.FC<EntityFormActionsProps>;
|
|
85
|
+
|
|
86
|
+
Builder?: React.ComponentType<EntityCustomViewParams<M>>;
|
|
87
|
+
|
|
88
|
+
children?: React.ReactNode;
|
|
84
89
|
};
|
|
85
90
|
|
|
86
91
|
export function EntityForm<M extends Record<string, any>>({
|
|
@@ -100,9 +105,11 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
100
105
|
onEntityChange,
|
|
101
106
|
openEntityMode = "full_screen",
|
|
102
107
|
formex: formexProp,
|
|
108
|
+
Builder,
|
|
103
109
|
EntityFormActionsComponent = EntityFormActions,
|
|
104
110
|
showDefaultActions = true,
|
|
105
|
-
showEntityPath = true
|
|
111
|
+
showEntityPath = true,
|
|
112
|
+
children
|
|
106
113
|
}: EntityFormProps<M>) {
|
|
107
114
|
|
|
108
115
|
if (collection.customId && collection.formAutoSave) {
|
|
@@ -495,83 +502,94 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
495
502
|
|
|
496
503
|
const formFieldKeys = getFormFieldKeys(resolvedCollection);
|
|
497
504
|
|
|
498
|
-
const formFields = () =>
|
|
499
|
-
<FormLayout>
|
|
500
|
-
{formFieldKeys.map((key) => {
|
|
501
|
-
const property = resolvedCollection.properties[key];
|
|
502
|
-
if (property) {
|
|
503
|
-
const underlyingValueHasChanged: boolean =
|
|
504
|
-
!!underlyingChanges &&
|
|
505
|
-
Object.keys(underlyingChanges).includes(key) &&
|
|
506
|
-
formex.touched[key];
|
|
507
|
-
const disabled = (!autoSave && formex.isSubmitting) || isReadOnly(property) || Boolean(property.disabled);
|
|
508
|
-
const hidden = isHidden(property);
|
|
509
|
-
if (hidden) return null;
|
|
510
|
-
const widthPercentage = property.widthPercentage ?? 100;
|
|
511
|
-
const cmsFormFieldProps: PropertyFieldBindingProps<any, M> = {
|
|
512
|
-
propertyKey: key,
|
|
513
|
-
disabled,
|
|
514
|
-
property,
|
|
515
|
-
includeDescription: property.description || property.longDescription,
|
|
516
|
-
underlyingValueHasChanged: underlyingValueHasChanged && !autoSave,
|
|
517
|
-
context: formContext,
|
|
518
|
-
partOfArray: false,
|
|
519
|
-
minimalistView: false,
|
|
520
|
-
autoFocus: false
|
|
521
|
-
};
|
|
522
|
-
|
|
523
|
-
return (
|
|
524
|
-
<FormEntry propertyKey={key}
|
|
525
|
-
widthPercentage={widthPercentage}
|
|
526
|
-
key={`field_${key}`}>
|
|
527
|
-
<PropertyFieldBinding {...cmsFormFieldProps} />
|
|
528
|
-
</FormEntry>
|
|
529
|
-
);
|
|
530
|
-
}
|
|
505
|
+
const formFields = () => {
|
|
531
506
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
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
|
+
);
|
|
537
547
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
<
|
|
557
|
-
{
|
|
558
|
-
|
|
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>
|
|
559
577
|
</div>
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
}
|
|
578
|
+
);
|
|
579
|
+
}
|
|
563
580
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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
|
+
};
|
|
569
587
|
|
|
570
588
|
const formRef = useRef<HTMLDivElement>(null);
|
|
571
589
|
|
|
572
590
|
const formView = <ErrorBoundary>
|
|
573
591
|
<>
|
|
574
|
-
<div className={"w-full py-2 flex flex-col items-start
|
|
592
|
+
<div className={"w-full py-2 flex flex-col items-start my-4 lg:my-6"}>
|
|
575
593
|
<Typography
|
|
576
594
|
className={"py-4 flex-grow line-clamp-1 " + (collection.hideIdFromForm ? "mb-2" : "mb-0")}
|
|
577
595
|
variant={"h4"}>
|
|
@@ -585,6 +603,8 @@ export function EntityForm<M extends Record<string, any>>({
|
|
|
585
603
|
</Alert>}
|
|
586
604
|
</div>
|
|
587
605
|
|
|
606
|
+
{children}
|
|
607
|
+
|
|
588
608
|
{!collection.hideIdFromForm &&
|
|
589
609
|
<CustomIdField customId={collection.customId}
|
|
590
610
|
entityId={entityId}
|