@firecms/core 3.0.0-canary.174 → 3.0.0-canary.175
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/index.es.js +90 -31
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +89 -30
- package/dist/index.umd.js.map +1 -1
- package/dist/types/properties.d.ts +2 -2
- package/dist/util/builders.d.ts +1 -1
- package/package.json +17 -17
- package/src/core/EntityEditView.tsx +91 -39
- package/src/form/PropertyFieldBinding.tsx +2 -2
- package/src/routes/FireCMSRoute.tsx +3 -3
- package/src/types/properties.ts +2 -2
- package/src/util/builders.ts +5 -3
|
@@ -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
|
/**
|
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.175",
|
|
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.175",
|
|
54
|
+
"@firecms/formex": "^3.0.0-canary.175",
|
|
55
|
+
"@firecms/ui": "^3.0.0-canary.175",
|
|
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": "0fd5d55e8bba65c5bd992606c3f8c61e0ad75ed7",
|
|
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-4xl 2xl:max-w-5xl 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,
|
|
@@ -535,7 +575,37 @@ export function EntityEditViewInner<M extends Record<string, any>>({
|
|
|
535
575
|
const selectedEntityView = resolvedEntityViews.find(e => e.key === selectedTab);
|
|
536
576
|
const shouldShowEntityActions = !autoSave && (selectedTab === MAIN_TAB_VALUE || selectedEntityView?.includeActions);
|
|
537
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);
|
|
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) {
|
|
@@ -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>
|
|
@@ -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/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
|
};
|
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 :
|