@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.
Files changed (47) hide show
  1. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  2. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +4 -2
  3. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +1 -0
  4. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +1 -1
  5. package/dist/components/FireCMSAppBar.d.ts +3 -2
  6. package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
  7. package/dist/components/common/types.d.ts +4 -6
  8. package/dist/core/NavigationRoutes.d.ts +1 -1
  9. package/dist/core/Scaffold.d.ts +1 -1
  10. package/dist/hooks/data/save.d.ts +1 -2
  11. package/dist/hooks/useValidateAuthenticator.d.ts +2 -6
  12. package/dist/index.es.js +4102 -4094
  13. package/dist/index.es.js.map +1 -1
  14. package/dist/index.umd.js +5 -5
  15. package/dist/index.umd.js.map +1 -1
  16. package/dist/internal/useBuildDataSource.d.ts +1 -16
  17. package/dist/types/datasource.d.ts +2 -5
  18. package/dist/types/entities.d.ts +5 -1
  19. package/dist/types/index.d.ts +0 -1
  20. package/dist/types/properties.d.ts +2 -2
  21. package/dist/util/entities.d.ts +1 -1
  22. package/package.json +17 -17
  23. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +16 -8
  24. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +6 -4
  25. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +33 -32
  26. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +11 -6
  27. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +2 -4
  28. package/src/components/EntityCollectionView/EntityCollectionView.tsx +10 -6
  29. package/src/components/FireCMSAppBar.tsx +23 -8
  30. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +1 -0
  31. package/src/components/SelectableTable/SelectableTable.tsx +1 -1
  32. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +2 -3
  33. package/src/components/VirtualTable/VirtualTable.tsx +1 -1
  34. package/src/components/common/types.tsx +4 -6
  35. package/src/core/NavigationRoutes.tsx +3 -4
  36. package/src/core/Scaffold.tsx +5 -4
  37. package/src/hooks/data/save.ts +1 -1
  38. package/src/hooks/useValidateAuthenticator.tsx +2 -22
  39. package/src/internal/useBuildDataSource.ts +42 -47
  40. package/src/preview/PropertyPreview.tsx +2 -12
  41. package/src/types/datasource.ts +7 -4
  42. package/src/types/entities.ts +9 -1
  43. package/src/types/index.ts +0 -1
  44. package/src/types/properties.ts +5 -4
  45. package/src/util/entities.ts +1 -1
  46. package/dist/types/appcheck.d.ts +0 -26
  47. package/src/types/appcheck.ts +0 -29
@@ -1,4 +1,4 @@
1
- import { DataSource, DataSourceDelegate, EntityReference, GeoPoint, NavigationController, PropertyConfig } from "../types";
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, EntityReference, EntityStatus, EntityValues, GeoPoint } from "./entities";
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
  }
@@ -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<M extends Record<string, any> = any> {
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
+ }
@@ -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
  */
@@ -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<M>;
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.42",
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.42",
50
- "@firecms/ui": "^3.0.0-canary.42",
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.5.0",
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.2.1",
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.11.30",
90
+ "@types/node": "^20.12.7",
91
91
  "@types/object-hash": "^3.0.6",
92
- "@types/react": "^18.2.67",
93
- "@types/react-dom": "^18.2.22",
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.3.1",
96
- "@typescript-eslint/parser": "^7.3.1",
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.9.0",
106
+ "firebase": "^10.11.0",
107
107
  "jest": "^29.7.0",
108
108
  "npm-run-all": "^4.1.5",
109
- "react-router": "^6.22.0",
110
- "react-router-dom": "^6.22.0",
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.30.7",
114
- "typescript": "^5.4.2",
115
- "vite": "^5.2.3"
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": "d6a2f28e93d3c532dd6efacfccffb91383d5330e",
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?.({ entity, context })}</>;
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
- .map((p) => {
240
- return collectionColumns.find(c => c.key === p.key);
241
- }).filter(Boolean) as VirtualTableColumn[]
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: PropertyColumnConfig[];
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: boolean,
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
- setError(undefined);
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
- setError(undefined);
140
+ setValidationError(undefined);
140
141
  internalValueRef.current = value;
141
142
  if (onValueChange) {
142
- onValueChange({
143
- value,
144
- propertyKey,
145
- setError,
146
- onValueUpdated,
147
- entity,
148
- fullPath: path,
149
- context
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
- setError(e);
159
+ setValidationError(e);
155
160
  });
156
161
  };
157
162
 
158
163
  useEffect(() => {
159
164
  validation
160
165
  .validate(internalValue)
161
- .then(() => setError(undefined))
162
- .catch((e) => {
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 width={width}
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
- isSelected && !internalSaved ? "border-primary" : "",
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, M>) => Promise<void> | void;
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: () => onValueUpdated(),
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}