@firecms/core 3.0.0-canary.42 → 3.0.0-canary.44
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/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +4 -2
- package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +1 -0
- package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
- package/dist/components/FireCMSAppBar.d.ts +3 -2
- package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
- package/dist/components/common/types.d.ts +4 -6
- package/dist/core/NavigationRoutes.d.ts +1 -1
- package/dist/core/Scaffold.d.ts +1 -1
- package/dist/hooks/data/save.d.ts +1 -2
- package/dist/hooks/useValidateAuthenticator.d.ts +2 -6
- package/dist/index.es.js +4102 -4094
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5 -5
- package/dist/index.umd.js.map +1 -1
- package/dist/internal/useBuildDataSource.d.ts +1 -16
- package/dist/types/datasource.d.ts +2 -5
- package/dist/types/entities.d.ts +5 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/properties.d.ts +2 -2
- package/dist/util/entities.d.ts +1 -1
- package/package.json +17 -17
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +16 -8
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +6 -4
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +33 -32
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +11 -6
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +10 -6
- package/src/components/FireCMSAppBar.tsx +23 -8
- package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +1 -0
- package/src/components/SelectableTable/SelectableTable.tsx +1 -1
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
- package/src/components/VirtualTable/VirtualTable.tsx +1 -1
- package/src/components/common/types.tsx +4 -6
- package/src/core/NavigationRoutes.tsx +3 -4
- package/src/core/Scaffold.tsx +5 -4
- package/src/hooks/data/save.ts +1 -1
- package/src/hooks/useValidateAuthenticator.tsx +2 -22
- package/src/internal/useBuildDataSource.ts +42 -47
- package/src/preview/PropertyPreview.tsx +2 -12
- package/src/types/datasource.ts +7 -4
- package/src/types/entities.ts +9 -1
- package/src/types/index.ts +0 -1
- package/src/types/properties.ts +5 -4
- package/src/util/entities.ts +1 -1
- package/dist/types/appcheck.d.ts +0 -26
- package/src/types/appcheck.ts +0 -29
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataSource, DataSourceDelegate,
|
|
1
|
+
import { DataSource, DataSourceDelegate, NavigationController, PropertyConfig } from "../types";
|
|
2
2
|
/**
|
|
3
3
|
* Use this hook to build a {@link DataSource} based on Firestore
|
|
4
4
|
* @param firebaseApp
|
|
@@ -9,18 +9,3 @@ export declare function useBuildDataSource({ delegate, propertyConfigs, navigati
|
|
|
9
9
|
propertyConfigs?: Record<string, PropertyConfig>;
|
|
10
10
|
navigationController: NavigationController;
|
|
11
11
|
}): DataSource;
|
|
12
|
-
/**
|
|
13
|
-
* Recursive function that converts Firestore data types into CMS or plain
|
|
14
|
-
* JS types.
|
|
15
|
-
* FireCMS uses Javascript dates internally instead of Firestore timestamps.
|
|
16
|
-
* This makes it easier to interact with the rest of the libraries and
|
|
17
|
-
* bindings.
|
|
18
|
-
* Also, Firestore references are replaced with {@link EntityReference}
|
|
19
|
-
* @param data
|
|
20
|
-
* @param buildReference
|
|
21
|
-
* @param buildGeoPoint
|
|
22
|
-
* @param buildDate
|
|
23
|
-
* @param buildDelete
|
|
24
|
-
* @group Firestore
|
|
25
|
-
*/
|
|
26
|
-
export declare function cmsToDelegateModel(data: any, buildReference: (reference: EntityReference) => any, buildGeoPoint: (geoPoint: GeoPoint) => any, buildDate: (date: Date) => any, buildDelete: () => any): any;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Entity,
|
|
1
|
+
import { Entity, EntityStatus, EntityValues } from "./entities";
|
|
2
2
|
import { EntityCollection, FilterValues } from "./collections";
|
|
3
3
|
import { ResolvedEntityCollection } from "./resolved_entities";
|
|
4
4
|
/**
|
|
@@ -245,18 +245,15 @@ export interface DataSourceDelegate {
|
|
|
245
245
|
* Convert a FireCMS reference to a reference that can be used by the datasource
|
|
246
246
|
* @param reference
|
|
247
247
|
*/
|
|
248
|
-
buildReference: (reference: EntityReference) => any;
|
|
249
248
|
/**
|
|
250
249
|
* Convert a FireCMS GeoPoint to a GeoPoint that can be used by the datasource
|
|
251
250
|
* @param geoPoint
|
|
252
251
|
*/
|
|
253
|
-
buildGeoPoint: (geoPoint: GeoPoint) => any;
|
|
254
252
|
/**
|
|
255
253
|
* Get the object to generate the current time in the datasource
|
|
256
254
|
*/
|
|
257
255
|
currentTime(): any;
|
|
258
|
-
buildDate: (date: Date) => any;
|
|
259
|
-
buildDeleteFieldValue: () => any;
|
|
260
256
|
delegateToCMSModel: (data: any) => any;
|
|
257
|
+
cmsToDelegateModel: (data: any) => any;
|
|
261
258
|
setDateToMidnight: (input?: any) => any;
|
|
262
259
|
}
|
package/dist/types/entities.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type EntityValues<M extends object> = M;
|
|
|
31
31
|
/**
|
|
32
32
|
* Class used to create a reference to an entity in a different path
|
|
33
33
|
*/
|
|
34
|
-
export declare class EntityReference
|
|
34
|
+
export declare class EntityReference {
|
|
35
35
|
/**
|
|
36
36
|
* ID of the entity
|
|
37
37
|
*/
|
|
@@ -56,3 +56,7 @@ export declare class GeoPoint {
|
|
|
56
56
|
readonly longitude: number;
|
|
57
57
|
constructor(latitude: number, longitude: number);
|
|
58
58
|
}
|
|
59
|
+
export declare class Vector {
|
|
60
|
+
readonly value: number[];
|
|
61
|
+
constructor(value: number[]);
|
|
62
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -23,7 +23,6 @@ export * from "./plugins";
|
|
|
23
23
|
export * from "./analytics";
|
|
24
24
|
export * from "./firecms";
|
|
25
25
|
export * from "./roles";
|
|
26
|
-
export * from "./appcheck";
|
|
27
26
|
export * from "./export_import";
|
|
28
27
|
export * from "./modify_collections";
|
|
29
28
|
export * from "./analytics_controller";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { FieldProps } from "./fields";
|
|
3
3
|
import { PropertyPreviewProps } from "../preview";
|
|
4
|
-
import { EntityReference, EntityValues, GeoPoint } from "./entities";
|
|
4
|
+
import { EntityReference, EntityValues, GeoPoint, Vector } from "./entities";
|
|
5
5
|
import { ResolvedArrayProperty, ResolvedStringProperty } from "./resolved_entities";
|
|
6
6
|
import { FilterValues } from "./collections";
|
|
7
7
|
import { ChipColorKey, ChipColorScheme } from "@firecms/ui";
|
|
8
8
|
/**
|
|
9
9
|
* @group Entity properties
|
|
10
10
|
*/
|
|
11
|
-
export type DataType<T extends CMSType = CMSType> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : T extends Date ? "date" : T extends GeoPoint ? "geopoint" : T extends EntityReference ? "reference" : T extends Array<CMSType> ? "array" : T extends Record<string, any> ? "map" : never;
|
|
11
|
+
export type DataType<T extends CMSType = CMSType> = T extends string ? "string" : T extends number ? "number" : T extends boolean ? "boolean" : T extends Date ? "date" : T extends GeoPoint ? "geopoint" : T extends Vector ? "vector" : T extends EntityReference ? "reference" : T extends Array<CMSType> ? "array" : T extends Record<string, any> ? "map" : never;
|
|
12
12
|
/**
|
|
13
13
|
* @group Entity properties
|
|
14
14
|
*/
|
package/dist/util/entities.d.ts
CHANGED
|
@@ -23,6 +23,6 @@ export declare function updateDateAutoValues<M extends Record<string, any>>({ in
|
|
|
23
23
|
* @group Datasource
|
|
24
24
|
*/
|
|
25
25
|
export declare function sanitizeData<M extends Record<string, any>>(values: EntityValues<M>, properties: ResolvedProperties<M>): any;
|
|
26
|
-
export declare function getReferenceFrom<M extends Record<string, any>>(entity: Entity<M>): EntityReference
|
|
26
|
+
export declare function getReferenceFrom<M extends Record<string, any>>(entity: Entity<M>): EntityReference;
|
|
27
27
|
export declare function traverseValuesProperties<M extends Record<string, any>>(inputValues: Partial<EntityValues<M>>, properties: ResolvedProperties<M>, operation: (value: any, property: Property) => any): EntityValues<M> | undefined;
|
|
28
28
|
export declare function traverseValueProperty(inputValue: any, property: Property, operation: (value: any, property: Property) => any): any;
|
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.44",
|
|
5
5
|
"description": "Awesome Firebase/Firestore-based headless open-source CMS",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/firecmsco"
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"./package.json": "./package.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@firecms/formex": "^3.0.0-canary.
|
|
50
|
-
"@firecms/ui": "^3.0.0-canary.
|
|
49
|
+
"@firecms/formex": "^3.0.0-canary.44",
|
|
50
|
+
"@firecms/ui": "^3.0.0-canary.44",
|
|
51
51
|
"@fontsource/jetbrains-mono": "^5.0.19",
|
|
52
|
-
"@hello-pangea/dnd": "^16.
|
|
52
|
+
"@hello-pangea/dnd": "^16.6.0",
|
|
53
53
|
"@radix-ui/react-portal": "^1.0.4",
|
|
54
54
|
"clsx": "^2.1.0",
|
|
55
55
|
"date-fns": "^3.6.0",
|
|
@@ -84,16 +84,16 @@
|
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@jest/globals": "^29.7.0",
|
|
86
86
|
"@testing-library/jest-dom": "^6.4.2",
|
|
87
|
-
"@testing-library/react": "^14.
|
|
87
|
+
"@testing-library/react": "^14.3.1",
|
|
88
88
|
"@testing-library/user-event": "^14.5.2",
|
|
89
89
|
"@types/jest": "^29.5.12",
|
|
90
|
-
"@types/node": "^20.
|
|
90
|
+
"@types/node": "^20.12.7",
|
|
91
91
|
"@types/object-hash": "^3.0.6",
|
|
92
|
-
"@types/react": "^18.2.
|
|
93
|
-
"@types/react-dom": "^18.2.
|
|
92
|
+
"@types/react": "^18.2.79",
|
|
93
|
+
"@types/react-dom": "^18.2.25",
|
|
94
94
|
"@types/react-measure": "^2.0.12",
|
|
95
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
96
|
-
"@typescript-eslint/parser": "^7.
|
|
95
|
+
"@typescript-eslint/eslint-plugin": "^7.7.0",
|
|
96
|
+
"@typescript-eslint/parser": "^7.7.0",
|
|
97
97
|
"@vitejs/plugin-react": "^4.2.1",
|
|
98
98
|
"cross-env": "^7.0.3",
|
|
99
99
|
"eslint": "^8.57.0",
|
|
@@ -103,22 +103,22 @@
|
|
|
103
103
|
"eslint-plugin-promise": "^6.1.1",
|
|
104
104
|
"eslint-plugin-react": "^7.34.1",
|
|
105
105
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
106
|
-
"firebase": "^10.
|
|
106
|
+
"firebase": "^10.11.0",
|
|
107
107
|
"jest": "^29.7.0",
|
|
108
108
|
"npm-run-all": "^4.1.5",
|
|
109
|
-
"react-router": "^6.22.
|
|
110
|
-
"react-router-dom": "^6.22.
|
|
109
|
+
"react-router": "^6.22.3",
|
|
110
|
+
"react-router-dom": "^6.22.3",
|
|
111
111
|
"ts-jest": "^29.1.2",
|
|
112
112
|
"ts-node": "^10.9.2",
|
|
113
|
-
"tsd": "^0.
|
|
114
|
-
"typescript": "^5.4.
|
|
115
|
-
"vite": "^5.2.
|
|
113
|
+
"tsd": "^0.31.0",
|
|
114
|
+
"typescript": "^5.4.5",
|
|
115
|
+
"vite": "^5.2.9"
|
|
116
116
|
},
|
|
117
117
|
"files": [
|
|
118
118
|
"dist",
|
|
119
119
|
"src"
|
|
120
120
|
],
|
|
121
|
-
"gitHead": "
|
|
121
|
+
"gitHead": "15e52171f137c2876a3566bbc2752d140b9d0c7a",
|
|
122
122
|
"publishConfig": {
|
|
123
123
|
"access": "public"
|
|
124
124
|
}
|
|
@@ -15,7 +15,7 @@ import { renderSkeletonText } from "../../preview";
|
|
|
15
15
|
import { propertiesToColumns } from "./column_utils";
|
|
16
16
|
import { ErrorView } from "../ErrorView";
|
|
17
17
|
import { SelectableTable } from "../SelectableTable/SelectableTable";
|
|
18
|
-
|
|
18
|
+
import { cn } from "@firecms/ui";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* This component is in charge of rendering a collection table with a high
|
|
@@ -43,6 +43,7 @@ import { SelectableTable } from "../SelectableTable/SelectableTable";
|
|
|
43
43
|
*/
|
|
44
44
|
export const EntityCollectionTable = function EntityCollectionTable<M extends Record<string, any>, UserType extends User>
|
|
45
45
|
({
|
|
46
|
+
className,
|
|
46
47
|
forceFilter,
|
|
47
48
|
actionsStart,
|
|
48
49
|
actions,
|
|
@@ -73,7 +74,8 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
73
74
|
emptyComponent,
|
|
74
75
|
getIdColumnWidth,
|
|
75
76
|
onTextSearchClick,
|
|
76
|
-
textSearchLoading
|
|
77
|
+
textSearchLoading,
|
|
78
|
+
enablePopupIcon
|
|
77
79
|
}: EntityCollectionTableProps<M>) {
|
|
78
80
|
|
|
79
81
|
const ref = useRef<HTMLDivElement>(null);
|
|
@@ -148,6 +150,7 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
148
150
|
height={getRowHeight(size)}
|
|
149
151
|
entity={entity}
|
|
150
152
|
disabled={disabled}
|
|
153
|
+
enablePopupIcon={enablePopupIcon}
|
|
151
154
|
path={entity.path}/>
|
|
152
155
|
: renderSkeletonText()
|
|
153
156
|
}
|
|
@@ -177,7 +180,10 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
177
180
|
|
|
178
181
|
const child = Builder
|
|
179
182
|
? <Builder entity={entity} context={context}/>
|
|
180
|
-
: <>{additionalField.value?.({
|
|
183
|
+
: <>{additionalField.value?.({
|
|
184
|
+
entity,
|
|
185
|
+
context
|
|
186
|
+
})}</>;
|
|
181
187
|
|
|
182
188
|
return (
|
|
183
189
|
<EntityTableCell
|
|
@@ -235,10 +241,12 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
235
241
|
|
|
236
242
|
const columns: VirtualTableColumn[] = [
|
|
237
243
|
idColumn,
|
|
238
|
-
...displayedColumnIds
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
244
|
+
...(displayedColumnIds
|
|
245
|
+
? displayedColumnIds
|
|
246
|
+
.map((p) => {
|
|
247
|
+
return collectionColumns.find(c => c.key === p.key);
|
|
248
|
+
}).filter(Boolean)
|
|
249
|
+
: collectionColumns) as VirtualTableColumn[]
|
|
242
250
|
];
|
|
243
251
|
|
|
244
252
|
const cellRenderer = (props: CellRendererParams<any>) => {
|
|
@@ -286,7 +294,7 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
286
294
|
return (
|
|
287
295
|
|
|
288
296
|
<div ref={ref}
|
|
289
|
-
className="h-full w-full flex flex-col bg-white dark:bg-gray-950">
|
|
297
|
+
className={cn("h-full w-full flex flex-col bg-white dark:bg-gray-950", className)}>
|
|
290
298
|
|
|
291
299
|
<CollectionTableToolbar
|
|
292
300
|
onTextSearch={textSearchEnabled ? onTextSearch : undefined}
|
|
@@ -12,13 +12,13 @@ import {
|
|
|
12
12
|
} from "../../types";
|
|
13
13
|
import { OnCellValueChange, OnColumnResizeParams, UniqueFieldValidator } from "../common/types";
|
|
14
14
|
|
|
15
|
-
|
|
16
15
|
/**
|
|
17
16
|
* @group Collection components
|
|
18
17
|
*/
|
|
19
18
|
export type EntityCollectionTableProps<M extends Record<string, any>,
|
|
20
19
|
UserType extends User = User> = {
|
|
21
20
|
|
|
21
|
+
className?: string;
|
|
22
22
|
/**
|
|
23
23
|
* Display these entities as selected
|
|
24
24
|
*/
|
|
@@ -92,7 +92,7 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
|
|
|
92
92
|
*/
|
|
93
93
|
tableController: EntityTableController<M>;
|
|
94
94
|
|
|
95
|
-
displayedColumnIds
|
|
95
|
+
displayedColumnIds?: PropertyColumnConfig[];
|
|
96
96
|
|
|
97
97
|
forceFilter?: FilterValues<Extract<keyof M, string>>;
|
|
98
98
|
|
|
@@ -131,7 +131,9 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
|
|
|
131
131
|
onTextSearchClick?: () => void;
|
|
132
132
|
|
|
133
133
|
textSearchLoading?: boolean;
|
|
134
|
-
|
|
134
|
+
|
|
135
|
+
enablePopupIcon: boolean;
|
|
136
|
+
};
|
|
135
137
|
|
|
136
138
|
export type GetPropertyForProps<M extends Record<string, any>> = {
|
|
137
139
|
propertyKey: string,
|
|
@@ -141,5 +143,5 @@ export type GetPropertyForProps<M extends Record<string, any>> = {
|
|
|
141
143
|
|
|
142
144
|
export type PropertyColumnConfig = {
|
|
143
145
|
key: string,
|
|
144
|
-
disabled
|
|
146
|
+
disabled?: boolean,
|
|
145
147
|
};
|
|
@@ -46,6 +46,7 @@ export interface PropertyTableCellProps<T extends CMSType> {
|
|
|
46
46
|
entity: Entity<any>;
|
|
47
47
|
path: string;
|
|
48
48
|
disabled: boolean;
|
|
49
|
+
enablePopupIcon?: boolean;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
function isStorageProperty(property: ResolvedProperty) {
|
|
@@ -74,11 +75,10 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
74
75
|
path,
|
|
75
76
|
entity,
|
|
76
77
|
readonly,
|
|
77
|
-
disabled: disabledProp
|
|
78
|
+
disabled: disabledProp,
|
|
79
|
+
enablePopupIcon = true
|
|
78
80
|
}: PropertyTableCellProps<T>) {
|
|
79
81
|
|
|
80
|
-
const context = useFireCMSContext();
|
|
81
|
-
|
|
82
82
|
const {
|
|
83
83
|
onValueChange,
|
|
84
84
|
size,
|
|
@@ -95,6 +95,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
95
95
|
const internalValueRef = useRef(value);
|
|
96
96
|
|
|
97
97
|
const [error, setError] = useState<Error | undefined>();
|
|
98
|
+
const [validationError, setValidationError] = useState<Error | undefined>();
|
|
98
99
|
const [saved, setSaved] = useState<boolean>(false);
|
|
99
100
|
|
|
100
101
|
const onValueUpdated = useCallback(() => {
|
|
@@ -120,7 +121,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
120
121
|
useEffect(
|
|
121
122
|
() => {
|
|
122
123
|
if (!equal(value, internalValueRef.current)) {
|
|
123
|
-
|
|
124
|
+
setValidationError(undefined);
|
|
124
125
|
setInternalValue(value);
|
|
125
126
|
internalValueRef.current = value;
|
|
126
127
|
onValueUpdated();
|
|
@@ -136,32 +137,34 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
136
137
|
validation
|
|
137
138
|
.validate(value)
|
|
138
139
|
.then(() => {
|
|
139
|
-
|
|
140
|
+
setValidationError(undefined);
|
|
140
141
|
internalValueRef.current = value;
|
|
141
142
|
if (onValueChange) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
})
|
|
143
|
+
try {
|
|
144
|
+
onValueChange({
|
|
145
|
+
value,
|
|
146
|
+
propertyKey,
|
|
147
|
+
setError,
|
|
148
|
+
onValueUpdated,
|
|
149
|
+
data: entity,
|
|
150
|
+
});
|
|
151
|
+
} catch (e:any) {
|
|
152
|
+
console.error("onValueChange error", e);
|
|
153
|
+
setError(e);
|
|
154
|
+
}
|
|
155
|
+
|
|
151
156
|
}
|
|
152
157
|
})
|
|
153
158
|
.catch((e) => {
|
|
154
|
-
|
|
159
|
+
setValidationError(e);
|
|
155
160
|
});
|
|
156
161
|
};
|
|
157
162
|
|
|
158
163
|
useEffect(() => {
|
|
159
164
|
validation
|
|
160
165
|
.validate(internalValue)
|
|
161
|
-
.then(() =>
|
|
162
|
-
.catch(
|
|
163
|
-
setError(e);
|
|
164
|
-
});
|
|
166
|
+
.then(() => setValidationError(undefined))
|
|
167
|
+
.catch(setValidationError);
|
|
165
168
|
}, [internalValue, validation, propertyKey, property, entity]);
|
|
166
169
|
|
|
167
170
|
const updateValue = (newValue: any | null) => {
|
|
@@ -237,7 +240,6 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
237
240
|
height={getRowHeight(size)}
|
|
238
241
|
propertyKey={propertyKey}
|
|
239
242
|
property={property}
|
|
240
|
-
// entity={entity}
|
|
241
243
|
value={internalValue}
|
|
242
244
|
size={getPreviewSizeFrom(size)}
|
|
243
245
|
/>
|
|
@@ -247,7 +249,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
247
249
|
if (!customField && (!customPreview || selected)) {
|
|
248
250
|
const isAStorageProperty = isStorageProperty(property);
|
|
249
251
|
if (isAStorageProperty) {
|
|
250
|
-
innerComponent = <TableStorageUpload error={error}
|
|
252
|
+
innerComponent = <TableStorageUpload error={validationError ?? error}
|
|
251
253
|
disabled={disabled}
|
|
252
254
|
focused={selected}
|
|
253
255
|
selected={selected}
|
|
@@ -274,7 +276,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
274
276
|
valueType={"number"}
|
|
275
277
|
small={getPreviewSizeFrom(size) !== "medium"}
|
|
276
278
|
enumValues={numberProperty.enumValues}
|
|
277
|
-
error={error}
|
|
279
|
+
error={validationError ?? error}
|
|
278
280
|
internalValue={internalValue as string | number}
|
|
279
281
|
updateValue={updateValue}
|
|
280
282
|
/>;
|
|
@@ -282,7 +284,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
282
284
|
} else {
|
|
283
285
|
innerComponent = <VirtualTableNumberInput
|
|
284
286
|
align={align}
|
|
285
|
-
error={error}
|
|
287
|
+
error={validationError ?? error}
|
|
286
288
|
focused={selected}
|
|
287
289
|
disabled={disabled}
|
|
288
290
|
value={internalValue as number}
|
|
@@ -300,14 +302,14 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
300
302
|
valueType={"string"}
|
|
301
303
|
small={getPreviewSizeFrom(size) !== "medium"}
|
|
302
304
|
enumValues={stringProperty.enumValues}
|
|
303
|
-
error={error}
|
|
305
|
+
error={validationError ?? error}
|
|
304
306
|
internalValue={internalValue as string | number}
|
|
305
307
|
updateValue={updateValue}
|
|
306
308
|
/>;
|
|
307
309
|
fullHeight = true;
|
|
308
310
|
} else if (!stringProperty.storage) {
|
|
309
311
|
const multiline = Boolean(stringProperty.multiline) || Boolean(stringProperty.markdown);
|
|
310
|
-
innerComponent = <VirtualTableInput error={error}
|
|
312
|
+
innerComponent = <VirtualTableInput error={validationError ?? error}
|
|
311
313
|
disabled={disabled}
|
|
312
314
|
multiline={multiline}
|
|
313
315
|
focused={selected}
|
|
@@ -317,7 +319,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
317
319
|
allowScroll = true;
|
|
318
320
|
}
|
|
319
321
|
} else if (property.dataType === "boolean") {
|
|
320
|
-
innerComponent = <VirtualTableSwitch error={error}
|
|
322
|
+
innerComponent = <VirtualTableSwitch error={validationError ?? error}
|
|
321
323
|
disabled={disabled}
|
|
322
324
|
focused={selected}
|
|
323
325
|
internalValue={internalValue as boolean}
|
|
@@ -325,7 +327,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
325
327
|
/>;
|
|
326
328
|
} else if (property.dataType === "date") {
|
|
327
329
|
innerComponent = <VirtualTableDateField name={propertyKey as string}
|
|
328
|
-
error={error}
|
|
330
|
+
error={validationError ?? error}
|
|
329
331
|
disabled={disabled}
|
|
330
332
|
mode={property.mode}
|
|
331
333
|
focused={selected}
|
|
@@ -368,7 +370,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
368
370
|
small={getPreviewSizeFrom(size) !== "medium"}
|
|
369
371
|
valueType={arrayProperty.of.dataType}
|
|
370
372
|
enumValues={arrayProperty.of.enumValues}
|
|
371
|
-
error={error}
|
|
373
|
+
error={validationError ?? error}
|
|
372
374
|
internalValue={internalValue as string | number}
|
|
373
375
|
updateValue={updateValue}
|
|
374
376
|
/>;
|
|
@@ -401,11 +403,10 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
401
403
|
|
|
402
404
|
if (!innerComponent) {
|
|
403
405
|
allowScroll = false;
|
|
404
|
-
showExpandIcon = selected && !innerComponent && !disabled && !readOnlyProperty;
|
|
406
|
+
showExpandIcon = enablePopupIcon && selected && !innerComponent && !disabled && !readOnlyProperty;
|
|
405
407
|
innerComponent = (
|
|
406
|
-
<PropertyPreview
|
|
408
|
+
<PropertyPreview width={width}
|
|
407
409
|
height={height}
|
|
408
|
-
// entity={entity}
|
|
409
410
|
propertyKey={propertyKey as string}
|
|
410
411
|
value={internalValue}
|
|
411
412
|
property={property}
|
|
@@ -426,7 +427,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
426
427
|
removePadding={removePadding}
|
|
427
428
|
fullHeight={fullHeight}
|
|
428
429
|
saved={saved}
|
|
429
|
-
error={error}
|
|
430
|
+
error={validationError ?? error}
|
|
430
431
|
align={align}
|
|
431
432
|
allowScroll={allowScroll}
|
|
432
433
|
showExpandIcon={showExpandIcon}
|
|
@@ -96,7 +96,7 @@ export const EntityTableCell = React.memo<EntityTableCellProps>(
|
|
|
96
96
|
const [onHover, setOnHover] = useState(false);
|
|
97
97
|
const [internalSaved, setInternalSaved] = useState(saved);
|
|
98
98
|
|
|
99
|
-
const showError = !disabled && error;
|
|
99
|
+
const showError = !disabled && Boolean(error);
|
|
100
100
|
|
|
101
101
|
useEffect(() => {
|
|
102
102
|
if (saved) {
|
|
@@ -176,21 +176,26 @@ export const EntityTableCell = React.memo<EntityTableCellProps>(
|
|
|
176
176
|
const setOnHoverTrue = useCallback(() => setOnHover(true), []);
|
|
177
177
|
const setOnHoverFalse = useCallback(() => setOnHover(false), []);
|
|
178
178
|
|
|
179
|
+
const borderClass = showError
|
|
180
|
+
? "border-red-500"
|
|
181
|
+
: internalSaved
|
|
182
|
+
? "border-green-500"
|
|
183
|
+
: isSelected
|
|
184
|
+
? "border-primary"
|
|
185
|
+
: "border-transparent";
|
|
186
|
+
|
|
179
187
|
return (
|
|
180
188
|
<div
|
|
181
|
-
ref={ref}
|
|
182
189
|
className={cn(
|
|
183
190
|
"transition-colors duration-100 ease-in-out",
|
|
184
191
|
`flex relative h-full rounded-md p-${p} border border-4 border-opacity-75`,
|
|
185
192
|
onHover && !disabled ? "bg-gray-50 dark:bg-gray-900" : "",
|
|
186
193
|
saved ? "bg-gray-100 bg-opacity-75 dark:bg-gray-800 dark:bg-opacity-75" : "",
|
|
187
|
-
!isSelected && !internalSaved && !showError ? "border-transparent" : "",
|
|
188
194
|
hideOverflow ? "overflow-hidden" : "",
|
|
189
195
|
isSelected ? "bg-gray-50 dark:bg-gray-900" : "",
|
|
190
|
-
|
|
191
|
-
internalSaved ? "border-green-500 " : "",
|
|
192
|
-
showError ? "border-red-500" : ""
|
|
196
|
+
borderClass
|
|
193
197
|
)}
|
|
198
|
+
ref={ref}
|
|
194
199
|
style={{
|
|
195
200
|
justifyContent,
|
|
196
201
|
alignItems: disabled || !isOverflowing ? "center" : undefined,
|
|
@@ -41,7 +41,7 @@ interface PopupFormFieldProps<M extends Record<string, any>> {
|
|
|
41
41
|
* Callback when the value of a cell has been edited
|
|
42
42
|
* @param params
|
|
43
43
|
*/
|
|
44
|
-
onCellValueChange?: (params: OnCellValueChangeParams<any,
|
|
44
|
+
onCellValueChange?: (params: OnCellValueChangeParams<any, any>) => Promise<void> | void;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export function PopupFormField<M extends Record<string, any>>(props: PopupFormFieldProps<M>) {
|
|
@@ -205,12 +205,10 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
|
|
|
205
205
|
return onCellValueChange({
|
|
206
206
|
value: values[propertyKey as string],
|
|
207
207
|
propertyKey: propertyKey as string,
|
|
208
|
-
entity,
|
|
208
|
+
data: entity,
|
|
209
209
|
setError: setSavingError,
|
|
210
210
|
onValueUpdated: () => {
|
|
211
211
|
},
|
|
212
|
-
fullPath: path,
|
|
213
|
-
context: fireCMSContext
|
|
214
212
|
});
|
|
215
213
|
}
|
|
216
214
|
return Promise.resolve();
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
saveEntityWithCallbacks,
|
|
35
35
|
useAuthController,
|
|
36
36
|
useCustomizationController,
|
|
37
|
-
useDataSource,
|
|
37
|
+
useDataSource, useFireCMSContext,
|
|
38
38
|
useLargeLayout,
|
|
39
39
|
useNavigationController,
|
|
40
40
|
useSideEntityController
|
|
@@ -94,7 +94,9 @@ export type EntityCollectionViewProps<M extends Record<string, any>> = {
|
|
|
94
94
|
* Whether this is a subcollection or not.
|
|
95
95
|
*/
|
|
96
96
|
isSubCollection?: boolean;
|
|
97
|
+
|
|
97
98
|
className?: string;
|
|
99
|
+
|
|
98
100
|
} & EntityCollection<M>;
|
|
99
101
|
|
|
100
102
|
/**
|
|
@@ -131,6 +133,7 @@ export const EntityCollectionView = React.memo(
|
|
|
131
133
|
}: EntityCollectionViewProps<M>
|
|
132
134
|
) {
|
|
133
135
|
|
|
136
|
+
const context = useFireCMSContext();
|
|
134
137
|
const fullPath = fullPathProp ?? collectionProp.path;
|
|
135
138
|
const dataSource = useDataSource(collectionProp);
|
|
136
139
|
const navigation = useNavigationController();
|
|
@@ -311,13 +314,11 @@ export const EntityCollectionView = React.memo(
|
|
|
311
314
|
[fullPath]);
|
|
312
315
|
|
|
313
316
|
const onValueChange: OnCellValueChange<any, any> = ({
|
|
314
|
-
fullPath,
|
|
315
|
-
context,
|
|
316
317
|
value,
|
|
317
318
|
propertyKey,
|
|
318
319
|
onValueUpdated,
|
|
319
320
|
setError,
|
|
320
|
-
entity,
|
|
321
|
+
data: entity,
|
|
321
322
|
}) => {
|
|
322
323
|
|
|
323
324
|
const updatedValues = setIn({ ...entity.values }, propertyKey, value);
|
|
@@ -334,10 +335,12 @@ export const EntityCollectionView = React.memo(
|
|
|
334
335
|
return saveEntityWithCallbacks({
|
|
335
336
|
...saveProps,
|
|
336
337
|
collection,
|
|
337
|
-
callbacks: collection.callbacks,
|
|
338
338
|
dataSource,
|
|
339
339
|
context,
|
|
340
|
-
onSaveSuccess: () =>
|
|
340
|
+
onSaveSuccess: () => {
|
|
341
|
+
setError(undefined);
|
|
342
|
+
onValueUpdated();
|
|
343
|
+
},
|
|
341
344
|
onSaveFailure: (e: Error) => {
|
|
342
345
|
console.error("Save failure");
|
|
343
346
|
console.error(e);
|
|
@@ -600,6 +603,7 @@ export const EntityCollectionView = React.memo(
|
|
|
600
603
|
key={`collection_table_${fullPath}`}
|
|
601
604
|
additionalFields={additionalFields}
|
|
602
605
|
tableController={tableController}
|
|
606
|
+
enablePopupIcon={true}
|
|
603
607
|
displayedColumnIds={displayedColumnIds}
|
|
604
608
|
onSizeChanged={onSizeChanged}
|
|
605
609
|
onEntityClick={onEntityClick}
|