@firecms/core 3.0.0-canary.174 → 3.0.0-canary.176
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/PropertyFieldBinding.d.ts +1 -1
- 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/RepeatFieldBinding.d.ts +1 -1
- package/dist/index.es.js +128 -52
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +127 -51
- package/dist/index.umd.js.map +1 -1
- package/dist/types/collections.d.ts +5 -3
- package/dist/types/fields.d.ts +4 -2
- package/dist/types/properties.d.ts +12 -2
- package/dist/util/builders.d.ts +1 -1
- package/package.json +17 -17
- package/src/core/EntityEditView.tsx +93 -41
- package/src/form/PropertyFieldBinding.tsx +2 -2
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +3 -1
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +3 -1
- package/src/form/field_bindings/BlockFieldBinding.tsx +4 -2
- package/src/form/field_bindings/MapFieldBinding.tsx +2 -1
- package/src/form/field_bindings/RepeatFieldBinding.tsx +3 -1
- package/src/routes/FireCMSRoute.tsx +3 -3
- package/src/types/collections.ts +11 -6
- package/src/types/fields.tsx +4 -2
- package/src/types/properties.ts +14 -2
- package/src/util/builders.ts +5 -3
|
@@ -426,10 +426,12 @@ export type EntityCustomView<M extends Record<string, any> = any> = {
|
|
|
426
426
|
*/
|
|
427
427
|
name: string;
|
|
428
428
|
/**
|
|
429
|
-
* If set to true, the actions of the entity will be
|
|
430
|
-
*
|
|
429
|
+
* If set to true, the actions of the entity (save, discard,delete) will be
|
|
430
|
+
* included in the view. By default the actions are located in the right or bottom,
|
|
431
|
+
* based on the screen size. You can force the actions to be located at the bottom
|
|
432
|
+
* by setting this prop to "bottom".
|
|
431
433
|
*/
|
|
432
|
-
includeActions?: boolean;
|
|
434
|
+
includeActions?: boolean | "bottom";
|
|
433
435
|
/**
|
|
434
436
|
* Builder for rendering the custom view
|
|
435
437
|
*/
|
package/dist/types/fields.d.ts
CHANGED
|
@@ -67,7 +67,8 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
67
67
|
*/
|
|
68
68
|
partOfArray?: boolean;
|
|
69
69
|
/**
|
|
70
|
-
*
|
|
70
|
+
* Display the child properties directly, without being wrapped in an
|
|
71
|
+
* extendable panel. Note that this will also hide the title of this property.
|
|
71
72
|
*/
|
|
72
73
|
minimalistView?: boolean;
|
|
73
74
|
/**
|
|
@@ -170,7 +171,8 @@ export interface PropertyFieldBindingProps<T extends CMSType, M extends Record<s
|
|
|
170
171
|
*/
|
|
171
172
|
partOfArray?: boolean;
|
|
172
173
|
/**
|
|
173
|
-
*
|
|
174
|
+
* Display the child properties directly, without being wrapped in an
|
|
175
|
+
* extendable panel. Note that this will also hide the title of this property.
|
|
174
176
|
*/
|
|
175
177
|
minimalistView?: boolean;
|
|
176
178
|
/**
|
|
@@ -211,11 +211,11 @@ export type PropertyBuilder<T extends CMSType = any, M extends Record<string, an
|
|
|
211
211
|
/**
|
|
212
212
|
* @group Entity properties
|
|
213
213
|
*/
|
|
214
|
-
export type PropertyOrBuilder<T extends CMSType = CMSType, M extends Record<string, any> =
|
|
214
|
+
export type PropertyOrBuilder<T extends CMSType = CMSType, M extends Record<string, any> = any> = Property<T> | PropertyBuilder<T, M>;
|
|
215
215
|
/**
|
|
216
216
|
* @group Entity properties
|
|
217
217
|
*/
|
|
218
|
-
export type PropertiesOrBuilders<M extends Record<string, any> =
|
|
218
|
+
export type PropertiesOrBuilders<M extends Record<string, any> = any> = {
|
|
219
219
|
[k in keyof M]: PropertyOrBuilder<M[k], M>;
|
|
220
220
|
};
|
|
221
221
|
/**
|
|
@@ -361,6 +361,11 @@ export interface ArrayProperty<T extends ArrayT[] = any[], ArrayT extends CMSTyp
|
|
|
361
361
|
* Should the field be initially expanded. Defaults to `true`
|
|
362
362
|
*/
|
|
363
363
|
expanded?: boolean;
|
|
364
|
+
/**
|
|
365
|
+
* Display the child properties directly, without being wrapped in an
|
|
366
|
+
* extendable panel.
|
|
367
|
+
*/
|
|
368
|
+
minimalistView?: boolean;
|
|
364
369
|
}
|
|
365
370
|
/**
|
|
366
371
|
* @group Entity properties
|
|
@@ -400,6 +405,11 @@ export interface MapProperty<T extends Record<string, CMSType> = Record<string,
|
|
|
400
405
|
* view
|
|
401
406
|
*/
|
|
402
407
|
spreadChildren?: boolean;
|
|
408
|
+
/**
|
|
409
|
+
* Display the child properties directly, without being wrapped in an
|
|
410
|
+
* extendable panel. Note that this will also hide the title of this property.
|
|
411
|
+
*/
|
|
412
|
+
minimalistView?: boolean;
|
|
403
413
|
/**
|
|
404
414
|
* Should the field be initially expanded. Defaults to `true`
|
|
405
415
|
*/
|
package/dist/util/builders.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare function buildCollection<M extends Record<string, any> = any, USE
|
|
|
12
12
|
* @param property
|
|
13
13
|
* @group Builder
|
|
14
14
|
*/
|
|
15
|
-
export declare function buildProperty<T extends CMSType = CMSType, P extends PropertyOrBuilder<T> = PropertyOrBuilder<T>, M extends Record<string, any> =
|
|
15
|
+
export declare function buildProperty<T extends CMSType = CMSType, P extends PropertyOrBuilder<T> = PropertyOrBuilder<T>, M extends Record<string, any> = any>(property: P): P extends StringProperty ? StringProperty : P extends NumberProperty ? NumberProperty : P extends BooleanProperty ? BooleanProperty : P extends DateProperty ? DateProperty : P extends GeopointProperty ? GeopointProperty : P extends ReferenceProperty ? ReferenceProperty : P extends ArrayProperty ? ArrayProperty : P extends MapProperty ? MapProperty : P extends PropertyBuilder<T, M> ? PropertyBuilder<T, M> : never;
|
|
16
16
|
/**
|
|
17
17
|
* Identity function we use to defeat the type system of Typescript and preserve
|
|
18
18
|
* the properties keys.
|
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.176",
|
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/firecmsco"
|
|
@@ -50,24 +50,24 @@
|
|
|
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.176",
|
|
54
|
+
"@firecms/formex": "^3.0.0-canary.176",
|
|
55
|
+
"@firecms/ui": "^3.0.0-canary.176",
|
|
56
56
|
"@hello-pangea/dnd": "^17.0.0",
|
|
57
|
-
"@radix-ui/react-portal": "^1.1.
|
|
57
|
+
"@radix-ui/react-portal": "^1.1.3",
|
|
58
58
|
"clsx": "^2.1.1",
|
|
59
59
|
"date-fns": "^3.6.0",
|
|
60
60
|
"fuse.js": "^7.0.0",
|
|
61
61
|
"history": "^5.3.0",
|
|
62
62
|
"markdown-it": "^14.1.0",
|
|
63
|
-
"notistack": "^3.0.
|
|
63
|
+
"notistack": "^3.0.2",
|
|
64
64
|
"object-hash": "^3.0.0",
|
|
65
65
|
"react-dropzone": "^14.3.5",
|
|
66
66
|
"react-fast-compare": "^3.2.2",
|
|
67
67
|
"react-image-file-resizer": "^0.4.8",
|
|
68
68
|
"react-transition-group": "^4.4.5",
|
|
69
69
|
"react-use-measure": "^2.1.1",
|
|
70
|
-
"react-window": "^1.8.
|
|
70
|
+
"react-window": "^1.8.11",
|
|
71
71
|
"yup": "^0.32.11"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
@@ -78,13 +78,13 @@
|
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@jest/globals": "^29.7.0",
|
|
81
|
-
"@testing-library/react": "^16.0
|
|
82
|
-
"@testing-library/user-event": "^14.
|
|
81
|
+
"@testing-library/react": "^16.2.0",
|
|
82
|
+
"@testing-library/user-event": "^14.6.1",
|
|
83
83
|
"@types/jest": "^29.5.14",
|
|
84
|
-
"@types/node": "^20.17.
|
|
84
|
+
"@types/node": "^20.17.14",
|
|
85
85
|
"@types/object-hash": "^3.0.6",
|
|
86
|
-
"@types/react": "^18.3.
|
|
87
|
-
"@types/react-dom": "^18.3.
|
|
86
|
+
"@types/react": "^18.3.18",
|
|
87
|
+
"@types/react-dom": "^18.3.0",
|
|
88
88
|
"@types/react-measure": "^2.0.12",
|
|
89
89
|
"@vitejs/plugin-react": "^4.3.4",
|
|
90
90
|
"babel-plugin-react-compiler": "beta",
|
|
@@ -92,19 +92,19 @@
|
|
|
92
92
|
"eslint-plugin-react-compiler": "beta",
|
|
93
93
|
"jest": "^29.7.0",
|
|
94
94
|
"npm-run-all": "^4.1.5",
|
|
95
|
-
"react-router": "^6.28.
|
|
96
|
-
"react-router-dom": "^6.28.
|
|
95
|
+
"react-router": "^6.28.2",
|
|
96
|
+
"react-router-dom": "^6.28.2",
|
|
97
97
|
"ts-jest": "^29.2.5",
|
|
98
98
|
"ts-node": "^10.9.2",
|
|
99
99
|
"tsd": "^0.31.2",
|
|
100
|
-
"typescript": "^5.7.
|
|
101
|
-
"vite": "^5.4.
|
|
100
|
+
"typescript": "^5.7.3",
|
|
101
|
+
"vite": "^5.4.14"
|
|
102
102
|
},
|
|
103
103
|
"files": [
|
|
104
104
|
"dist",
|
|
105
105
|
"src"
|
|
106
106
|
],
|
|
107
|
-
"gitHead": "
|
|
107
|
+
"gitHead": "41075e0bfa191634e1a52442c8889d3ca53eb922",
|
|
108
108
|
"publishConfig": {
|
|
109
109
|
"access": "public"
|
|
110
110
|
},
|
|
@@ -76,12 +76,12 @@ import {
|
|
|
76
76
|
} from "@firecms/ui";
|
|
77
77
|
import { Formex, FormexController, getIn, setIn, useCreateFormex } from "@firecms/formex";
|
|
78
78
|
import { useAnalyticsController } from "../hooks/useAnalyticsController";
|
|
79
|
-
import { CustomIdField } from "../form/components/CustomIdField";
|
|
80
79
|
import { CustomFieldValidator, getYupEntitySchema } from "../form/validation";
|
|
81
|
-
import { ErrorFocus } from "../form/components/ErrorFocus";
|
|
82
80
|
import { LabelWithIconAndTooltip, PropertyFieldBinding } from "../form";
|
|
83
81
|
import { ValidationError } from "yup";
|
|
84
82
|
import { getEntityFromCache, removeEntityFromCache, saveEntityToCache } from "../util/entity_cache";
|
|
83
|
+
import { CustomIdField } from "../form/components/CustomIdField";
|
|
84
|
+
import { ErrorFocus } from "../form/components/ErrorFocus";
|
|
85
85
|
|
|
86
86
|
const MAIN_TAB_VALUE = "main_##Q$SC^#S6";
|
|
87
87
|
|
|
@@ -158,6 +158,46 @@ export function EntityEditView<M extends Record<string, any>, USER extends User>
|
|
|
158
158
|
/>;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
function FormLayout({
|
|
162
|
+
id,
|
|
163
|
+
formex,
|
|
164
|
+
children,
|
|
165
|
+
className
|
|
166
|
+
}: {
|
|
167
|
+
id?: string,
|
|
168
|
+
formex: FormexController<any>,
|
|
169
|
+
children: React.ReactNode,
|
|
170
|
+
className?: string
|
|
171
|
+
}) {
|
|
172
|
+
|
|
173
|
+
return <div
|
|
174
|
+
role="tabpanel"
|
|
175
|
+
id={id}
|
|
176
|
+
className={cls("relative flex flex-row max-w-4xl lg:max-w-3xl xl:max-w-5xl 2xl:max-w-7xl w-full h-fit", className)}>
|
|
177
|
+
|
|
178
|
+
<div className={cls("flex flex-col w-full pt-12 pb-16 px-4 sm:px-8 md:px-10")}>
|
|
179
|
+
|
|
180
|
+
{formex.dirty
|
|
181
|
+
? <Tooltip title={"Unsaved changes"}
|
|
182
|
+
className={"self-end sticky top-4 z-10"}>
|
|
183
|
+
<Chip size={"small"} colorScheme={"orangeDarker"}>
|
|
184
|
+
<EditIcon size={"smallest"}/>
|
|
185
|
+
</Chip>
|
|
186
|
+
</Tooltip>
|
|
187
|
+
: <Tooltip title={"In sync with the database"}
|
|
188
|
+
className={"self-end sticky top-4 z-10"}>
|
|
189
|
+
<Chip size={"small"}>
|
|
190
|
+
<CheckIcon size={"smallest"}/>
|
|
191
|
+
</Chip>
|
|
192
|
+
</Tooltip>}
|
|
193
|
+
|
|
194
|
+
{children}
|
|
195
|
+
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
</div>
|
|
199
|
+
}
|
|
200
|
+
|
|
161
201
|
export function EntityEditViewInner<M extends Record<string, any>>({
|
|
162
202
|
path,
|
|
163
203
|
entityId: entityIdProp,
|
|
@@ -533,9 +573,39 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
533
573
|
: [];
|
|
534
574
|
|
|
535
575
|
const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
|
|
536
|
-
const shouldShowEntityActions =
|
|
576
|
+
const shouldShowEntityActions = selectedTab === MAIN_TAB_VALUE || selectedEntityView?.includeActions;
|
|
577
|
+
|
|
578
|
+
const secondaryForms: React.ReactNode[] | undefined = customViews && resolvedEntityViews
|
|
579
|
+
.filter(e => e.includeActions)
|
|
580
|
+
.map(
|
|
581
|
+
(customView, colIndex) => {
|
|
582
|
+
if (!customView)
|
|
583
|
+
return null;
|
|
584
|
+
const Builder = customView.Builder;
|
|
585
|
+
if (!Builder) {
|
|
586
|
+
console.error("customView.Builder is not defined");
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
return <FormLayout
|
|
591
|
+
key={`custom_view_${customView.key}`}
|
|
592
|
+
className={selectedTab !== customView.key ? "hidden" : ""}
|
|
593
|
+
formex={formex}>
|
|
594
|
+
<ErrorBoundary>
|
|
595
|
+
{formContext && <Builder
|
|
596
|
+
collection={collection}
|
|
597
|
+
entity={usedEntity}
|
|
598
|
+
modifiedValues={formex.values ?? usedEntity?.values}
|
|
599
|
+
formContext={formContext}
|
|
600
|
+
/>}
|
|
601
|
+
</ErrorBoundary>
|
|
602
|
+
</FormLayout>
|
|
603
|
+
|
|
604
|
+
}
|
|
605
|
+
).filter(Boolean);
|
|
537
606
|
|
|
538
607
|
const customViewsView: React.ReactNode[] | undefined = customViews && resolvedEntityViews
|
|
608
|
+
.filter(e => !e.includeActions)
|
|
539
609
|
.map(
|
|
540
610
|
(customView, colIndex) => {
|
|
541
611
|
if (!customView)
|
|
@@ -545,6 +615,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
545
615
|
console.error("customView.Builder is not defined");
|
|
546
616
|
return null;
|
|
547
617
|
}
|
|
618
|
+
|
|
548
619
|
return <div
|
|
549
620
|
className={cls(defaultBorderMixin,
|
|
550
621
|
"relative flex-grow w-full h-full overflow-auto",
|
|
@@ -572,12 +643,10 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
572
643
|
(subcollection, colIndex) => {
|
|
573
644
|
const subcollectionId = subcollection.id ?? subcollection.path;
|
|
574
645
|
const fullPath = usedEntity ? `${path}/${usedEntity?.id}/${removeInitialAndTrailingSlashes(subcollectionId)}` : undefined;
|
|
646
|
+
if (selectedTab !== subcollectionId) return null;
|
|
575
647
|
return (
|
|
576
648
|
<div
|
|
577
|
-
className={
|
|
578
|
-
{
|
|
579
|
-
"hidden": selectedTab !== subcollectionId
|
|
580
|
-
})}
|
|
649
|
+
className={"relative flex-grow h-full overflow-auto w-full"}
|
|
581
650
|
key={`subcol_${subcollectionId}`}
|
|
582
651
|
role="tabpanel">
|
|
583
652
|
|
|
@@ -882,22 +951,7 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
882
951
|
: (!readOnly
|
|
883
952
|
? (
|
|
884
953
|
<ErrorBoundary>
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
{formex.dirty
|
|
888
|
-
? <Tooltip title={"Unsaved changes"}
|
|
889
|
-
className={"self-end sticky top-4 z-10"}>
|
|
890
|
-
<Chip size={"small"} colorScheme={"orangeDarker"}>
|
|
891
|
-
<EditIcon size={"smallest"}/>
|
|
892
|
-
</Chip>
|
|
893
|
-
</Tooltip>
|
|
894
|
-
: <Tooltip title={"In sync with the database"}
|
|
895
|
-
className={"self-end sticky top-4 z-10"}>
|
|
896
|
-
<Chip size={"small"}>
|
|
897
|
-
<CheckIcon size={"smallest"}/>
|
|
898
|
-
</Chip>
|
|
899
|
-
</Tooltip>}
|
|
900
|
-
|
|
954
|
+
<>
|
|
901
955
|
<div
|
|
902
956
|
className={"w-full py-2 flex flex-col items-start mt-4 lg:mt-8 mb-8"}>
|
|
903
957
|
|
|
@@ -929,12 +983,11 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
929
983
|
<ErrorFocus containerRef={formRef}/>
|
|
930
984
|
|
|
931
985
|
</div>
|
|
932
|
-
|
|
933
|
-
{actionsAtTheBottom && <div className="h-16"/>}
|
|
934
|
-
|
|
935
986
|
</>}
|
|
936
987
|
|
|
937
|
-
|
|
988
|
+
{actionsAtTheBottom && <div className="h-16"/>}
|
|
989
|
+
|
|
990
|
+
</>
|
|
938
991
|
</ErrorBoundary>
|
|
939
992
|
)
|
|
940
993
|
: (
|
|
@@ -1028,28 +1081,27 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
1028
1081
|
noValidate
|
|
1029
1082
|
className={"flex-1 flex flex-row w-full overflow-y-auto justify-center"}>
|
|
1030
1083
|
|
|
1031
|
-
<
|
|
1032
|
-
|
|
1033
|
-
hidden={!mainViewVisible}
|
|
1084
|
+
<FormLayout
|
|
1085
|
+
className={!mainViewVisible ? "hidden" : ""}
|
|
1034
1086
|
id={`form_${path}`}
|
|
1035
|
-
|
|
1036
|
-
"hidden": !mainViewVisible
|
|
1037
|
-
})}>
|
|
1038
|
-
|
|
1087
|
+
formex={formex}>
|
|
1039
1088
|
{globalLoading
|
|
1040
|
-
? <div className="w-full pt-12 pb-16 px-4 sm:px-8 md:px-10"
|
|
1089
|
+
? <div className="w-full pt-12 pb-16 px-4 sm:px-8 md:px-10">
|
|
1090
|
+
<CircularProgressCenter/>
|
|
1091
|
+
</div>
|
|
1041
1092
|
: entityView}
|
|
1093
|
+
</FormLayout>
|
|
1042
1094
|
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
{customViewsView}
|
|
1046
|
-
|
|
1047
|
-
{subCollectionsViews}
|
|
1095
|
+
{secondaryForms}
|
|
1048
1096
|
|
|
1049
1097
|
{shouldShowEntityActions && dialogActions}
|
|
1050
1098
|
|
|
1051
1099
|
</form>
|
|
1052
1100
|
|
|
1101
|
+
{customViewsView}
|
|
1102
|
+
|
|
1103
|
+
{subCollectionsViews}
|
|
1104
|
+
|
|
1053
1105
|
</div>;
|
|
1054
1106
|
|
|
1055
1107
|
if (plugins) {
|
|
@@ -1238,7 +1290,7 @@ function buildSideActions<M extends object>({
|
|
|
1238
1290
|
}: ActionsViewProps<M>) {
|
|
1239
1291
|
|
|
1240
1292
|
return <div
|
|
1241
|
-
className={cls("overflow-auto h-full flex flex-col gap-2 w-96 px-4 py-16 sticky top-0 border-l", defaultBorderMixin)}>
|
|
1293
|
+
className={cls("overflow-auto h-full flex flex-col gap-2 w-80 xl:w-96 px-4 py-16 sticky top-0 border-l", defaultBorderMixin)}>
|
|
1242
1294
|
|
|
1243
1295
|
<LoadingButton
|
|
1244
1296
|
fullWidth={true}
|
|
@@ -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,
|
|
@@ -175,7 +175,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
|
|
|
175
175
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
type ResolvedPropertyFieldBindingProps<T extends CMSType = CMSType, M extends Record<string, any> =
|
|
178
|
+
type ResolvedPropertyFieldBindingProps<T extends CMSType = CMSType, M extends Record<string, any> = any> =
|
|
179
179
|
Omit<PropertyFieldBindingProps<T, M>, "property">
|
|
180
180
|
& {
|
|
181
181
|
property: ResolvedProperty<T>
|
|
@@ -20,7 +20,7 @@ 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
26
|
underlyingValueHasChanged,
|
|
@@ -28,6 +28,8 @@ export function ArrayCustomShapedFieldBinding<T extends Array<any>>({
|
|
|
28
28
|
disabled
|
|
29
29
|
}: FieldProps<T, any, any>) {
|
|
30
30
|
|
|
31
|
+
const minimalistView = minimalistViewProp || property.minimalistView;
|
|
32
|
+
|
|
31
33
|
let resolvedProperties = "resolvedProperties" in property ? property.resolvedProperties : undefined;
|
|
32
34
|
if (!resolvedProperties) {
|
|
33
35
|
resolvedProperties = getArrayResolvedProperties({
|
|
@@ -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");
|
|
@@ -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
|
|
|
@@ -21,7 +21,7 @@ export function MapFieldBinding({
|
|
|
21
21
|
error,
|
|
22
22
|
disabled,
|
|
23
23
|
property,
|
|
24
|
-
minimalistView,
|
|
24
|
+
minimalistView: minimalistViewProp,
|
|
25
25
|
includeDescription,
|
|
26
26
|
underlyingValueHasChanged,
|
|
27
27
|
autoFocus,
|
|
@@ -31,6 +31,7 @@ export function MapFieldBinding({
|
|
|
31
31
|
|
|
32
32
|
const pickOnlySomeKeys = property.pickOnlySomeKeys || false;
|
|
33
33
|
const expanded = property.expanded === undefined ? true : property.expanded;
|
|
34
|
+
const minimalistView = minimalistViewProp || property.minimalistView;
|
|
34
35
|
|
|
35
36
|
if (!property.properties) {
|
|
36
37
|
throw Error(`You need to specify a 'properties' prop (or specify a custom field) in your map property ${propertyKey}`);
|
|
@@ -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
|
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "../util/navigation_from_path";
|
|
12
12
|
import { useBreadcrumbsController } from "../hooks/useBreadcrumbsController";
|
|
13
13
|
import { toArray } from "../util/arrays";
|
|
14
|
-
import { EntityCollectionView } from "../components";
|
|
14
|
+
import { EntityCollectionView, NotFoundPage } from "../components";
|
|
15
15
|
import { UnsavedChangesDialog } from "../components/UnsavedChangesDialog";
|
|
16
16
|
|
|
17
17
|
export function FireCMSRoute() {
|
|
@@ -191,11 +191,11 @@ function EntityFullScreenRoute({
|
|
|
191
191
|
const lastCollectionEntry = navigationEntries.findLast((entry) => entry.type === "collection");
|
|
192
192
|
|
|
193
193
|
if (isNew && !lastCollectionEntry) {
|
|
194
|
-
throw new Error("No collection found in the navigation");
|
|
194
|
+
throw new Error("INTERNAL: No collection found in the navigation");
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
if (!isNew && !lastEntityEntry) {
|
|
198
|
-
|
|
198
|
+
return <NotFoundPage/>;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
const collection = isNew ? lastCollectionEntry!.collection : lastEntityEntry!.parentCollection;
|
package/src/types/collections.ts
CHANGED
|
@@ -498,21 +498,26 @@ export type EntityCustomView<M extends Record<string, any> = any> =
|
|
|
498
498
|
/**
|
|
499
499
|
* Key of this custom view.
|
|
500
500
|
*/
|
|
501
|
-
key: string
|
|
501
|
+
key: string;
|
|
502
|
+
|
|
502
503
|
/**
|
|
503
504
|
* Name of this custom view.
|
|
504
505
|
*/
|
|
505
|
-
name: string
|
|
506
|
+
name: string;
|
|
507
|
+
|
|
506
508
|
/**
|
|
507
|
-
* If set to true, the actions of the entity will be
|
|
508
|
-
*
|
|
509
|
+
* If set to true, the actions of the entity (save, discard,delete) will be
|
|
510
|
+
* included in the view. By default the actions are located in the right or bottom,
|
|
511
|
+
* based on the screen size. You can force the actions to be located at the bottom
|
|
512
|
+
* by setting this prop to "bottom".
|
|
509
513
|
*/
|
|
510
|
-
includeActions?: boolean;
|
|
514
|
+
includeActions?: boolean | "bottom";
|
|
515
|
+
|
|
511
516
|
/**
|
|
512
517
|
* Builder for rendering the custom view
|
|
513
518
|
*/
|
|
514
519
|
Builder?: React.ComponentType<EntityCustomViewParams<M>>;
|
|
515
|
-
}
|
|
520
|
+
};
|
|
516
521
|
|
|
517
522
|
/**
|
|
518
523
|
* Parameters passed to the builder in charge of rendering a custom panel for
|
package/src/types/fields.tsx
CHANGED
|
@@ -81,7 +81,8 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
|
|
|
81
81
|
partOfArray?: boolean;
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
84
|
+
* Display the child properties directly, without being wrapped in an
|
|
85
|
+
* extendable panel. Note that this will also hide the title of this property.
|
|
85
86
|
*/
|
|
86
87
|
minimalistView?: boolean;
|
|
87
88
|
|
|
@@ -207,7 +208,8 @@ export interface PropertyFieldBindingProps<T extends CMSType, M extends Record<s
|
|
|
207
208
|
partOfArray?: boolean;
|
|
208
209
|
|
|
209
210
|
/**
|
|
210
|
-
*
|
|
211
|
+
* Display the child properties directly, without being wrapped in an
|
|
212
|
+
* extendable panel. Note that this will also hide the title of this property.
|
|
211
213
|
*/
|
|
212
214
|
minimalistView?: boolean;
|
|
213
215
|
|
package/src/types/properties.ts
CHANGED
|
@@ -285,14 +285,14 @@ export type PropertyBuilder<T extends CMSType = any, M extends Record<string, an
|
|
|
285
285
|
/**
|
|
286
286
|
* @group Entity properties
|
|
287
287
|
*/
|
|
288
|
-
export type PropertyOrBuilder<T extends CMSType = CMSType, M extends Record<string, any> =
|
|
288
|
+
export type PropertyOrBuilder<T extends CMSType = CMSType, M extends Record<string, any> = any> =
|
|
289
289
|
Property<T>
|
|
290
290
|
| PropertyBuilder<T, M>;
|
|
291
291
|
|
|
292
292
|
/**
|
|
293
293
|
* @group Entity properties
|
|
294
294
|
*/
|
|
295
|
-
export type PropertiesOrBuilders<M extends Record<string, any> =
|
|
295
|
+
export type PropertiesOrBuilders<M extends Record<string, any> = any> =
|
|
296
296
|
{
|
|
297
297
|
[k in keyof M]: PropertyOrBuilder<M[k], M>;
|
|
298
298
|
};
|
|
@@ -469,6 +469,12 @@ export interface ArrayProperty<T extends ArrayT[] = any[], ArrayT extends CMSTyp
|
|
|
469
469
|
*/
|
|
470
470
|
expanded?: boolean;
|
|
471
471
|
|
|
472
|
+
/**
|
|
473
|
+
* Display the child properties directly, without being wrapped in an
|
|
474
|
+
* extendable panel.
|
|
475
|
+
*/
|
|
476
|
+
minimalistView?: boolean;
|
|
477
|
+
|
|
472
478
|
}
|
|
473
479
|
|
|
474
480
|
/**
|
|
@@ -517,6 +523,12 @@ export interface MapProperty<T extends Record<string, CMSType> = Record<string,
|
|
|
517
523
|
*/
|
|
518
524
|
spreadChildren?: boolean;
|
|
519
525
|
|
|
526
|
+
/**
|
|
527
|
+
* Display the child properties directly, without being wrapped in an
|
|
528
|
+
* extendable panel. Note that this will also hide the title of this property.
|
|
529
|
+
*/
|
|
530
|
+
minimalistView?: boolean;
|
|
531
|
+
|
|
520
532
|
/**
|
|
521
533
|
* Should the field be initially expanded. Defaults to `true`
|
|
522
534
|
*/
|
package/src/util/builders.ts
CHANGED
|
@@ -26,8 +26,10 @@ import {
|
|
|
26
26
|
* @param collection
|
|
27
27
|
* @group Builder
|
|
28
28
|
*/
|
|
29
|
-
export function buildCollection<
|
|
30
|
-
|
|
29
|
+
export function buildCollection<
|
|
30
|
+
M extends Record<string, any> = any,
|
|
31
|
+
USER extends User = User>
|
|
32
|
+
(
|
|
31
33
|
collection: EntityCollection<M, USER>
|
|
32
34
|
): EntityCollection<M, USER> {
|
|
33
35
|
return collection;
|
|
@@ -39,7 +41,7 @@ export function buildCollection<M extends Record<string, any> = any,
|
|
|
39
41
|
* @param property
|
|
40
42
|
* @group Builder
|
|
41
43
|
*/
|
|
42
|
-
export function buildProperty<T extends CMSType = CMSType, P extends PropertyOrBuilder<T> = PropertyOrBuilder<T>, M extends Record<string, any> =
|
|
44
|
+
export function buildProperty<T extends CMSType = CMSType, P extends PropertyOrBuilder<T> = PropertyOrBuilder<T>, M extends Record<string, any> = any>(
|
|
43
45
|
property: P
|
|
44
46
|
):
|
|
45
47
|
P extends StringProperty ? StringProperty :
|