@firecms/core 3.0.0-beta.13 → 3.0.0-beta.15
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 +7 -12
- package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +2 -1
- package/dist/components/EntityPreview.d.ts +4 -2
- package/dist/components/HomePage/DefaultHomePage.d.ts +2 -15
- package/dist/components/HomePage/HomePageDnD.d.ts +76 -0
- package/dist/components/HomePage/NavigationCard.d.ts +3 -1
- package/dist/components/HomePage/NavigationCardBinding.d.ts +3 -2
- package/dist/components/HomePage/NavigationGroup.d.ts +7 -1
- package/dist/components/HomePage/RenameGroupDialog.d.ts +9 -0
- package/dist/components/SelectableTable/SelectableTable.d.ts +1 -1
- package/dist/components/VirtualTable/VirtualTableProps.d.ts +0 -4
- package/dist/components/index.d.ts +1 -0
- package/dist/core/EntityEditView.d.ts +3 -0
- package/dist/core/EntityEditViewFormActions.d.ts +1 -1
- package/dist/core/field_configs.d.ts +1 -1
- package/dist/form/EntityForm.d.ts +2 -1
- package/dist/form/EntityFormActions.d.ts +6 -2
- package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +9 -0
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +3 -9
- package/dist/form/index.d.ts +1 -0
- package/dist/hooks/useBuildNavigationController.d.ts +50 -8
- package/dist/index.es.js +3259 -1649
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +3265 -1658
- package/dist/index.umd.js.map +1 -1
- package/dist/types/analytics.d.ts +1 -1
- package/dist/types/collections.d.ts +28 -4
- package/dist/types/customization_controller.d.ts +8 -0
- package/dist/types/entity_actions.d.ts +46 -6
- package/dist/types/firecms.d.ts +10 -1
- package/dist/types/navigation.d.ts +26 -5
- package/dist/types/plugins.d.ts +32 -1
- package/dist/types/properties.d.ts +7 -0
- package/dist/types/property_config.d.ts +1 -1
- package/dist/types/side_entity_controller.d.ts +8 -0
- package/dist/util/callbacks.d.ts +2 -0
- package/dist/util/icons.d.ts +2 -2
- package/dist/util/index.d.ts +1 -0
- package/dist/util/navigation_from_path.d.ts +4 -0
- package/dist/util/resolutions.d.ts +2 -1
- package/package.json +8 -6
- package/src/components/ArrayContainer.tsx +409 -294
- package/src/components/ClearFilterSortButton.tsx +1 -1
- package/src/components/ConfirmationDialog.tsx +10 -9
- package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +6 -0
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +26 -4
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +13 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +53 -27
- package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +9 -9
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +11 -4
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +3 -2
- package/src/components/EntityPreview.tsx +18 -14
- package/src/components/ErrorView.tsx +1 -1
- package/src/components/FireCMSLogo.tsx +7 -51
- package/src/components/HomePage/DefaultHomePage.tsx +491 -156
- package/src/components/HomePage/FavouritesView.tsx +3 -3
- package/src/components/HomePage/HomePageDnD.tsx +599 -0
- package/src/components/HomePage/NavigationCard.tsx +47 -38
- package/src/components/HomePage/NavigationCardBinding.tsx +13 -7
- package/src/components/HomePage/NavigationGroup.tsx +63 -29
- package/src/components/HomePage/RenameGroupDialog.tsx +117 -0
- package/src/components/SelectableTable/SelectableTable.tsx +140 -143
- package/src/components/UnsavedChangesDialog.tsx +6 -2
- package/src/components/VirtualTable/VirtualTable.tsx +8 -30
- package/src/components/VirtualTable/VirtualTableProps.tsx +0 -5
- package/src/components/VirtualTable/fields/VirtualTableInput.tsx +0 -1
- package/src/components/common/default_entity_actions.tsx +25 -9
- package/src/components/common/useDataSourceTableController.tsx +2 -2
- package/src/components/index.tsx +2 -0
- package/src/core/DefaultDrawer.tsx +8 -8
- package/src/core/DrawerNavigationItem.tsx +1 -1
- package/src/core/EntityEditView.tsx +65 -18
- package/src/core/EntityEditViewFormActions.tsx +154 -29
- package/src/core/EntitySidePanel.tsx +19 -21
- package/src/core/FireCMS.tsx +9 -1
- package/src/core/field_configs.tsx +15 -1
- package/src/form/EntityForm.tsx +37 -5
- package/src/form/EntityFormActions.tsx +51 -9
- package/src/form/PropertyFieldBinding.tsx +0 -1
- package/src/form/components/CustomIdField.tsx +3 -1
- package/src/form/components/LabelWithIcon.tsx +1 -1
- package/src/form/components/StorageItemPreview.tsx +1 -1
- package/src/form/components/StorageUploadProgress.tsx +3 -3
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +3 -2
- package/src/form/field_bindings/MapFieldBinding.tsx +5 -4
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +4 -2
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +135 -0
- package/src/form/field_bindings/SelectFieldBinding.tsx +2 -1
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +216 -153
- package/src/form/index.tsx +1 -0
- package/src/hooks/data/save.ts +0 -6
- package/src/hooks/useBuildNavigationController.tsx +299 -96
- package/src/internal/useBuildSideEntityController.tsx +8 -5
- package/src/preview/PropertyPreview.tsx +14 -0
- package/src/preview/components/ImagePreview.tsx +2 -2
- package/src/preview/components/ReferencePreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +1 -1
- package/src/preview/property_previews/MapPropertyPreview.tsx +1 -1
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +1 -1
- package/src/preview/property_previews/StringPropertyPreview.tsx +1 -1
- package/src/routes/FireCMSRoute.tsx +3 -3
- package/src/types/analytics.ts +3 -0
- package/src/types/collections.ts +32 -4
- package/src/types/customization_controller.tsx +9 -0
- package/src/types/entity_actions.tsx +57 -6
- package/src/types/firecms.tsx +11 -2
- package/src/types/navigation.ts +34 -6
- package/src/types/plugins.tsx +40 -1
- package/src/types/properties.ts +8 -0
- package/src/types/property_config.tsx +1 -0
- package/src/types/side_entity_controller.tsx +10 -5
- package/src/util/callbacks.ts +119 -0
- package/src/util/icons.tsx +22 -7
- package/src/util/index.ts +1 -0
- package/src/util/join_collections.ts +3 -1
- package/src/util/navigation_from_path.ts +15 -5
- package/src/util/navigation_utils.ts +72 -57
- package/src/util/objects.ts +53 -20
- package/src/util/resolutions.ts +13 -1
- package/dist/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.d.ts +0 -5
- package/src/components/EntityCollectionTable/internal/popup_field/ElementResizeListener.tsx +0 -59
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect, useRef } from "react";
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
2
|
import {
|
|
3
3
|
CollectionSize,
|
|
4
4
|
Entity,
|
|
@@ -119,150 +119,147 @@ export type SelectableTableProps<M extends Record<string, any>> = {
|
|
|
119
119
|
* @see VirtualTable
|
|
120
120
|
* @group Components
|
|
121
121
|
*/
|
|
122
|
-
export const SelectableTable =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
122
|
+
export const SelectableTable = function SelectableTable<M extends Record<string, any>>
|
|
123
|
+
({
|
|
124
|
+
onValueChange,
|
|
125
|
+
cellRenderer,
|
|
126
|
+
onEntityClick,
|
|
127
|
+
onColumnResize,
|
|
128
|
+
hoverRow = true,
|
|
129
|
+
size = "m",
|
|
130
|
+
inlineEditing = false,
|
|
131
|
+
tableController:
|
|
132
|
+
{
|
|
133
|
+
data,
|
|
134
|
+
dataLoading,
|
|
135
|
+
noMoreToLoad,
|
|
136
|
+
dataLoadingError,
|
|
137
|
+
filterValues,
|
|
138
|
+
setFilterValues,
|
|
139
|
+
sortBy,
|
|
140
|
+
setSortBy,
|
|
141
|
+
itemCount,
|
|
142
|
+
setItemCount,
|
|
143
|
+
pageSize = 50,
|
|
144
|
+
paginationEnabled,
|
|
145
|
+
checkFilterCombination,
|
|
146
|
+
setPopupCell
|
|
147
|
+
},
|
|
148
|
+
filterable = true,
|
|
149
|
+
onScroll,
|
|
150
|
+
initialScroll,
|
|
151
|
+
emptyComponent,
|
|
152
|
+
columns,
|
|
153
|
+
forceFilter,
|
|
154
|
+
highlightedRow,
|
|
155
|
+
endAdornment,
|
|
156
|
+
AddColumnComponent
|
|
157
|
+
}: SelectableTableProps<M>) {
|
|
158
|
+
|
|
159
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
160
|
+
|
|
161
|
+
const [selectedCell, setSelectedCell] = React.useState<SelectedCellProps<M> | undefined>(undefined);
|
|
162
|
+
|
|
163
|
+
const loadNextPage = () => {
|
|
164
|
+
if (!paginationEnabled || dataLoading || noMoreToLoad)
|
|
165
|
+
return;
|
|
166
|
+
if (itemCount !== undefined)
|
|
167
|
+
setItemCount?.(itemCount + pageSize);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const resetPagination = useCallback(() => {
|
|
171
|
+
setItemCount?.(pageSize);
|
|
172
|
+
}, [pageSize]);
|
|
173
|
+
|
|
174
|
+
const onRowClick = useCallback(({ rowData }: {
|
|
175
|
+
rowData: Entity<M>
|
|
176
|
+
}) => {
|
|
177
|
+
if (inlineEditing)
|
|
178
|
+
return;
|
|
179
|
+
return onEntityClick && onEntityClick(rowData);
|
|
180
|
+
}, [onEntityClick, inlineEditing]);
|
|
181
|
+
|
|
182
|
+
useOutsideAlerter(ref,
|
|
183
|
+
() => {
|
|
184
|
+
if (selectedCell) {
|
|
185
|
+
unselect();
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
Boolean(selectedCell));
|
|
189
|
+
|
|
190
|
+
const select = useCallback((cell?: SelectedCellProps<M>) => {
|
|
191
|
+
setSelectedCell(cell);
|
|
192
|
+
}, []);
|
|
193
|
+
|
|
194
|
+
const unselect = useCallback(() => {
|
|
195
|
+
setSelectedCell(undefined);
|
|
196
|
+
}, []);
|
|
197
|
+
|
|
198
|
+
// on ESC key press
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
const escFunction = (event: any) => {
|
|
201
|
+
if (event.keyCode === 27) {
|
|
202
|
+
unselect();
|
|
203
|
+
}
|
|
169
204
|
};
|
|
205
|
+
document.addEventListener("keydown", escFunction, false);
|
|
206
|
+
return () => {
|
|
207
|
+
document.removeEventListener("keydown", escFunction, false);
|
|
208
|
+
};
|
|
209
|
+
}, [unselect]);
|
|
210
|
+
|
|
211
|
+
const onFilterUpdate = useCallback((updatedFilterValues?: FilterValues<any>) => {
|
|
212
|
+
setFilterValues?.({ ...updatedFilterValues, ...forceFilter } as FilterValues<any>);
|
|
213
|
+
}, [forceFilter]);
|
|
214
|
+
|
|
215
|
+
const contextValue = useMemo(() => ({
|
|
216
|
+
setPopupCell: setPopupCell as ((cell?: SelectedCellProps<M>) => void),
|
|
217
|
+
select,
|
|
218
|
+
onValueChange,
|
|
219
|
+
size: size ?? "m",
|
|
220
|
+
selectedCell
|
|
221
|
+
}), [setPopupCell, select, onValueChange, size, selectedCell]);
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
<SelectableTableContext.Provider
|
|
225
|
+
value={contextValue}>
|
|
226
|
+
<div className="h-full w-full flex flex-col bg-white dark:bg-surface-950"
|
|
227
|
+
ref={ref}>
|
|
228
|
+
|
|
229
|
+
<VirtualTable
|
|
230
|
+
data={data}
|
|
231
|
+
columns={columns}
|
|
232
|
+
cellRenderer={cellRenderer}
|
|
233
|
+
onRowClick={inlineEditing ? undefined : (onEntityClick ? onRowClick : undefined)}
|
|
234
|
+
onEndReached={loadNextPage}
|
|
235
|
+
onResetPagination={resetPagination}
|
|
236
|
+
error={dataLoadingError}
|
|
237
|
+
onColumnResize={onColumnResize}
|
|
238
|
+
rowHeight={getRowHeight(size)}
|
|
239
|
+
loading={dataLoading}
|
|
240
|
+
filter={filterValues}
|
|
241
|
+
onFilterUpdate={setFilterValues ? onFilterUpdate : undefined}
|
|
242
|
+
sortBy={sortBy}
|
|
243
|
+
onSortByUpdate={setSortBy as ((sortBy?: [string, "asc" | "desc"]) => void)}
|
|
244
|
+
hoverRow={hoverRow}
|
|
245
|
+
initialScroll={initialScroll}
|
|
246
|
+
onScroll={onScroll}
|
|
247
|
+
checkFilterCombination={checkFilterCombination}
|
|
248
|
+
createFilterField={filterable ? createFilterField : undefined}
|
|
249
|
+
rowClassName={useCallback((entity: Entity<M>) => {
|
|
250
|
+
return highlightedRow?.(entity) ? "bg-surface-100 bg-opacity-75 dark:bg-surface-800 dark:bg-opacity-75" : "";
|
|
251
|
+
}, [highlightedRow])}
|
|
252
|
+
className="flex-grow"
|
|
253
|
+
emptyComponent={emptyComponent}
|
|
254
|
+
endAdornment={endAdornment}
|
|
255
|
+
AddColumnComponent={AddColumnComponent}
|
|
256
|
+
/>
|
|
257
|
+
|
|
258
|
+
</div>
|
|
259
|
+
</SelectableTableContext.Provider>
|
|
260
|
+
);
|
|
170
261
|
|
|
171
|
-
|
|
172
|
-
setItemCount?.(pageSize);
|
|
173
|
-
}, [pageSize]);
|
|
174
|
-
|
|
175
|
-
const onRowClick = useCallback(({ rowData }: {
|
|
176
|
-
rowData: Entity<M>
|
|
177
|
-
}) => {
|
|
178
|
-
if (inlineEditing)
|
|
179
|
-
return;
|
|
180
|
-
return onEntityClick && onEntityClick(rowData);
|
|
181
|
-
}, [onEntityClick, inlineEditing]);
|
|
182
|
-
|
|
183
|
-
useOutsideAlerter(ref,
|
|
184
|
-
() => {
|
|
185
|
-
if (selectedCell) {
|
|
186
|
-
unselect();
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
Boolean(selectedCell));
|
|
190
|
-
|
|
191
|
-
// on ESC key press
|
|
192
|
-
useEffect(() => {
|
|
193
|
-
const escFunction = (event: any) => {
|
|
194
|
-
if (event.keyCode === 27) {
|
|
195
|
-
unselect();
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
document.addEventListener("keydown", escFunction, false);
|
|
199
|
-
return () => {
|
|
200
|
-
document.removeEventListener("keydown", escFunction, false);
|
|
201
|
-
};
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
const select = useCallback((cell?: SelectedCellProps<M>) => {
|
|
205
|
-
setSelectedCell(cell);
|
|
206
|
-
}, []);
|
|
207
|
-
|
|
208
|
-
const unselect = useCallback(() => {
|
|
209
|
-
setSelectedCell(undefined);
|
|
210
|
-
}, []);
|
|
211
|
-
|
|
212
|
-
const onFilterUpdate = useCallback((updatedFilterValues?: FilterValues<any>) => {
|
|
213
|
-
setFilterValues?.({ ...updatedFilterValues, ...forceFilter } as FilterValues<any>);
|
|
214
|
-
}, [forceFilter]);
|
|
215
|
-
|
|
216
|
-
return (
|
|
217
|
-
<SelectableTableContext.Provider
|
|
218
|
-
value={{
|
|
219
|
-
setPopupCell: setPopupCell as ((cell?: SelectedCellProps<M>) => void),
|
|
220
|
-
select,
|
|
221
|
-
onValueChange,
|
|
222
|
-
size: size ?? "m",
|
|
223
|
-
selectedCell,
|
|
224
|
-
}}
|
|
225
|
-
>
|
|
226
|
-
<div className="h-full w-full flex flex-col bg-white dark:bg-surface-950"
|
|
227
|
-
ref={ref}>
|
|
228
|
-
|
|
229
|
-
<VirtualTable
|
|
230
|
-
data={data}
|
|
231
|
-
columns={columns}
|
|
232
|
-
cellRenderer={cellRenderer}
|
|
233
|
-
onRowClick={inlineEditing ? undefined : (onEntityClick ? onRowClick : undefined)}
|
|
234
|
-
onEndReached={loadNextPage}
|
|
235
|
-
onResetPagination={resetPagination}
|
|
236
|
-
error={dataLoadingError}
|
|
237
|
-
onColumnResize={onColumnResize}
|
|
238
|
-
rowHeight={getRowHeight(size)}
|
|
239
|
-
loading={dataLoading}
|
|
240
|
-
filter={filterValues}
|
|
241
|
-
onFilterUpdate={setFilterValues ? onFilterUpdate : undefined}
|
|
242
|
-
sortBy={sortBy}
|
|
243
|
-
onSortByUpdate={setSortBy as ((sortBy?: [string, "asc" | "desc"]) => void)}
|
|
244
|
-
hoverRow={hoverRow}
|
|
245
|
-
initialScroll={initialScroll}
|
|
246
|
-
onScroll={onScroll}
|
|
247
|
-
checkFilterCombination={checkFilterCombination}
|
|
248
|
-
createFilterField={filterable ? createFilterField : undefined}
|
|
249
|
-
rowClassName={useCallback((entity: Entity<M>) => {
|
|
250
|
-
return highlightedRow?.(entity) ? "bg-surface-100 bg-opacity-75 dark:bg-surface-800 dark:bg-opacity-75" : "";
|
|
251
|
-
}, [highlightedRow])}
|
|
252
|
-
className="flex-grow"
|
|
253
|
-
emptyComponent={emptyComponent}
|
|
254
|
-
endAdornment={endAdornment}
|
|
255
|
-
AddColumnComponent={AddColumnComponent}
|
|
256
|
-
/>
|
|
257
|
-
|
|
258
|
-
</div>
|
|
259
|
-
</SelectableTableContext.Provider>
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
},
|
|
263
|
-
() => false,
|
|
264
|
-
// equal
|
|
265
|
-
);
|
|
262
|
+
};
|
|
266
263
|
|
|
267
264
|
function createFilterField({
|
|
268
265
|
id,
|
|
@@ -34,8 +34,12 @@ export function UnsavedChangesDialog({
|
|
|
34
34
|
|
|
35
35
|
</DialogContent>
|
|
36
36
|
<DialogActions>
|
|
37
|
-
<Button variant="text"
|
|
38
|
-
|
|
37
|
+
<Button variant="text"
|
|
38
|
+
color={"primary"}
|
|
39
|
+
onClick={handleCancel} autoFocus> Cancel </Button>
|
|
40
|
+
<Button
|
|
41
|
+
color={"primary"}
|
|
42
|
+
onClick={handleOk}> Ok </Button>
|
|
39
43
|
</DialogActions>
|
|
40
44
|
</Dialog>
|
|
41
45
|
);
|
|
@@ -115,7 +115,6 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
115
115
|
endAdornment,
|
|
116
116
|
AddColumnComponent,
|
|
117
117
|
initialScroll = 0,
|
|
118
|
-
debug
|
|
119
118
|
}: VirtualTableProps<T>) {
|
|
120
119
|
|
|
121
120
|
const sortByProperty: string | undefined = sortBy ? sortBy[0] : undefined;
|
|
@@ -131,7 +130,8 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
131
130
|
// Set initial scroll position
|
|
132
131
|
useEffect(() => {
|
|
133
132
|
if (tableRef.current && initialScroll) {
|
|
134
|
-
tableRef.current
|
|
133
|
+
const { scrollLeft } = tableRef.current;
|
|
134
|
+
tableRef.current.scrollTo(scrollLeft, initialScroll);
|
|
135
135
|
}
|
|
136
136
|
}, [tableRef, initialScroll]);
|
|
137
137
|
|
|
@@ -170,14 +170,14 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
170
170
|
});
|
|
171
171
|
|
|
172
172
|
const onColumnResizeInternal = useCallback((params: OnVirtualTableColumnResizeParams) => {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
setColumns(prevColumns =>
|
|
174
|
+
prevColumns.map((column) =>
|
|
175
|
+
column.key === params.column.key ? params.column : column
|
|
176
|
+
)
|
|
177
|
+
);
|
|
178
|
+
}, []);
|
|
177
179
|
|
|
178
180
|
const onColumnResizeEndInternal = useCallback((params: OnVirtualTableColumnResizeParams) => {
|
|
179
|
-
if (debug)
|
|
180
|
-
console.log("onColumnResizeEndInternal", params);
|
|
181
181
|
setColumns(columns.map((column) => column.key === params.column.key ? params.column : column));
|
|
182
182
|
if (onColumnResize) {
|
|
183
183
|
onColumnResize(params);
|
|
@@ -188,14 +188,10 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
188
188
|
const filterRef = useRef<VirtualTableFilterValues<any> | undefined>();
|
|
189
189
|
|
|
190
190
|
useEffect(() => {
|
|
191
|
-
if (debug)
|
|
192
|
-
console.log("Filter updated", filterInput);
|
|
193
191
|
filterRef.current = filterInput;
|
|
194
192
|
}, [filterInput]);
|
|
195
193
|
|
|
196
194
|
const scrollToTop = useCallback(() => {
|
|
197
|
-
if (debug)
|
|
198
|
-
console.log("scrollToTop");
|
|
199
195
|
endReachCallbackThreshold.current = 0;
|
|
200
196
|
if (tableRef.current) {
|
|
201
197
|
tableRef.current.scrollTo(tableRef.current?.scrollLeft, 0);
|
|
@@ -204,9 +200,6 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
204
200
|
|
|
205
201
|
const onColumnSort = useCallback((key: string) => {
|
|
206
202
|
|
|
207
|
-
if (debug)
|
|
208
|
-
console.log("onColumnSort", key);
|
|
209
|
-
|
|
210
203
|
const isDesc = sortByProperty === key && currentSort === "desc";
|
|
211
204
|
const isAsc = sortByProperty === key && currentSort === "asc";
|
|
212
205
|
const newSort = isAsc ? "desc" : (isDesc ? undefined : "asc");
|
|
@@ -234,12 +227,8 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
234
227
|
}, [checkFilterCombination, currentSort, onFilterUpdate, onResetPagination, onSortByUpdate, scrollToTop, sortByProperty]);
|
|
235
228
|
|
|
236
229
|
const maxScroll = Math.max((data?.length ?? 0) * rowHeight - bounds.height, 0);
|
|
237
|
-
if (debug)
|
|
238
|
-
console.log("maxScroll", maxScroll);
|
|
239
230
|
|
|
240
231
|
const onEndReachedInternal = useCallback((scrollOffset: number) => {
|
|
241
|
-
if (debug)
|
|
242
|
-
console.log("onEndReachedInternal", scrollOffset, endReachCallbackThreshold.current + endOffset);
|
|
243
232
|
if (onEndReached && (data?.length ?? 0) > 0 && scrollOffset > endReachCallbackThreshold.current + endOffset) {
|
|
244
233
|
endReachCallbackThreshold.current = scrollOffset;
|
|
245
234
|
onEndReached();
|
|
@@ -255,12 +244,6 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
255
244
|
scrollOffset: number,
|
|
256
245
|
scrollUpdateWasRequested: boolean;
|
|
257
246
|
}) => {
|
|
258
|
-
if (debug)
|
|
259
|
-
console.log("onScroll", {
|
|
260
|
-
scrollDirection,
|
|
261
|
-
scrollOffset,
|
|
262
|
-
scrollUpdateWasRequested
|
|
263
|
-
});
|
|
264
247
|
if (onScrollProp) {
|
|
265
248
|
debouncedScroll({
|
|
266
249
|
scrollDirection,
|
|
@@ -273,8 +256,6 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
273
256
|
}, [maxScroll, onEndReachedInternal]);
|
|
274
257
|
|
|
275
258
|
const onFilterUpdateInternal = useCallback((column: VirtualTableColumn, filterForProperty?: [VirtualTableWhereFilterOp, any]) => {
|
|
276
|
-
if (debug)
|
|
277
|
-
console.log("onFilterUpdateInternal", column, filterForProperty);
|
|
278
259
|
|
|
279
260
|
endReachCallbackThreshold.current = 0;
|
|
280
261
|
const filter = filterRef.current;
|
|
@@ -337,9 +318,6 @@ export const VirtualTable = React.memo<VirtualTableProps<any>>(
|
|
|
337
318
|
AddColumnComponent
|
|
338
319
|
};
|
|
339
320
|
|
|
340
|
-
if (debug)
|
|
341
|
-
console.log("VirtualTable render", virtualListController);
|
|
342
|
-
|
|
343
321
|
return (
|
|
344
322
|
<div
|
|
345
323
|
ref={measureRef}
|
|
@@ -5,20 +5,26 @@ import { addRecentId } from "../EntityCollectionView/utils";
|
|
|
5
5
|
import { navigateToEntity, resolveDefaultSelectedView } from "../../util";
|
|
6
6
|
|
|
7
7
|
export const editEntityAction: EntityAction = {
|
|
8
|
-
icon: <EditIcon/>,
|
|
8
|
+
icon: <EditIcon size={"small"}/>,
|
|
9
9
|
key: "edit",
|
|
10
10
|
name: "Edit",
|
|
11
11
|
collapsed: false,
|
|
12
|
+
isEnabled: ({ entity }) => Boolean(entity),
|
|
12
13
|
onClick({
|
|
13
14
|
entity,
|
|
14
15
|
collection,
|
|
15
16
|
fullPath,
|
|
17
|
+
fullIdPath,
|
|
16
18
|
context,
|
|
17
19
|
highlightEntity,
|
|
18
20
|
unhighlightEntity,
|
|
19
21
|
openEntityMode
|
|
20
22
|
}): Promise<void> {
|
|
21
23
|
|
|
24
|
+
if (!entity) {
|
|
25
|
+
throw new Error("INTERNAL: editEntityAction: Entity is undefined");
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
highlightEntity?.(entity);
|
|
23
29
|
|
|
24
30
|
context.analyticsController?.onAnalyticsEvent?.("entity_click", {
|
|
@@ -30,7 +36,8 @@ export const editEntityAction: EntityAction = {
|
|
|
30
36
|
addRecentId(collection.id, entity.id);
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
const path = collection?.collectionGroup ?
|
|
39
|
+
const path = collection?.collectionGroup ? entity.path : (fullPath ?? collection?.path ?? entity.path);
|
|
40
|
+
const newFullIdPath = collection?.collectionGroup ? collection.id : (fullIdPath ?? collection?.id ?? entity.path);
|
|
34
41
|
const defaultSelectedView = resolveDefaultSelectedView(
|
|
35
42
|
collection ? collection.defaultSelectedView : undefined,
|
|
36
43
|
{
|
|
@@ -43,7 +50,7 @@ export const editEntityAction: EntityAction = {
|
|
|
43
50
|
collection,
|
|
44
51
|
entityId: entity.id,
|
|
45
52
|
path,
|
|
46
|
-
fullIdPath:
|
|
53
|
+
fullIdPath: newFullIdPath,
|
|
47
54
|
sideEntityController: context.sideEntityController,
|
|
48
55
|
onClose: () => unhighlightEntity?.(entity),
|
|
49
56
|
navigation: context.navigation,
|
|
@@ -55,9 +62,10 @@ export const editEntityAction: EntityAction = {
|
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
export const copyEntityAction: EntityAction = {
|
|
58
|
-
icon: <FileCopyIcon/>,
|
|
65
|
+
icon: <FileCopyIcon size={"small"}/>,
|
|
59
66
|
name: "Copy",
|
|
60
67
|
key: "copy",
|
|
68
|
+
isEnabled: ({ entity }) => Boolean(entity),
|
|
61
69
|
onClick({
|
|
62
70
|
entity,
|
|
63
71
|
collection,
|
|
@@ -67,19 +75,23 @@ export const copyEntityAction: EntityAction = {
|
|
|
67
75
|
unhighlightEntity,
|
|
68
76
|
openEntityMode
|
|
69
77
|
}): Promise<void> {
|
|
78
|
+
if (!entity) {
|
|
79
|
+
throw new Error("INTERNAL: copyEntityAction: Entity is undefined");
|
|
80
|
+
}
|
|
70
81
|
highlightEntity?.(entity);
|
|
71
82
|
context.analyticsController?.onAnalyticsEvent?.("copy_entity_click", {
|
|
72
83
|
path: entity.path,
|
|
73
84
|
entityId: entity.id
|
|
74
85
|
});
|
|
75
86
|
|
|
76
|
-
const path = collection?.collectionGroup ? collection.
|
|
87
|
+
const path = collection?.collectionGroup ? collection.path : (fullPath ?? collection?.path ?? entity.path);
|
|
88
|
+
const fullIdPath = collection?.collectionGroup ? collection.id : (fullPath ?? collection?.id ?? entity.path);
|
|
77
89
|
navigateToEntity({
|
|
78
90
|
openEntityMode,
|
|
79
91
|
collection,
|
|
80
92
|
entityId: entity.id,
|
|
81
93
|
path,
|
|
82
|
-
fullIdPath
|
|
94
|
+
fullIdPath,
|
|
83
95
|
copy: true,
|
|
84
96
|
sideEntityController: context.sideEntityController,
|
|
85
97
|
onClose: () => unhighlightEntity?.(entity),
|
|
@@ -91,9 +103,10 @@ export const copyEntityAction: EntityAction = {
|
|
|
91
103
|
}
|
|
92
104
|
|
|
93
105
|
export const deleteEntityAction: EntityAction = {
|
|
94
|
-
icon: <DeleteIcon/>,
|
|
106
|
+
icon: <DeleteIcon size={"small"}/>,
|
|
95
107
|
name: "Delete",
|
|
96
108
|
key: "delete",
|
|
109
|
+
isEnabled: ({ entity }) => Boolean(entity),
|
|
97
110
|
onClick({
|
|
98
111
|
entity,
|
|
99
112
|
fullPath,
|
|
@@ -101,8 +114,11 @@ export const deleteEntityAction: EntityAction = {
|
|
|
101
114
|
context,
|
|
102
115
|
selectionController,
|
|
103
116
|
onCollectionChange,
|
|
104
|
-
|
|
117
|
+
navigateBack
|
|
105
118
|
}): Promise<void> {
|
|
119
|
+
if (!entity) {
|
|
120
|
+
throw new Error("INTERNAL: deleteEntityAction: Entity is undefined");
|
|
121
|
+
}
|
|
106
122
|
const { closeDialog } = context.dialogsController.open({
|
|
107
123
|
key: "delete_entity_dialog_" + entity.id,
|
|
108
124
|
Component: ({ open }) => {
|
|
@@ -120,7 +136,7 @@ export const deleteEntityAction: EntityAction = {
|
|
|
120
136
|
});
|
|
121
137
|
selectionController?.setSelectedEntities(selectionController.selectedEntities.filter(e => e.id !== entity.id));
|
|
122
138
|
onCollectionChange?.();
|
|
123
|
-
|
|
139
|
+
navigateBack?.();
|
|
124
140
|
}}
|
|
125
141
|
onClose={closeDialog}/>;
|
|
126
142
|
}
|
|
@@ -134,7 +134,7 @@ export function useDataSourceTableController<M extends Record<string, any> = any
|
|
|
134
134
|
} = parseFilterAndSort(window.location.search);
|
|
135
135
|
|
|
136
136
|
const [filterValues, setFilterValues] = React.useState<FilterValues<Extract<keyof M, string>> | undefined>(forceFilter ?? (updateUrl ? initialFilterUrl : undefined) ?? initialFilter ?? undefined);
|
|
137
|
-
const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>(initialSortUrl ?? initialSortInternal);
|
|
137
|
+
const [sortBy, setSortBy] = React.useState<[Extract<keyof M, string>, "asc" | "desc"] | undefined>((updateUrl ? initialSortUrl : undefined) ?? initialSortInternal);
|
|
138
138
|
|
|
139
139
|
useUpdateUrl(filterValues, sortBy, searchString, updateUrl);
|
|
140
140
|
|
|
@@ -334,7 +334,7 @@ function encodeFilterAndSort(filterValues?: FilterValues<string>, sortBy?: [stri
|
|
|
334
334
|
}
|
|
335
335
|
if (encodedValue !== undefined) {
|
|
336
336
|
entries[encodeURIComponent(`${key}_op`)] = encodeURIComponent(op);
|
|
337
|
-
entries[encodeURIComponent(`${key}_value`)] = encodeURIComponent(encodedValue.toString());
|
|
337
|
+
entries[encodeURIComponent(`${key}_value`)] = encodedValue ? encodeURIComponent(encodedValue.toString()) : "null";
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
});
|
package/src/components/index.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import React, { useCallback } from "react";
|
|
|
3
3
|
import { useLargeLayout, useNavigationController } from "../hooks";
|
|
4
4
|
|
|
5
5
|
import { Link, useNavigate } from "react-router-dom";
|
|
6
|
-
import { CMSAnalyticsEvent,
|
|
6
|
+
import { CMSAnalyticsEvent, NavigationEntry, NavigationResult } from "../types";
|
|
7
7
|
import { IconForView } from "../util";
|
|
8
8
|
import { cls, IconButton, Menu, MenuItem, MoreVertIcon, Tooltip, Typography } from "@firecms/ui";
|
|
9
9
|
import { useAnalyticsController } from "../hooks/useAnalyticsController";
|
|
@@ -45,7 +45,7 @@ export function DefaultDrawer({
|
|
|
45
45
|
const {
|
|
46
46
|
navigationEntries,
|
|
47
47
|
groups
|
|
48
|
-
}:
|
|
48
|
+
}: NavigationResult = navigation.topLevelNavigation;
|
|
49
49
|
|
|
50
50
|
const adminViews = navigationEntries.filter(e => e.type === "admin") ?? [];
|
|
51
51
|
const groupsWithoutAdmin = groups.filter(g => g !== "Admin");
|
|
@@ -63,7 +63,7 @@ export function DefaultDrawer({
|
|
|
63
63
|
</div>;
|
|
64
64
|
}, [drawerOpen]);
|
|
65
65
|
|
|
66
|
-
const onClick = (view:
|
|
66
|
+
const onClick = (view: NavigationEntry) => {
|
|
67
67
|
const eventName: CMSAnalyticsEvent = view.type === "collection"
|
|
68
68
|
? "drawer_navigate_to_collection"
|
|
69
69
|
: (view.type === "view" ? "drawer_navigate_to_view" : "unmapped_event");
|
|
@@ -90,9 +90,9 @@ export function DefaultDrawer({
|
|
|
90
90
|
{buildGroupHeader(group)}
|
|
91
91
|
{Object.values(navigationEntries)
|
|
92
92
|
.filter(e => e.group === group)
|
|
93
|
-
.map((view
|
|
93
|
+
.map((view) =>
|
|
94
94
|
<DrawerNavigationItem
|
|
95
|
-
key={
|
|
95
|
+
key={view.id}
|
|
96
96
|
icon={<IconForView collectionOrView={view.collection ?? view.view}
|
|
97
97
|
size={"small"}/>}
|
|
98
98
|
tooltipsOpen={tooltipsOpen}
|
|
@@ -128,13 +128,13 @@ export function DefaultDrawer({
|
|
|
128
128
|
</div>}
|
|
129
129
|
</IconButton>}
|
|
130
130
|
>
|
|
131
|
-
{adminViews.map((entry
|
|
131
|
+
{adminViews.map((entry) =>
|
|
132
132
|
<MenuItem
|
|
133
133
|
onClick={(event) => {
|
|
134
134
|
event.preventDefault();
|
|
135
|
-
navigate(entry.
|
|
135
|
+
navigate(entry.url); // Consistent use of entry.url for navigation
|
|
136
136
|
}}
|
|
137
|
-
key={
|
|
137
|
+
key={entry.id}>
|
|
138
138
|
{<IconForView collectionOrView={entry.view}/>}
|
|
139
139
|
{entry.name}
|
|
140
140
|
</MenuItem>)}
|
|
@@ -38,7 +38,7 @@ export function DrawerNavigationItem({
|
|
|
38
38
|
"flex flex-row items-center mr-8",
|
|
39
39
|
// "transition-all ease-in-out delay-100 duration-300",
|
|
40
40
|
// drawerOpen ? "w-full" : "w-18",
|
|
41
|
-
drawerOpen ? "pl-4 h-
|
|
41
|
+
drawerOpen ? "pl-4 h-10" : "pl-4 h-9",
|
|
42
42
|
"font-semibold text-xs",
|
|
43
43
|
isActive ? "bg-surface-accent-200 bg-opacity-60 dark:bg-surface-800 dark:bg-opacity-50" : ""
|
|
44
44
|
)}
|