@firecms/core 3.0.0-alpha.84 → 3.0.0-beta.2-pre.1
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/ArrayContainer.d.ts +1 -3
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -2
- package/dist/components/EntityCollectionTable/{SimpleEntityCollectionTable.d.ts → SimpleTable.d.ts} +7 -26
- package/dist/components/EntityCollectionTable/index.d.ts +1 -1
- package/dist/components/EntityCollectionTable/useDataSourceEntityCollectionTableController.d.ts +1 -1
- package/dist/components/{FieldConfigBadge.d.ts → PropertyConfigBadge.d.ts} +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/core/Scaffold.d.ts +5 -2
- package/dist/form/components/CustomIdField.d.ts +2 -1
- package/dist/index.es.js +4269 -4446
- 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/types/datasource.d.ts +3 -3
- package/dist/types/entity_callbacks.d.ts +1 -1
- package/dist/util/strings.d.ts +1 -1
- package/package.json +16 -16
- package/src/components/ArrayContainer.tsx +31 -67
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +78 -262
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -2
- package/src/components/EntityCollectionTable/{SimpleEntityCollectionTable.tsx → SimpleTable.tsx} +36 -73
- package/src/components/EntityCollectionTable/index.tsx +1 -1
- package/src/components/EntityCollectionTable/useDataSourceEntityCollectionTableController.tsx +1 -1
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +9 -8
- package/src/components/EntityPreview.tsx +0 -1
- package/src/components/LabelWithIcon.tsx +1 -1
- package/src/components/{FieldConfigBadge.tsx → PropertyConfigBadge.tsx} +1 -1
- package/src/components/ReferenceSelectionInner.tsx +0 -1
- package/src/components/index.tsx +1 -1
- package/src/core/NavigationRoutes.tsx +0 -1
- package/src/core/Scaffold.tsx +11 -8
- package/src/form/EntityForm.tsx +12 -2
- package/src/form/components/CustomIdField.tsx +16 -4
- package/src/form/components/ErrorFocus.tsx +1 -1
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
- package/src/form/field_bindings/MarkdownFieldBinding.tsx +2 -2
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +1 -2
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -2
- package/src/hooks/useLargeLayout.tsx +10 -7
- package/src/internal/useBuildDataSource.ts +9 -9
- package/src/preview/PropertyPreviewProps.tsx +1 -1
- package/src/types/datasource.ts +3 -3
- package/src/types/entity_callbacks.ts +2 -1
- package/src/util/strings.ts +2 -1
|
@@ -1,35 +1,22 @@
|
|
|
1
|
-
import React, { useCallback, useContext,
|
|
1
|
+
import React, { useCallback, useContext, useMemo, useRef } from "react";
|
|
2
2
|
import equal from "react-fast-compare";
|
|
3
|
-
import {
|
|
4
|
-
AdditionalFieldDelegate,
|
|
5
|
-
CollectionSize,
|
|
6
|
-
Entity,
|
|
7
|
-
FilterValues,
|
|
8
|
-
FireCMSContext,
|
|
9
|
-
ResolvedProperty,
|
|
10
|
-
SelectedCellProps,
|
|
11
|
-
User
|
|
12
|
-
} from "../../types";
|
|
3
|
+
import { AdditionalFieldDelegate, CollectionSize, Entity, FireCMSContext, User } from "../../types";
|
|
13
4
|
import { PropertyTableCell } from "./PropertyTableCell";
|
|
14
5
|
import { ErrorBoundary } from "../ErrorBoundary";
|
|
15
6
|
import { useFireCMSContext, useLargeLayout } from "../../hooks";
|
|
16
|
-
import { CellRendererParams,
|
|
17
|
-
import {
|
|
7
|
+
import { CellRendererParams, VirtualTableColumn } from "../VirtualTable";
|
|
8
|
+
import { getValueInPath } from "../../util";
|
|
18
9
|
import { getRowHeight } from "../VirtualTable/common";
|
|
19
10
|
import { EntityCollectionRowActions } from "./EntityCollectionRowActions";
|
|
20
11
|
import { EntityCollectionTableController } from "./types";
|
|
21
12
|
import { CollectionTableToolbar } from "./internal/CollectionTableToolbar";
|
|
22
13
|
import { EntityCollectionTableProps } from "./EntityCollectionTableProps";
|
|
23
14
|
import { EntityTableCell } from "./internal/EntityTableCell";
|
|
24
|
-
import { FilterFormFieldProps } from "../VirtualTable/VirtualTableHeader";
|
|
25
|
-
import { ReferenceFilterField } from "./filters/ReferenceFilterField";
|
|
26
|
-
import { StringNumberFilterField } from "./filters/StringNumberFilterField";
|
|
27
|
-
import { BooleanFilterField } from "./filters/BooleanFilterField";
|
|
28
|
-
import { DateTimeFilterField } from "./filters/DateTimeFilterField";
|
|
29
15
|
import { CustomFieldValidator } from "../../form/validation";
|
|
30
16
|
import { renderSkeletonText } from "../../preview";
|
|
31
17
|
import { propertiesToColumns } from "./column_utils";
|
|
32
|
-
import {
|
|
18
|
+
import { ErrorView } from "../ErrorView";
|
|
19
|
+
import { SimpleTable } from "./SimpleTable";
|
|
33
20
|
|
|
34
21
|
const DEFAULT_STATE = {} as any;
|
|
35
22
|
|
|
@@ -64,7 +51,6 @@ export const useEntityCollectionTableController = () => useContext<EntityCollect
|
|
|
64
51
|
export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>(
|
|
65
52
|
function EntityCollectionTable<M extends Record<string, any>, UserType extends User>
|
|
66
53
|
({
|
|
67
|
-
debugKey,
|
|
68
54
|
forceFilter,
|
|
69
55
|
actionsStart,
|
|
70
56
|
actions,
|
|
@@ -85,25 +71,7 @@ export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>
|
|
|
85
71
|
displayedColumnIds,
|
|
86
72
|
defaultSize,
|
|
87
73
|
properties,
|
|
88
|
-
tableController
|
|
89
|
-
{
|
|
90
|
-
data,
|
|
91
|
-
dataLoading,
|
|
92
|
-
noMoreToLoad,
|
|
93
|
-
dataLoadingError,
|
|
94
|
-
filterValues,
|
|
95
|
-
setFilterValues,
|
|
96
|
-
sortBy,
|
|
97
|
-
setSortBy,
|
|
98
|
-
setSearchString,
|
|
99
|
-
clearFilter,
|
|
100
|
-
itemCount,
|
|
101
|
-
setItemCount,
|
|
102
|
-
pageSize = 50,
|
|
103
|
-
paginationEnabled,
|
|
104
|
-
checkFilterCombination,
|
|
105
|
-
setPopupCell
|
|
106
|
-
},
|
|
74
|
+
tableController,
|
|
107
75
|
filterable = true,
|
|
108
76
|
sortable = true,
|
|
109
77
|
endAdornment,
|
|
@@ -126,38 +94,9 @@ export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>
|
|
|
126
94
|
|
|
127
95
|
const [size, setSize] = React.useState<CollectionSize>(defaultSize ?? "m");
|
|
128
96
|
|
|
129
|
-
const [selectedCell, setSelectedCell] = React.useState<SelectedCellProps<M> | undefined>(undefined);
|
|
130
|
-
|
|
131
97
|
const selectedEntityIds = selectedEntities?.map(e => e.id);
|
|
132
98
|
|
|
133
|
-
const filterIsSet = !!filterValues && Object.keys(filterValues).length > 0;
|
|
134
|
-
|
|
135
|
-
const loadNextPage = useCallback(() => {
|
|
136
|
-
if (!paginationEnabled || dataLoading || noMoreToLoad)
|
|
137
|
-
return;
|
|
138
|
-
if (itemCount !== undefined)
|
|
139
|
-
setItemCount?.(itemCount + pageSize);
|
|
140
|
-
}, [dataLoading, itemCount, noMoreToLoad, pageSize, paginationEnabled, setItemCount]);
|
|
141
|
-
|
|
142
|
-
useOutsideAlerter(ref,
|
|
143
|
-
() => {
|
|
144
|
-
if (selectedCell) {
|
|
145
|
-
unselect();
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
Boolean(selectedCell));
|
|
149
|
-
|
|
150
|
-
const resetPagination = useCallback(() => {
|
|
151
|
-
setItemCount?.(pageSize);
|
|
152
|
-
}, [pageSize]);
|
|
153
|
-
|
|
154
|
-
const onRowClickCallback = useCallback(({ rowData }: {
|
|
155
|
-
rowData: Entity<M>
|
|
156
|
-
}) => {
|
|
157
|
-
if (inlineEditing)
|
|
158
|
-
return;
|
|
159
|
-
return onEntityClick && onEntityClick(rowData);
|
|
160
|
-
}, [onEntityClick, inlineEditing]);
|
|
99
|
+
const filterIsSet = !!tableController.filterValues && Object.keys(tableController.filterValues).length > 0;
|
|
161
100
|
|
|
162
101
|
const updateSize = useCallback((size: CollectionSize) => {
|
|
163
102
|
if (onSizeChanged)
|
|
@@ -165,7 +104,7 @@ export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>
|
|
|
165
104
|
setSize(size);
|
|
166
105
|
}, []);
|
|
167
106
|
|
|
168
|
-
const onTextSearch = useCallback((newSearchString?: string) => setSearchString?.(newSearchString), []);
|
|
107
|
+
const onTextSearch = useCallback((newSearchString?: string) => tableController.setSearchString?.(newSearchString), []);
|
|
169
108
|
|
|
170
109
|
const additionalFieldsMap: Record<string, AdditionalFieldDelegate<M, UserType>> = useMemo(() => {
|
|
171
110
|
return (additionalFields
|
|
@@ -175,27 +114,6 @@ export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>
|
|
|
175
114
|
: {}) as Record<string, AdditionalFieldDelegate<M, UserType>>;
|
|
176
115
|
}, [additionalFields]);
|
|
177
116
|
|
|
178
|
-
// on ESC key press
|
|
179
|
-
useEffect(() => {
|
|
180
|
-
const escFunction = (event: any) => {
|
|
181
|
-
if (event.keyCode === 27) {
|
|
182
|
-
unselect();
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
document.addEventListener("keydown", escFunction, false);
|
|
186
|
-
return () => {
|
|
187
|
-
document.removeEventListener("keydown", escFunction, false);
|
|
188
|
-
};
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
const select = useCallback((cell?: SelectedCellProps<M>) => {
|
|
192
|
-
setSelectedCell(cell);
|
|
193
|
-
}, []);
|
|
194
|
-
|
|
195
|
-
const unselect = useCallback(() => {
|
|
196
|
-
setSelectedCell(undefined);
|
|
197
|
-
}, []);
|
|
198
|
-
|
|
199
117
|
const customFieldValidator: CustomFieldValidator | undefined = uniqueFieldValidator;
|
|
200
118
|
|
|
201
119
|
const propertyCellRenderer = useCallback(({
|
|
@@ -338,184 +256,82 @@ export const EntityCollectionTable = React.memo<EntityCollectionTableProps<any>>
|
|
|
338
256
|
const column = props.column;
|
|
339
257
|
const columns = props.columns;
|
|
340
258
|
const columnKey = column.key;
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
if (props.columnIndex === 0) {
|
|
262
|
+
if (tableRowActionsBuilder)
|
|
263
|
+
return tableRowActionsBuilder({
|
|
264
|
+
entity: props.rowData,
|
|
265
|
+
size,
|
|
266
|
+
width: column.width,
|
|
267
|
+
frozen: column.frozen
|
|
268
|
+
});
|
|
269
|
+
else
|
|
270
|
+
return <EntityCollectionRowActions entity={props.rowData}
|
|
271
|
+
width={column.width}
|
|
272
|
+
frozen={column.frozen}
|
|
273
|
+
isSelected={false}
|
|
274
|
+
size={size}/>;
|
|
275
|
+
} else if (additionalFieldsMap[columnKey]) {
|
|
276
|
+
return additionalCellRenderer(props);
|
|
277
|
+
} else if (props.columnIndex < columns.length + 1) {
|
|
278
|
+
return propertyCellRenderer(props);
|
|
279
|
+
} else {
|
|
280
|
+
throw Error("Internal: columns not mapped properly");
|
|
281
|
+
}
|
|
282
|
+
} catch (e: any) {
|
|
283
|
+
console.error("Error rendering cell", e);
|
|
284
|
+
return <EntityTableCell
|
|
285
|
+
size={size}
|
|
286
|
+
width={column.width}
|
|
287
|
+
saved={false}
|
|
288
|
+
value={null}
|
|
289
|
+
align={"left"}
|
|
290
|
+
fullHeight={false}
|
|
291
|
+
disabled={true}>
|
|
292
|
+
<ErrorView error={e}/>
|
|
293
|
+
</EntityTableCell>;
|
|
361
294
|
}
|
|
362
295
|
}, [additionalFieldsMap, tableRowActionsBuilder, size, additionalCellRenderer, propertyCellRenderer])
|
|
363
296
|
|
|
364
|
-
const onFilterUpdate = useCallback((updatedFilterValues?: FilterValues<any>) => {
|
|
365
|
-
setFilterValues?.({ ...updatedFilterValues, ...forceFilter } as FilterValues<any>);
|
|
366
|
-
}, [forceFilter]);
|
|
367
|
-
|
|
368
|
-
// useTraceUpdate({
|
|
369
|
-
// data,
|
|
370
|
-
// columns,
|
|
371
|
-
// inlineEditing,
|
|
372
|
-
// size, selectedEntityIds, additionalCellRenderer, propertyCellRenderer,
|
|
373
|
-
// cellRenderer,
|
|
374
|
-
// onRowClick,
|
|
375
|
-
// onEndReached: loadNextPage,
|
|
376
|
-
// onResetPagination: resetPagination,
|
|
377
|
-
// error: dataLoadingError,
|
|
378
|
-
// paginationEnabled,
|
|
379
|
-
// onColumnResize,
|
|
380
|
-
// loading: dataLoading,
|
|
381
|
-
// filter: filterValues,
|
|
382
|
-
// onFilterUpdate,
|
|
383
|
-
// sortBy,
|
|
384
|
-
// onSortByUpdate: setSortBy,
|
|
385
|
-
// hoverRow,
|
|
386
|
-
// emptyComponent,
|
|
387
|
-
// checkFilterCombination,
|
|
388
|
-
// createFilterField,
|
|
389
|
-
// });
|
|
390
|
-
|
|
391
|
-
const onRowClick = inlineEditing ? undefined : (onEntityClick ? onRowClickCallback : undefined);
|
|
392
|
-
|
|
393
297
|
return (
|
|
394
298
|
|
|
395
|
-
<
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
error={dataLoadingError}
|
|
430
|
-
paginationEnabled={paginationEnabled}
|
|
431
|
-
onColumnResize={onColumnResize}
|
|
432
|
-
size={size}
|
|
433
|
-
loading={dataLoading}
|
|
434
|
-
filter={filterValues}
|
|
435
|
-
onFilterUpdate={setFilterValues ? onFilterUpdate : undefined}
|
|
436
|
-
sortBy={sortBy}
|
|
437
|
-
onSortByUpdate={setSortBy as ((sortBy?: [string, "asc" | "desc"]) => void)}
|
|
438
|
-
hoverRow={hoverRow}
|
|
439
|
-
emptyComponent={emptyComponent}
|
|
440
|
-
checkFilterCombination={checkFilterCombination}
|
|
441
|
-
createFilterField={filterable ? createFilterField : undefined}
|
|
442
|
-
rowClassName={useCallback((entity: Entity<M>) => {
|
|
443
|
-
return selectedEntityIds?.includes(entity.id) ? "bg-gray-100 bg-opacity-75 dark:bg-gray-800 dark:bg-opacity-75" : "";
|
|
444
|
-
}, [selectedEntityIds])}
|
|
445
|
-
className="flex-grow"
|
|
446
|
-
endAdornment={endAdornment}
|
|
447
|
-
AddColumnComponent={AddColumnComponent}
|
|
448
|
-
/>
|
|
449
|
-
|
|
450
|
-
</div>
|
|
451
|
-
</EntityCollectionTableContext.Provider>
|
|
299
|
+
<div ref={ref}
|
|
300
|
+
className="h-full w-full flex flex-col bg-white dark:bg-gray-950">
|
|
301
|
+
|
|
302
|
+
<CollectionTableToolbar
|
|
303
|
+
forceFilter={disabledFilterChange}
|
|
304
|
+
filterIsSet={filterIsSet}
|
|
305
|
+
onTextSearch={textSearchEnabled ? onTextSearch : undefined}
|
|
306
|
+
textSearchLoading={textSearchLoading}
|
|
307
|
+
onTextSearchClick={textSearchEnabled ? onTextSearchClick : undefined}
|
|
308
|
+
clearFilter={tableController.clearFilter}
|
|
309
|
+
size={size}
|
|
310
|
+
onSizeChanged={updateSize}
|
|
311
|
+
title={title}
|
|
312
|
+
actionsStart={actionsStart}
|
|
313
|
+
actions={actions}
|
|
314
|
+
loading={tableController.dataLoading}/>
|
|
315
|
+
|
|
316
|
+
<SimpleTable columns={columns}
|
|
317
|
+
size={size}
|
|
318
|
+
inlineEditing={inlineEditing}
|
|
319
|
+
cellRenderer={cellRenderer}
|
|
320
|
+
onEntityClick={onEntityClick}
|
|
321
|
+
highlightedRow={useCallback((entity: Entity<M>) => selectedEntityIds?.includes(entity.id) ?? false, [selectedEntityIds])}
|
|
322
|
+
tableController={tableController}
|
|
323
|
+
onValueChange={onValueChange}
|
|
324
|
+
onColumnResize={onColumnResize}
|
|
325
|
+
hoverRow={hoverRow}
|
|
326
|
+
filterable={filterable}
|
|
327
|
+
emptyComponent={emptyComponent}
|
|
328
|
+
endAdornment={endAdornment}
|
|
329
|
+
AddColumnComponent={AddColumnComponent}/>
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
</div>
|
|
452
333
|
);
|
|
453
334
|
|
|
454
335
|
},
|
|
455
336
|
equal
|
|
456
337
|
);
|
|
457
|
-
|
|
458
|
-
function createFilterField({
|
|
459
|
-
id,
|
|
460
|
-
filterValue,
|
|
461
|
-
setFilterValue,
|
|
462
|
-
column,
|
|
463
|
-
hidden,
|
|
464
|
-
setHidden
|
|
465
|
-
}: FilterFormFieldProps<{
|
|
466
|
-
resolvedProperty: ResolvedProperty,
|
|
467
|
-
disabled: boolean,
|
|
468
|
-
}>): React.ReactNode {
|
|
469
|
-
|
|
470
|
-
if (!column.custom) {
|
|
471
|
-
return null;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
const { resolvedProperty } = column.custom;
|
|
475
|
-
|
|
476
|
-
const isArray = resolvedProperty?.dataType === "array";
|
|
477
|
-
const baseProperty: ResolvedProperty = isArray ? resolvedProperty.of : resolvedProperty;
|
|
478
|
-
if (!baseProperty) {
|
|
479
|
-
return null;
|
|
480
|
-
}
|
|
481
|
-
if (baseProperty.dataType === "reference") {
|
|
482
|
-
return <ReferenceFilterField value={filterValue}
|
|
483
|
-
setValue={setFilterValue}
|
|
484
|
-
name={id as string}
|
|
485
|
-
isArray={isArray}
|
|
486
|
-
path={baseProperty.path}
|
|
487
|
-
title={resolvedProperty?.name}
|
|
488
|
-
previewProperties={baseProperty?.previewProperties}
|
|
489
|
-
hidden={hidden}
|
|
490
|
-
setHidden={setHidden}/>;
|
|
491
|
-
} else if (baseProperty.dataType === "number" || baseProperty.dataType === "string") {
|
|
492
|
-
const name = baseProperty.name;
|
|
493
|
-
const enumValues = baseProperty.enumValues ? enumToObjectEntries(baseProperty.enumValues) : undefined;
|
|
494
|
-
return <StringNumberFilterField value={filterValue}
|
|
495
|
-
setValue={setFilterValue}
|
|
496
|
-
name={id as string}
|
|
497
|
-
dataType={baseProperty.dataType}
|
|
498
|
-
isArray={isArray}
|
|
499
|
-
enumValues={enumValues}
|
|
500
|
-
title={name}/>;
|
|
501
|
-
} else if (baseProperty.dataType === "boolean") {
|
|
502
|
-
const name = baseProperty.name;
|
|
503
|
-
return <BooleanFilterField value={filterValue}
|
|
504
|
-
setValue={setFilterValue}
|
|
505
|
-
name={id as string}
|
|
506
|
-
title={name}/>;
|
|
507
|
-
|
|
508
|
-
} else if (baseProperty.dataType === "date") {
|
|
509
|
-
const title = baseProperty.name;
|
|
510
|
-
return <DateTimeFilterField value={filterValue}
|
|
511
|
-
setValue={setFilterValue}
|
|
512
|
-
name={id as string}
|
|
513
|
-
mode={baseProperty.mode}
|
|
514
|
-
isArray={isArray}
|
|
515
|
-
title={title}/>;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
return (
|
|
519
|
-
<div>{`Currently the filter field ${resolvedProperty.dataType} is not supported`}</div>
|
|
520
|
-
);
|
|
521
|
-
}
|
|
@@ -23,7 +23,6 @@ export type OnColumnResizeParams = { width: number, key: string };
|
|
|
23
23
|
export type EntityCollectionTableProps<M extends Record<string, any>,
|
|
24
24
|
UserType extends User = User> = {
|
|
25
25
|
|
|
26
|
-
debugKey?: string;
|
|
27
26
|
/**
|
|
28
27
|
* Display these entities as selected
|
|
29
28
|
*/
|
|
@@ -103,7 +102,7 @@ export type EntityCollectionTableProps<M extends Record<string, any>,
|
|
|
103
102
|
|
|
104
103
|
textSearchEnabled?: boolean;
|
|
105
104
|
|
|
106
|
-
inlineEditing?: boolean
|
|
105
|
+
inlineEditing?: boolean;
|
|
107
106
|
|
|
108
107
|
additionalFields?: AdditionalFieldDelegate<M, UserType>[];
|
|
109
108
|
|
package/src/components/EntityCollectionTable/{SimpleEntityCollectionTable.tsx → SimpleTable.tsx}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect } from "react";
|
|
1
|
+
import React, { useCallback, useEffect, useRef } from "react";
|
|
2
2
|
import equal from "react-fast-compare";
|
|
3
3
|
import {
|
|
4
4
|
CollectionSize,
|
|
@@ -6,33 +6,21 @@ import {
|
|
|
6
6
|
EntityTableController,
|
|
7
7
|
FilterValues,
|
|
8
8
|
ResolvedProperty,
|
|
9
|
-
SelectedCellProps
|
|
10
|
-
User
|
|
9
|
+
SelectedCellProps
|
|
11
10
|
} from "../../types";
|
|
12
|
-
import { useLargeLayout } from "../../hooks";
|
|
13
11
|
import { CellRendererParams, VirtualTable, VirtualTableColumn } from "../VirtualTable";
|
|
14
12
|
import { enumToObjectEntries } from "../../util";
|
|
15
13
|
import { OnCellValueChange } from "./types";
|
|
16
|
-
import {
|
|
17
|
-
import { EntityCollectionTableProps, OnColumnResizeParams } from "./EntityCollectionTableProps";
|
|
14
|
+
import { OnColumnResizeParams } from "./EntityCollectionTableProps";
|
|
18
15
|
import { FilterFormFieldProps } from "../VirtualTable/VirtualTableHeader";
|
|
19
16
|
import { ReferenceFilterField } from "./filters/ReferenceFilterField";
|
|
20
17
|
import { StringNumberFilterField } from "./filters/StringNumberFilterField";
|
|
21
18
|
import { BooleanFilterField } from "./filters/BooleanFilterField";
|
|
22
19
|
import { DateTimeFilterField } from "./filters/DateTimeFilterField";
|
|
23
20
|
import { EntityCollectionTableContext } from "./EntityCollectionTable";
|
|
21
|
+
import { useOutsideAlerter } from "@firecms/ui";
|
|
24
22
|
|
|
25
|
-
export type
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* List of entities that will be displayed as selected;
|
|
29
|
-
*/
|
|
30
|
-
highlightedEntities?: Entity<M>[];
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Override the title in the toolbar
|
|
34
|
-
*/
|
|
35
|
-
title?: React.ReactNode;
|
|
23
|
+
export type SimpleTableProps<M extends Record<string, any>> = {
|
|
36
24
|
|
|
37
25
|
/**
|
|
38
26
|
* Callback when a cell value changes.
|
|
@@ -65,28 +53,11 @@ export type SimpleEntityCollectionTableProps<M extends Record<string, any>> = {
|
|
|
65
53
|
*/
|
|
66
54
|
onColumnResize?(params: OnColumnResizeParams): void;
|
|
67
55
|
|
|
68
|
-
/**
|
|
69
|
-
* Callback when the selected size of the table is changed
|
|
70
|
-
*/
|
|
71
|
-
onSizeChanged?(size: CollectionSize): void;
|
|
72
|
-
|
|
73
56
|
/**
|
|
74
57
|
* Should apply a different style to a row when hovering
|
|
75
58
|
*/
|
|
76
59
|
hoverRow?: boolean;
|
|
77
60
|
|
|
78
|
-
/**
|
|
79
|
-
* Additional component that renders actions such as buttons in the
|
|
80
|
-
* collection toolbar, displayed on the left side
|
|
81
|
-
*/
|
|
82
|
-
actionsStart?: React.ReactNode;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Additional component that renders actions such as buttons in the
|
|
86
|
-
* collection toolbar, displayed on the right side
|
|
87
|
-
*/
|
|
88
|
-
actions?: React.ReactNode;
|
|
89
|
-
|
|
90
61
|
/**
|
|
91
62
|
* Controller holding the logic for the table
|
|
92
63
|
* {@link useDataSourceEntityCollectionTableController}
|
|
@@ -100,14 +71,18 @@ export type SimpleEntityCollectionTableProps<M extends Record<string, any>> = {
|
|
|
100
71
|
|
|
101
72
|
inlineEditing?: boolean;
|
|
102
73
|
|
|
103
|
-
|
|
74
|
+
forceFilter?: FilterValues<keyof M extends string ? keyof M : never>;
|
|
75
|
+
|
|
76
|
+
highlightedRow?: (data: Entity<M>) => boolean;
|
|
104
77
|
|
|
105
|
-
|
|
78
|
+
size?: CollectionSize;
|
|
106
79
|
|
|
107
|
-
|
|
108
|
-
}
|
|
80
|
+
emptyComponent?: React.ReactNode;
|
|
109
81
|
|
|
82
|
+
endAdornment?: React.ReactNode;
|
|
110
83
|
|
|
84
|
+
AddColumnComponent?: React.ComponentType;
|
|
85
|
+
}
|
|
111
86
|
|
|
112
87
|
/**
|
|
113
88
|
* This component is in charge of rendering a collection table with a high
|
|
@@ -133,18 +108,13 @@ export type SimpleEntityCollectionTableProps<M extends Record<string, any>> = {
|
|
|
133
108
|
* @see VirtualTable
|
|
134
109
|
* @group Components
|
|
135
110
|
*/
|
|
136
|
-
export const
|
|
137
|
-
function
|
|
111
|
+
export const SimpleTable = React.memo<SimpleTableProps<any>>(
|
|
112
|
+
function SimpleTable<M extends Record<string, any>>
|
|
138
113
|
({
|
|
139
|
-
actionsStart,
|
|
140
|
-
actions,
|
|
141
|
-
title,
|
|
142
114
|
onValueChange,
|
|
143
115
|
cellRenderer,
|
|
144
|
-
highlightedEntities,
|
|
145
116
|
onEntityClick,
|
|
146
117
|
onColumnResize,
|
|
147
|
-
onSizeChanged,
|
|
148
118
|
hoverRow = true,
|
|
149
119
|
inlineEditing = false,
|
|
150
120
|
tableController:
|
|
@@ -167,21 +137,19 @@ export const SimpleEntityCollectionTable = React.memo<SimpleEntityCollectionTabl
|
|
|
167
137
|
setPopupCell
|
|
168
138
|
},
|
|
169
139
|
filterable = true,
|
|
170
|
-
sortable = true,
|
|
171
140
|
emptyComponent,
|
|
172
|
-
textSearchEnabled,
|
|
173
141
|
columns,
|
|
174
|
-
forceFilter
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
142
|
+
forceFilter,
|
|
143
|
+
highlightedRow,
|
|
144
|
+
endAdornment,
|
|
145
|
+
AddColumnComponent
|
|
146
|
+
}: SimpleTableProps<M>) {
|
|
178
147
|
|
|
148
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
179
149
|
const [size, setSize] = React.useState<CollectionSize>("m");
|
|
180
150
|
|
|
181
151
|
const [selectedCell, setSelectedCell] = React.useState<SelectedCellProps<M> | undefined>(undefined);
|
|
182
152
|
|
|
183
|
-
const filterIsSet = !!filterValues && Object.keys(filterValues).length > 0;
|
|
184
|
-
|
|
185
153
|
const loadNextPage = () => {
|
|
186
154
|
if (!paginationEnabled || dataLoading || noMoreToLoad)
|
|
187
155
|
return;
|
|
@@ -201,13 +169,13 @@ export const SimpleEntityCollectionTable = React.memo<SimpleEntityCollectionTabl
|
|
|
201
169
|
return onEntityClick && onEntityClick(rowData);
|
|
202
170
|
}, [onEntityClick, inlineEditing]);
|
|
203
171
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
172
|
+
useOutsideAlerter(ref,
|
|
173
|
+
() => {
|
|
174
|
+
if (selectedCell) {
|
|
175
|
+
unselect();
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
Boolean(selectedCell));
|
|
211
179
|
|
|
212
180
|
// on ESC key press
|
|
213
181
|
useEffect(() => {
|
|
@@ -244,18 +212,8 @@ export const SimpleEntityCollectionTable = React.memo<SimpleEntityCollectionTabl
|
|
|
244
212
|
selectedCell,
|
|
245
213
|
}}
|
|
246
214
|
>
|
|
247
|
-
<div className="h-full w-full flex flex-col bg-white dark:bg-gray-950"
|
|
248
|
-
|
|
249
|
-
<CollectionTableToolbar
|
|
250
|
-
filterIsSet={filterIsSet}
|
|
251
|
-
onTextSearch={textSearchEnabled ? onTextSearch : undefined}
|
|
252
|
-
clearFilter={clearFilter}
|
|
253
|
-
size={size}
|
|
254
|
-
onSizeChanged={updateSize}
|
|
255
|
-
title={title}
|
|
256
|
-
actionsStart={actionsStart}
|
|
257
|
-
actions={actions}
|
|
258
|
-
loading={dataLoading}/>
|
|
215
|
+
<div className="h-full w-full flex flex-col bg-white dark:bg-gray-950"
|
|
216
|
+
ref={ref}>
|
|
259
217
|
|
|
260
218
|
<VirtualTable
|
|
261
219
|
data={data}
|
|
@@ -274,10 +232,15 @@ export const SimpleEntityCollectionTable = React.memo<SimpleEntityCollectionTabl
|
|
|
274
232
|
sortBy={sortBy}
|
|
275
233
|
onSortByUpdate={setSortBy as ((sortBy?: [string, "asc" | "desc"]) => void)}
|
|
276
234
|
hoverRow={hoverRow}
|
|
277
|
-
emptyComponent={emptyComponent}
|
|
278
235
|
checkFilterCombination={checkFilterCombination}
|
|
279
236
|
createFilterField={filterable ? createFilterField : undefined}
|
|
237
|
+
rowClassName={useCallback((entity: Entity<M>) => {
|
|
238
|
+
return highlightedRow?.(entity) ? "bg-gray-100 bg-opacity-75 dark:bg-gray-800 dark:bg-opacity-75" : "";
|
|
239
|
+
}, [highlightedRow])}
|
|
280
240
|
className="flex-grow"
|
|
241
|
+
emptyComponent={emptyComponent}
|
|
242
|
+
endAdornment={endAdornment}
|
|
243
|
+
AddColumnComponent={AddColumnComponent}
|
|
281
244
|
/>
|
|
282
245
|
|
|
283
246
|
</div>
|
|
@@ -14,7 +14,7 @@ export type {
|
|
|
14
14
|
} from "./types";
|
|
15
15
|
|
|
16
16
|
export * from "./PropertyTableCell";
|
|
17
|
-
export * from "./
|
|
17
|
+
export * from "./SimpleTable";
|
|
18
18
|
export * from "./EntityCollectionRowActions";
|
|
19
19
|
export * from "./useDataSourceEntityCollectionTableController";
|
|
20
20
|
export * from "./column_utils";
|
package/src/components/EntityCollectionTable/useDataSourceEntityCollectionTableController.tsx
CHANGED
|
@@ -5,10 +5,10 @@ import { useDataOrder } from "../../hooks/data/useDataOrder";
|
|
|
5
5
|
import {
|
|
6
6
|
Entity,
|
|
7
7
|
EntityCollection,
|
|
8
|
+
EntityTableController,
|
|
8
9
|
FilterValues,
|
|
9
10
|
FireCMSContext,
|
|
10
11
|
SelectedCellProps,
|
|
11
|
-
EntityTableController,
|
|
12
12
|
User
|
|
13
13
|
} from "../../types";
|
|
14
14
|
import { useDebouncedData } from "./useDebouncedData";
|
|
@@ -754,14 +754,15 @@ function EntitiesCount({
|
|
|
754
754
|
const resolvedPath = useMemo(() => navigation.resolveAliasesFrom(fullPath), [fullPath, navigation.resolveAliasesFrom]);
|
|
755
755
|
|
|
756
756
|
useEffect(() => {
|
|
757
|
-
dataSource.countEntities
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
757
|
+
if (dataSource.countEntities)
|
|
758
|
+
dataSource.countEntities({
|
|
759
|
+
path: resolvedPath,
|
|
760
|
+
collection,
|
|
761
|
+
filter,
|
|
762
|
+
orderBy: sortByProperty,
|
|
763
|
+
order: currentSort
|
|
764
|
+
}).then(setCount).catch(setError);
|
|
765
|
+
}, [fullPath, dataSource.countEntities, resolvedPath, collection, filter, sortByProperty, currentSort]);
|
|
765
766
|
|
|
766
767
|
useEffect(() => {
|
|
767
768
|
if (onCountChange) {
|