@linzjs/step-ag-grid 28.5.1 → 29.0.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/index.css +11 -7
- package/dist/src/components/Grid.d.ts +5 -1
- package/dist/src/contexts/GridContext.d.ts +3 -4
- package/dist/src/contexts/GridPopoverContext.d.ts +1 -0
- package/dist/src/contexts/GridUpdatingContext.d.ts +1 -0
- package/dist/src/lui/reactUtils.d.ts +4 -0
- package/dist/step-ag-grid.cjs +272 -250
- package/dist/step-ag-grid.cjs.map +1 -1
- package/dist/step-ag-grid.esm.js +273 -251
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +21 -22
- package/src/components/Grid.tsx +114 -112
- package/src/components/GridCell.tsx +6 -2
- package/src/components/GridPopoverHook.tsx +25 -20
- package/src/components/gridFilter/useGridFilter.ts +3 -3
- package/src/components/gridForm/GridFormTextInput.tsx +6 -2
- package/src/components/gridHook/useGridContextMenu.tsx +3 -3
- package/src/contexts/GridContext.tsx +11 -14
- package/src/contexts/GridContextProvider.tsx +164 -137
- package/src/contexts/GridPopoverContext.tsx +2 -0
- package/src/contexts/GridPopoverContextProvider.tsx +9 -5
- package/src/contexts/GridUpdatingContext.tsx +5 -0
- package/src/contexts/GridUpdatingContextProvider.tsx +35 -28
- package/src/lui/reactUtils.tsx +24 -0
- package/src/react-menu3/components/MenuList.tsx +3 -0
- package/src/stories/grid/GridFilterButtons.stories.tsx +1 -1
- package/src/stories/grid/GridNonEditableRow.stories.tsx +1 -1
- package/src/stories/grid/GridPinnedRow.stories.tsx +1 -1
- package/src/stories/grid/GridPopoutContextMenu.stories.tsx +3 -3
- package/src/stories/grid/GridPopoutEditGenericTextArea.stories.tsx +3 -3
- package/src/stories/grid/GridPopoverEditDropDown.stories.tsx +8 -4
- package/src/stories/grid/GridPopoverEditMultiSelect.stories.tsx +1 -0
- package/src/stories/grid/GridReadOnly.stories.tsx +1 -1
- package/src/stories/grid/GridViewList.stories.tsx +1 -1
- package/src/stories/grid/gridFormInteraction/GridFormDropDownInteraction.stories.tsx +5 -3
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectGridInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormPopoverMenuInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormTextAreaInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormInteraction/GridFormTextInputInteraction.stories.tsx +3 -2
- package/src/stories/grid/gridFormStatic/GridFormDropDown.stories.tsx +2 -2
- package/src/stories/grid/interactions/GridKeyboardInteractions.stories.tsx +2 -2
package/dist/step-ag-grid.cjs
CHANGED
|
@@ -449,9 +449,6 @@ const GridContext = React.createContext({
|
|
|
449
449
|
prePopupOps: () => {
|
|
450
450
|
console.error('no context provider for prePopupOps');
|
|
451
451
|
},
|
|
452
|
-
postPopupOps: () => {
|
|
453
|
-
console.error('no context provider for prePopupOps');
|
|
454
|
-
},
|
|
455
452
|
externallySelectedItemsAreInSync: false,
|
|
456
453
|
setApis: () => {
|
|
457
454
|
console.error('no context provider for setApis');
|
|
@@ -523,15 +520,12 @@ const GridContext = React.createContext({
|
|
|
523
520
|
console.error('no context provider for editingCells');
|
|
524
521
|
return false;
|
|
525
522
|
},
|
|
526
|
-
cancelEdit: () => {
|
|
527
|
-
console.error('no context provider for cancelEdit');
|
|
528
|
-
},
|
|
529
523
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
530
524
|
startCellEditing: async () => {
|
|
531
525
|
console.error('no context provider for startCellEditing');
|
|
532
526
|
},
|
|
533
|
-
|
|
534
|
-
console.error('no context provider for
|
|
527
|
+
resetFocusedCellAfterCellEditing: () => {
|
|
528
|
+
console.error('no context provider for resetFocusedCellAfterCellEditing');
|
|
535
529
|
},
|
|
536
530
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
537
531
|
updatingCells: async () => {
|
|
@@ -565,8 +559,11 @@ const GridContext = React.createContext({
|
|
|
565
559
|
downloadCsv: () => {
|
|
566
560
|
console.error('no context provider for downloadCsv');
|
|
567
561
|
},
|
|
568
|
-
|
|
569
|
-
console.error('no context provider for
|
|
562
|
+
onBulkEditingComplete: () => {
|
|
563
|
+
console.error('no context provider for onBulkEditingComplete');
|
|
564
|
+
},
|
|
565
|
+
setOnBulkEditingComplete: () => {
|
|
566
|
+
console.error('no context provider for setOnBulkEditingComplete');
|
|
570
567
|
},
|
|
571
568
|
showNoRowsOverlay: () => {
|
|
572
569
|
console.error('no context provider for showLoadingOverlay');
|
|
@@ -575,6 +572,10 @@ const GridContext = React.createContext({
|
|
|
575
572
|
const useGridContext = () => React.useContext(GridContext);
|
|
576
573
|
|
|
577
574
|
const GridUpdatingContext = React.createContext({
|
|
575
|
+
anyUpdating: () => {
|
|
576
|
+
console.error('Missing GridUpdatingContext');
|
|
577
|
+
return false;
|
|
578
|
+
},
|
|
578
579
|
checkUpdating: () => {
|
|
579
580
|
console.error('Missing GridUpdatingContext');
|
|
580
581
|
return false;
|
|
@@ -1796,6 +1797,9 @@ const MenuList = ({ ariaLabel, menuClassName, menuStyle, arrowClassName, arrowSt
|
|
|
1796
1797
|
return;
|
|
1797
1798
|
}
|
|
1798
1799
|
const callback = lodashEs.debounce(() => {
|
|
1800
|
+
if (!menuRef.current) {
|
|
1801
|
+
return;
|
|
1802
|
+
}
|
|
1799
1803
|
const { width, height } = menuRef.current.ownerDocument.body.getBoundingClientRect();
|
|
1800
1804
|
if (width === 0 || height === 0)
|
|
1801
1805
|
return;
|
|
@@ -2541,7 +2545,7 @@ const SubMenuFr = ({ 'aria-label': ariaLabel, className, disabled, direction, la
|
|
|
2541
2545
|
const SubMenu = withHovering('SubMenu', SubMenuFr);
|
|
2542
2546
|
|
|
2543
2547
|
const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, }) => {
|
|
2544
|
-
const { redrawRows, prePopupOps,
|
|
2548
|
+
const { redrawRows, prePopupOps, resetFocusedCellAfterCellEditing, getSelectedRows } = React.useContext(GridContext);
|
|
2545
2549
|
const [isOpen, setOpen] = React.useState(false);
|
|
2546
2550
|
const [anchorPoint, setAnchorPoint] = React.useState({ x: 0, y: 0 });
|
|
2547
2551
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
@@ -2558,8 +2562,8 @@ const useGridContextMenu = ({ contextMenuSelectRow, contextMenu: ContextMenu, })
|
|
|
2558
2562
|
const closeMenu = React.useCallback(() => {
|
|
2559
2563
|
setOpen(false);
|
|
2560
2564
|
redrawRows();
|
|
2561
|
-
|
|
2562
|
-
}, [
|
|
2565
|
+
resetFocusedCellAfterCellEditing();
|
|
2566
|
+
}, [resetFocusedCellAfterCellEditing, redrawRows]);
|
|
2563
2567
|
const cellContextMenu = React.useCallback((event) => {
|
|
2564
2568
|
if (contextMenuSelectRow && !event.node.isSelected()) {
|
|
2565
2569
|
event.node.setSelected(true, true);
|
|
@@ -2755,36 +2759,11 @@ const usePostSortRowsHook = ({ setStaleGrid }) => {
|
|
|
2755
2759
|
};
|
|
2756
2760
|
|
|
2757
2761
|
agGridCommunity.ModuleRegistry.registerModules([agGridCommunity.AllCommunityModule]);
|
|
2758
|
-
let timeOfLastSingleClick = 0;
|
|
2759
|
-
let lastClickColId;
|
|
2760
|
-
let lastClickRowIndex;
|
|
2761
|
-
const resetClickDebounce = () => {
|
|
2762
|
-
timeOfLastSingleClick = 0;
|
|
2763
|
-
lastClickColId = '';
|
|
2764
|
-
lastClickRowIndex = -1;
|
|
2765
|
-
};
|
|
2766
|
-
/**
|
|
2767
|
-
* If click is more than 200ms since last click return true.
|
|
2768
|
-
*/
|
|
2769
|
-
const clickDebounceSkipClick = (colId, rowIndex) => {
|
|
2770
|
-
const doubleClickMs = 200;
|
|
2771
|
-
if (Date.now() - timeOfLastSingleClick < doubleClickMs &&
|
|
2772
|
-
lastClickColId === colId &&
|
|
2773
|
-
lastClickRowIndex === rowIndex) {
|
|
2774
|
-
// Skipping double click due to single click edit
|
|
2775
|
-
return true;
|
|
2776
|
-
}
|
|
2777
|
-
timeOfLastSingleClick = Date.now();
|
|
2778
|
-
lastClickColId = colId;
|
|
2779
|
-
lastClickRowIndex = rowIndex;
|
|
2780
|
-
return false;
|
|
2781
|
-
};
|
|
2782
2762
|
/**
|
|
2783
2763
|
* Wrapper for AgGrid to add commonly used functionality.
|
|
2784
2764
|
*/
|
|
2785
2765
|
const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection = 'multiple', suppressColumnVirtualization = true, theme = 'ag-theme-step-default', sizeColumns = 'auto', selectColumnPinned = 'left', contextMenuSelectRow = false, singleClickEdit = false, rowData, rowHeight = theme === 'ag-theme-step-default' ? 40 : theme === 'ag-theme-step-compact' ? 36 : 40, selectable, ...params }) => {
|
|
2786
|
-
const { gridReady, gridRenderState, setApis, ensureRowVisible, getFirstRowId, selectRowsById, focusByRowById, ensureSelectedRowIsVisible, autoSizeColumns, sizeColumnsToFit, externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync, isExternalFilterPresent, doesExternalFilterPass,
|
|
2787
|
-
const { startCellEditing } = useGridContext();
|
|
2766
|
+
const { gridReady, gridRenderState, setApis, ensureRowVisible, getFirstRowId, selectRowsById, focusByRowById, ensureSelectedRowIsVisible, autoSizeColumns, sizeColumnsToFit, externallySelectedItemsAreInSync, setExternallySelectedItemsAreInSync, isExternalFilterPresent, doesExternalFilterPass, setOnBulkEditingComplete, getColDef, showNoRowsOverlay, prePopupOps, startCellEditing, } = useGridContext();
|
|
2788
2767
|
const { updatedDep, updatingCols } = React.useContext(GridUpdatingContext);
|
|
2789
2768
|
const gridDivRef = React.useRef(null);
|
|
2790
2769
|
const lastSelectedIds = React.useRef([]);
|
|
@@ -3003,26 +2982,10 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
|
|
|
3003
2982
|
const onModelUpdated = React.useCallback((event) => {
|
|
3004
2983
|
event.api.showNoRowsOverlay();
|
|
3005
2984
|
}, []);
|
|
3006
|
-
/**
|
|
3007
|
-
* Force-refresh all selected rows to re-run class function, to update selection highlighting
|
|
3008
|
-
*/
|
|
3009
|
-
const refreshSelectedRows = React.useCallback((_event) => {
|
|
3010
|
-
// MATT Disabled I don't believe these are needed anymore
|
|
3011
|
-
// I've left them here just in case they are
|
|
3012
|
-
/*event.api.refreshCells({
|
|
3013
|
-
force: true,
|
|
3014
|
-
rowNodes: event.api.getSelectedNodes(),
|
|
3015
|
-
});*/
|
|
3016
|
-
}, []);
|
|
3017
2985
|
/**
|
|
3018
2986
|
* Handle double click edit
|
|
3019
2987
|
*/
|
|
3020
2988
|
const onCellDoubleClick = React.useCallback((event) => {
|
|
3021
|
-
if (clickDebounceSkipClick(event.colDef.colId, event.rowIndex)) {
|
|
3022
|
-
// the next click will be a single click, we want it to pass
|
|
3023
|
-
resetClickDebounce();
|
|
3024
|
-
return;
|
|
3025
|
-
}
|
|
3026
2989
|
const editable = fnOrVar(event.colDef?.editable, event);
|
|
3027
2990
|
if (editable && !invokeEditAction(event)) {
|
|
3028
2991
|
void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
|
|
@@ -3034,9 +2997,6 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
|
|
|
3034
2997
|
const onCellClicked = React.useCallback((event) => {
|
|
3035
2998
|
const editable = fnOrVar(event.colDef?.editable, event);
|
|
3036
2999
|
if ((editable && event.colDef.singleClickEdit) ?? singleClickEdit) {
|
|
3037
|
-
if (clickDebounceSkipClick(event.colDef.colId, event.rowIndex)) {
|
|
3038
|
-
return;
|
|
3039
|
-
}
|
|
3040
3000
|
void startCellEditing({ rowId: event.data.id, colId: event.column.getColId() });
|
|
3041
3001
|
}
|
|
3042
3002
|
}, [singleClickEdit, startCellEditing]);
|
|
@@ -3132,11 +3092,10 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
|
|
|
3132
3092
|
React.useEffect(() => {
|
|
3133
3093
|
const newLoading = !rowData || params.loading === true;
|
|
3134
3094
|
if (newLoading && !prevLoading.current) {
|
|
3135
|
-
stopEditing();
|
|
3136
3095
|
showNoRowsOverlay();
|
|
3137
3096
|
}
|
|
3138
3097
|
prevLoading.current = newLoading;
|
|
3139
|
-
}, [params.loading, rowData, showNoRowsOverlay
|
|
3098
|
+
}, [params.loading, rowData, showNoRowsOverlay]);
|
|
3140
3099
|
/**
|
|
3141
3100
|
* Resize columns to fit if required on window/container resize
|
|
3142
3101
|
*/
|
|
@@ -3198,6 +3157,23 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
|
|
|
3198
3157
|
});
|
|
3199
3158
|
}
|
|
3200
3159
|
}, [clearHighlightRowClasses]);
|
|
3160
|
+
const onCellFocused = React.useCallback((event) => {
|
|
3161
|
+
if (!params.onCellFocused || event.rowIndex == null) {
|
|
3162
|
+
return;
|
|
3163
|
+
}
|
|
3164
|
+
const api = event.api;
|
|
3165
|
+
const rowNode = api.getDisplayedRowAtIndex(event.rowIndex);
|
|
3166
|
+
const data = rowNode?.data;
|
|
3167
|
+
const column = event.column;
|
|
3168
|
+
if (!data || !column || typeof column === 'string') {
|
|
3169
|
+
return;
|
|
3170
|
+
}
|
|
3171
|
+
const colDef = column.getColDef();
|
|
3172
|
+
if (!colDef || typeof colDef === 'string') {
|
|
3173
|
+
return;
|
|
3174
|
+
}
|
|
3175
|
+
params.onCellFocused({ colDef, data });
|
|
3176
|
+
}, [params]);
|
|
3201
3177
|
const onRowDragEnd = React.useCallback((event) => {
|
|
3202
3178
|
clearHighlightRowClasses();
|
|
3203
3179
|
gridElementRef.current = undefined;
|
|
@@ -3222,57 +3198,76 @@ const Grid = ({ 'data-testid': dataTestId, defaultPostSort = true, rowSelection
|
|
|
3222
3198
|
}
|
|
3223
3199
|
}, [params.setExternalSelectedItems, selectable]);
|
|
3224
3200
|
// This is setting a ref in the GridContext so won't be triggering an update loop
|
|
3225
|
-
|
|
3226
|
-
const
|
|
3227
|
-
const
|
|
3201
|
+
setOnBulkEditingComplete(params.onBulkEditingComplete);
|
|
3202
|
+
const getRowId = React.useCallback((params) => `${params.data.id}`, []);
|
|
3203
|
+
const defaultColDef = React.useMemo(() => ({
|
|
3204
|
+
minWidth: 48,
|
|
3205
|
+
...lodashEs.omit(params.defaultColDef, ['editable', 'field', 'colId', 'tooltipField']),
|
|
3206
|
+
}), [params.defaultColDef]);
|
|
3207
|
+
const noRowsOverlayComponent = React.useCallback((event) => {
|
|
3208
|
+
const headerRowCount = columnDefs.some((c) => c.children) ? 2 : 1;
|
|
3209
|
+
let rowCount = 0;
|
|
3210
|
+
event.api.forEachNode(() => rowCount++);
|
|
3211
|
+
return (jsxRuntime.jsx(GridNoRowsOverlay, { loading: !rowData || params.loading === true, rowCount: rowCount, headerRowHeight: headerRowCount * rowHeight, filteredRowCount: event.api.getDisplayedRowCount(), noRowsOverlayText: params.noRowsOverlayText, noRowsMatchingOverlayText: params.noRowsMatchingOverlayText }));
|
|
3212
|
+
}, [columnDefs, params.loading, params.noRowsMatchingOverlayText, params.noRowsOverlayText, rowData, rowHeight]);
|
|
3213
|
+
const selectionColumnDef = React.useMemo(() => {
|
|
3214
|
+
const selectWidth = params.hideSelectColumn ? 0 : selectable && params.onRowDragEnd ? 76 : 48;
|
|
3215
|
+
return {
|
|
3216
|
+
suppressNavigable: params.hideSelectColumn,
|
|
3217
|
+
rowDrag: !!params.onRowDragEnd,
|
|
3218
|
+
minWidth: selectWidth,
|
|
3219
|
+
maxWidth: selectWidth,
|
|
3220
|
+
pinned: selectColumnPinned,
|
|
3221
|
+
headerComponentParams: {
|
|
3222
|
+
exportable: false,
|
|
3223
|
+
},
|
|
3224
|
+
headerClass: clsx('ag-header-hide-default-select', params.onRowDragEnd && 'ag-header-select-draggable'),
|
|
3225
|
+
headerComponent: rowSelection == 'multiple' ? GridHeaderSelect : undefined,
|
|
3226
|
+
suppressHeaderKeyboardEvent: (e) => {
|
|
3227
|
+
if (!selectable)
|
|
3228
|
+
return false;
|
|
3229
|
+
if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
|
|
3230
|
+
if (lodashEs.isEmpty(e.api.getSelectedRows())) {
|
|
3231
|
+
e.api.selectAll('filtered');
|
|
3232
|
+
}
|
|
3233
|
+
else {
|
|
3234
|
+
e.api.deselectAll();
|
|
3235
|
+
}
|
|
3236
|
+
return true;
|
|
3237
|
+
}
|
|
3238
|
+
return false;
|
|
3239
|
+
},
|
|
3240
|
+
onCellClicked: params.enableSelectionWithoutKeys || params.enableClickSelection
|
|
3241
|
+
? undefined
|
|
3242
|
+
: clickInputWhenContainingCellClicked,
|
|
3243
|
+
};
|
|
3244
|
+
}, [
|
|
3245
|
+
params.enableClickSelection,
|
|
3246
|
+
params.enableSelectionWithoutKeys,
|
|
3247
|
+
params.hideSelectColumn,
|
|
3248
|
+
params.onRowDragEnd,
|
|
3249
|
+
rowSelection,
|
|
3250
|
+
selectColumnPinned,
|
|
3251
|
+
selectable,
|
|
3252
|
+
]);
|
|
3228
3253
|
return (jsxRuntime.jsxs("div", { "data-testid": dataTestId, className: clsx('Grid-container', theme, 'theme-specific', staleGrid && 'Grid-sortIsStale', gridReady && rowData && autoSized && 'Grid-ready'), children: [gridContextMenu.component, jsxRuntime.jsx("div", { style: { flex: 1 }, ref: gridDivRef, children: jsxRuntime.jsx(agGridReact.AgGridReact, { theme: 'legacy', rowSelection: selectable
|
|
3229
3254
|
? {
|
|
3230
3255
|
enableSelectionWithoutKeys: params.enableSelectionWithoutKeys ?? false,
|
|
3231
3256
|
enableClickSelection: params.enableClickSelection ?? false,
|
|
3232
3257
|
mode: rowSelection == 'single' ? 'singleRow' : 'multiRow',
|
|
3233
3258
|
}
|
|
3234
|
-
: undefined, rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId:
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
// filter is exact matches exactly groups separated by commas
|
|
3240
|
-
return filterStr.split(',').map((str) => str.trim());
|
|
3241
|
-
}, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, postSortRows: params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, alwaysShowVerticalScroll: params.alwaysShowVerticalScroll, isExternalFilterPresent: isExternalFilterPresent, doesExternalFilterPass: doesExternalFilterPass, maintainColumnOrder: true, preventDefaultOnContextMenu: true, onCellContextMenu: gridContextMenu.cellContextMenu, rowDragText: params.rowDragText, onRowDragCancel: clearHighlightRowClasses, onRowDragMove: onRowDragMove, onRowDragEnd: onRowDragEnd, suppressCellFocus: params.suppressCellFocus, pinnedTopRowData: params.pinnedTopRowData, pinnedBottomRowData: params.pinnedBottomRowData, selectionColumnDef: {
|
|
3242
|
-
suppressNavigable: params.hideSelectColumn,
|
|
3243
|
-
rowDrag: !!params.onRowDragEnd,
|
|
3244
|
-
minWidth: selectWidth,
|
|
3245
|
-
maxWidth: selectWidth,
|
|
3246
|
-
pinned: selectColumnPinned,
|
|
3247
|
-
headerComponentParams: {
|
|
3248
|
-
exportable: false,
|
|
3249
|
-
},
|
|
3250
|
-
headerClass: clsx('ag-header-hide-default-select', params.onRowDragEnd && 'ag-header-select-draggable'),
|
|
3251
|
-
headerComponent: rowSelection == 'multiple' ? GridHeaderSelect : undefined,
|
|
3252
|
-
suppressHeaderKeyboardEvent: (e) => {
|
|
3253
|
-
if (!selectable)
|
|
3254
|
-
return false;
|
|
3255
|
-
if ((e.event.key === 'Enter' || e.event.key === ' ') && !e.event.repeat) {
|
|
3256
|
-
if (lodashEs.isEmpty(e.api.getSelectedRows())) {
|
|
3257
|
-
e.api.selectAll('filtered');
|
|
3258
|
-
}
|
|
3259
|
-
else {
|
|
3260
|
-
e.api.deselectAll();
|
|
3261
|
-
}
|
|
3262
|
-
return true;
|
|
3263
|
-
}
|
|
3264
|
-
return false;
|
|
3265
|
-
},
|
|
3266
|
-
onCellClicked: params.enableSelectionWithoutKeys || params.enableClickSelection
|
|
3267
|
-
? undefined
|
|
3268
|
-
: clickInputWhenContainingCellClicked,
|
|
3269
|
-
} }) })] }));
|
|
3259
|
+
: undefined, rowHeight: rowHeight, animateRows: params.animateRows ?? false, rowClassRules: params.rowClassRules, getRowId: getRowId, onGridSizeChanged: onGridSizeChanged, suppressColumnVirtualisation: suppressColumnVirtualization, suppressClickEdit: true, onColumnVisible: setInitialContentSize, onRowDataUpdated: onRowDataChanged, onCellFocused: onCellFocused, onCellKeyDown: onCellKeyPress, onCellClicked: onCellClicked, onCellDoubleClicked: onCellDoubleClick, domLayout: params.domLayout, onColumnResized: onColumnResized, defaultColDef: defaultColDef, columnDefs: columnDefsAdjusted, selectionColumnDef: selectionColumnDef, rowData: rowData, postSortRows: params.onRowDragEnd || !defaultPostSort ? undefined : postSortRows, onModelUpdated: onModelUpdated, onGridReady: onGridReady, onSortChanged: ensureSelectedRowIsVisible, quickFilterParser: quickFilterParser, onSelectionChanged: synchroniseExternalStateToGridSelection, onColumnMoved: params.onColumnMoved, noRowsOverlayComponent: noRowsOverlayComponent, alwaysShowVerticalScroll: params.alwaysShowVerticalScroll, isExternalFilterPresent: isExternalFilterPresent, doesExternalFilterPass: doesExternalFilterPass, maintainColumnOrder: true, preventDefaultOnContextMenu: true, onCellContextMenu: gridContextMenu.cellContextMenu, rowDragText: params.rowDragText, onRowDragCancel: clearHighlightRowClasses, onRowDragMove: onRowDragMove, onRowDragEnd: onRowDragEnd, suppressCellFocus: params.suppressCellFocus, pinnedTopRowData: params.pinnedTopRowData, pinnedBottomRowData: params.pinnedBottomRowData }) })] }));
|
|
3260
|
+
};
|
|
3261
|
+
const quickFilterParser = (filterStr) => {
|
|
3262
|
+
// filter is exact matches exactly groups separated by commas
|
|
3263
|
+
return filterStr.split(',').map((str) => str.trim());
|
|
3270
3264
|
};
|
|
3271
3265
|
|
|
3272
3266
|
const GridPopoverContext = React.createContext({
|
|
3273
3267
|
anchorRef: { current: null },
|
|
3274
3268
|
saving: false,
|
|
3275
3269
|
setSaving: () => { },
|
|
3270
|
+
stopEditing: () => { },
|
|
3276
3271
|
colId: '',
|
|
3277
3272
|
field: '',
|
|
3278
3273
|
value: null,
|
|
@@ -3290,7 +3285,7 @@ const GridPopoverContextProvider = (props2) => {
|
|
|
3290
3285
|
const anchorRef = React.useRef(props.eGridCell);
|
|
3291
3286
|
const hasSaved = React.useRef(false);
|
|
3292
3287
|
const [saving, setSaving] = React.useState(false);
|
|
3293
|
-
const { colDef } = props;
|
|
3288
|
+
const { colDef, stopEditing, formatValue, data, value } = props;
|
|
3294
3289
|
const { cellEditorParams } = colDef;
|
|
3295
3290
|
const multiEdit = cellEditorParams?.multiEdit ?? false;
|
|
3296
3291
|
// Then item that is clicked on will always be first in the list
|
|
@@ -3298,8 +3293,10 @@ const GridPopoverContextProvider = (props2) => {
|
|
|
3298
3293
|
const field = props.colDef?.field ?? '';
|
|
3299
3294
|
const colId = props.colDef?.colId ?? field ?? '';
|
|
3300
3295
|
const updateValue = React.useCallback(async (saveFn, tabDirection) => {
|
|
3301
|
-
if (hasSaved.current)
|
|
3296
|
+
if (hasSaved.current) {
|
|
3297
|
+
// already called save so ignore
|
|
3302
3298
|
return true;
|
|
3299
|
+
}
|
|
3303
3300
|
hasSaved.current = true;
|
|
3304
3301
|
return saving ? false : await updatingCells({ selectedRows, field }, saveFn, setSaving, tabDirection);
|
|
3305
3302
|
}, [field, saving, selectedRows, updatingCells]);
|
|
@@ -3310,10 +3307,11 @@ const GridPopoverContextProvider = (props2) => {
|
|
|
3310
3307
|
selectedRows,
|
|
3311
3308
|
colId,
|
|
3312
3309
|
field,
|
|
3313
|
-
data
|
|
3314
|
-
value
|
|
3310
|
+
data,
|
|
3311
|
+
value,
|
|
3315
3312
|
updateValue,
|
|
3316
|
-
formatValue
|
|
3313
|
+
formatValue,
|
|
3314
|
+
stopEditing,
|
|
3317
3315
|
}, children: children }));
|
|
3318
3316
|
};
|
|
3319
3317
|
|
|
@@ -3379,16 +3377,18 @@ const defaultValueFormatter = ({ value }) => {
|
|
|
3379
3377
|
? String(value)
|
|
3380
3378
|
: JSON.stringify(value);
|
|
3381
3379
|
};
|
|
3380
|
+
// ag-grid doesn't understand the custom editor, when it stops editing it thinks
|
|
3381
|
+
// that _it_ was editing and overwrites the user updated data
|
|
3382
|
+
// _but_, it only does this if the initial value of the cell was null!?
|
|
3383
|
+
const blockValueSetter = () => true;
|
|
3382
3384
|
/*
|
|
3383
3385
|
* All cells should use this.
|
|
3384
3386
|
*/
|
|
3385
3387
|
const GridCell = (props, custom) => {
|
|
3386
|
-
// props.field = ;
|
|
3387
3388
|
// Generate a default filter value getter which uses the formatted value plus
|
|
3388
3389
|
// the editable value if it's a string and different from the formatted value.
|
|
3389
3390
|
// This is so that e.g. bearings can be searched for by DMS or raw number.
|
|
3390
3391
|
const valueFormatter = props.valueFormatter ?? defaultValueFormatter;
|
|
3391
|
-
// FIXME
|
|
3392
3392
|
const filterValueGetter = props.filterValueGetter ?? generateFilterGetter(valueFormatter);
|
|
3393
3393
|
const exportable = props.exportable;
|
|
3394
3394
|
// Can't leave this here ag-grid will complain
|
|
@@ -3399,6 +3399,7 @@ const GridCell = (props, custom) => {
|
|
|
3399
3399
|
headerTooltip: props.headerName,
|
|
3400
3400
|
sortable: true,
|
|
3401
3401
|
resizable: true,
|
|
3402
|
+
valueSetter: custom?.editor ? blockValueSetter : undefined,
|
|
3402
3403
|
editable: props.editable ?? false,
|
|
3403
3404
|
...(custom?.editor && {
|
|
3404
3405
|
cellClassRules: GridCellMultiSelectClassRules,
|
|
@@ -3463,7 +3464,7 @@ const GridCellMultiEditor = (props, cellEditorSelector) => GridCell({
|
|
|
3463
3464
|
});
|
|
3464
3465
|
|
|
3465
3466
|
const useGridFilter = (filter) => {
|
|
3466
|
-
const { addExternalFilter, removeExternalFilter } =
|
|
3467
|
+
const { addExternalFilter, removeExternalFilter } = useGridContext();
|
|
3467
3468
|
React.useEffect(() => {
|
|
3468
3469
|
const thisFilter = filter;
|
|
3469
3470
|
thisFilter && addExternalFilter(thisFilter);
|
|
@@ -3938,8 +3939,8 @@ const textMatch = (text, filter) => {
|
|
|
3938
3939
|
};
|
|
3939
3940
|
|
|
3940
3941
|
const useGridPopoverHook = (props) => {
|
|
3941
|
-
const {
|
|
3942
|
-
const { anchorRef, saving, updateValue } = useGridPopoverContext();
|
|
3942
|
+
const { onBulkEditingComplete } = useGridContext();
|
|
3943
|
+
const { anchorRef, saving, updateValue, stopEditing } = useGridPopoverContext();
|
|
3943
3944
|
const saveButtonRef = React.useRef(null);
|
|
3944
3945
|
const [isOpen, setOpen] = React.useState(false);
|
|
3945
3946
|
React.useEffect(() => {
|
|
@@ -3947,30 +3948,30 @@ const useGridPopoverHook = (props) => {
|
|
|
3947
3948
|
}, []);
|
|
3948
3949
|
const triggerSave = React.useCallback(async (reason) => {
|
|
3949
3950
|
if (reason == CloseReason.CANCEL) {
|
|
3950
|
-
|
|
3951
|
+
stopEditing();
|
|
3952
|
+
onBulkEditingComplete();
|
|
3951
3953
|
return;
|
|
3952
3954
|
}
|
|
3953
|
-
if (props
|
|
3955
|
+
if (props?.invalid?.()) {
|
|
3956
|
+
// Don't close, don't do anything it's invalid
|
|
3954
3957
|
return;
|
|
3955
3958
|
}
|
|
3956
3959
|
if (!props.save) {
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
if (props.invalid)
|
|
3962
|
-
stopEditing();
|
|
3963
|
-
if (await updateValue(props.save, reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0)) {
|
|
3964
|
-
if (!props.invalid)
|
|
3965
|
-
stopEditing();
|
|
3966
|
-
}
|
|
3960
|
+
// No save method so just close
|
|
3961
|
+
stopEditing();
|
|
3962
|
+
onBulkEditingComplete();
|
|
3963
|
+
return;
|
|
3967
3964
|
}
|
|
3968
|
-
|
|
3965
|
+
if (await updateValue(props.save, reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0)) {
|
|
3966
|
+
stopEditing();
|
|
3967
|
+
}
|
|
3968
|
+
}, [onBulkEditingComplete, props, stopEditing, updateValue]);
|
|
3969
3969
|
const popoverWrapper = React.useCallback((children) => {
|
|
3970
3970
|
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: anchorRef.current && (jsxRuntime.jsxs(ControlledMenu, { state: isOpen ? 'open' : 'closed', portal: true, unmountOnClose: true, anchorRef: anchorRef, saveButtonRef: saveButtonRef, menuClassName: 'step-ag-grid-react-menu', onClose: (event) => {
|
|
3971
3971
|
// Prevent menu from closing when modals are invoked
|
|
3972
|
-
if (event.reason === CloseReason.BLUR)
|
|
3972
|
+
if (event.reason === CloseReason.BLUR) {
|
|
3973
3973
|
return;
|
|
3974
|
+
}
|
|
3974
3975
|
void triggerSave(event.reason);
|
|
3975
3976
|
}, viewScroll: 'auto', dontShrinkIfDirectionIsTop: true, className: props.className, children: [saving && ( // This is the overlay that prevents editing when the editor is saving
|
|
3976
3977
|
jsxRuntime.jsx("div", { className: 'ComponentLoadingWrapper-saveOverlay' })), children, jsxRuntime.jsx("button", { ref: saveButtonRef, "data-reason": '', onClick: (e) => {
|
|
@@ -4838,12 +4839,14 @@ const GridFormTextInput = (props) => {
|
|
|
4838
4839
|
const [value, setValue] = React.useState(initValue);
|
|
4839
4840
|
const invalid = React.useCallback(() => TextInputValidator(props, value, data, {}), [data, props, value]);
|
|
4840
4841
|
const save = React.useCallback(async (selectedRows) => {
|
|
4841
|
-
if (invalid())
|
|
4842
|
+
if (invalid()) {
|
|
4842
4843
|
return false;
|
|
4844
|
+
}
|
|
4843
4845
|
const trimmedValue = value.trim();
|
|
4844
4846
|
// No change, so don't save
|
|
4845
|
-
if (initValue === trimmedValue)
|
|
4847
|
+
if (initValue === trimmedValue) {
|
|
4846
4848
|
return true;
|
|
4849
|
+
}
|
|
4847
4850
|
if (props.onSave) {
|
|
4848
4851
|
return await props.onSave({ selectedRows, value: trimmedValue });
|
|
4849
4852
|
}
|
|
@@ -5064,7 +5067,7 @@ const isFlexColumn = (colDef) => !!colDef.flex && !isGridCellFiller(colDef);
|
|
|
5064
5067
|
* Also, make sure the provider is created in a separate component, otherwise it won't be found.
|
|
5065
5068
|
*/
|
|
5066
5069
|
const GridContextProvider = (props) => {
|
|
5067
|
-
const { modifyUpdating,
|
|
5070
|
+
const { modifyUpdating, anyUpdating } = React.useContext(GridUpdatingContext);
|
|
5068
5071
|
const [gridApi, setGridApi] = React.useState();
|
|
5069
5072
|
const [gridReady, setGridReady] = React.useState(false);
|
|
5070
5073
|
const [quickFilter, _setQuickFilter] = React.useState('');
|
|
@@ -5083,7 +5086,7 @@ const GridContextProvider = (props) => {
|
|
|
5083
5086
|
/**
|
|
5084
5087
|
* Make extra sure the GridCellFillerColId never gets added to invisibleColumnIds as it's dynamically determined
|
|
5085
5088
|
*/
|
|
5086
|
-
const setInvisibleColumnIds = (invisibleColumnIds) => _setInvisibleColumnIds(lodashEs.pull(invisibleColumnIds, GridCellFillerColId));
|
|
5089
|
+
const setInvisibleColumnIds = React.useCallback((invisibleColumnIds) => _setInvisibleColumnIds(lodashEs.pull(invisibleColumnIds, GridCellFillerColId)), []);
|
|
5087
5090
|
/**
|
|
5088
5091
|
* Set quick filter directly on grid, based on previously save quickFilter state.
|
|
5089
5092
|
*/
|
|
@@ -5178,17 +5181,6 @@ const GridContextProvider = (props) => {
|
|
|
5178
5181
|
}
|
|
5179
5182
|
prePopupFocusedCell.current = gridApi.getFocusedCell() ?? undefined;
|
|
5180
5183
|
}, [gridApi]);
|
|
5181
|
-
/**
|
|
5182
|
-
* After a popup refocus the cell.
|
|
5183
|
-
*/
|
|
5184
|
-
const postPopupOps = React.useCallback(() => {
|
|
5185
|
-
if (!gridApi || gridApi.isDestroyed()) {
|
|
5186
|
-
return;
|
|
5187
|
-
}
|
|
5188
|
-
if (prePopupFocusedCell.current) {
|
|
5189
|
-
gridApi.setFocusedCell(prePopupFocusedCell.current.rowIndex, prePopupFocusedCell.current.column);
|
|
5190
|
-
}
|
|
5191
|
-
}, [gridApi]);
|
|
5192
5184
|
/**
|
|
5193
5185
|
* Get all row id's in grid.
|
|
5194
5186
|
*/
|
|
@@ -5376,13 +5368,16 @@ const GridContextProvider = (props) => {
|
|
|
5376
5368
|
gridApi.sizeColumnsToFit();
|
|
5377
5369
|
}
|
|
5378
5370
|
}, [gridApi]);
|
|
5379
|
-
|
|
5380
|
-
|
|
5371
|
+
/**
|
|
5372
|
+
*
|
|
5373
|
+
*/
|
|
5374
|
+
const resetFocusedCellAfterCellEditing = React.useCallback(() => {
|
|
5375
|
+
if (!gridApi || gridApi.isDestroyed() || startCellEditingInProgressRef.current) {
|
|
5381
5376
|
return;
|
|
5382
5377
|
}
|
|
5383
|
-
gridApi.stopEditing();
|
|
5384
5378
|
if (prePopupFocusedCell.current) {
|
|
5385
5379
|
gridApi.setFocusedCell(prePopupFocusedCell.current.rowIndex, prePopupFocusedCell.current.column);
|
|
5380
|
+
prePopupFocusedCell.current = undefined;
|
|
5386
5381
|
}
|
|
5387
5382
|
}, [gridApi]);
|
|
5388
5383
|
// waitForExternallySelectedItemsToBeInSync can't use the state as it won't be updated during function execution
|
|
@@ -5403,58 +5398,65 @@ const GridContextProvider = (props) => {
|
|
|
5403
5398
|
console.error('externallySelectedItems did not sync with ag-grid selection');
|
|
5404
5399
|
}
|
|
5405
5400
|
}, []);
|
|
5401
|
+
const startCellEditingInProgressRef = React.useRef(false);
|
|
5406
5402
|
const startCellEditing = React.useCallback(async ({ rowId, colId }) => {
|
|
5407
|
-
if (!gridApi)
|
|
5408
|
-
return;
|
|
5409
|
-
const colDef = gridApi.getColumnDef(colId);
|
|
5410
|
-
if (!colDef) {
|
|
5411
|
-
return;
|
|
5412
|
-
}
|
|
5413
|
-
const rowNode = gridApi.getRowNode(`${rowId}`);
|
|
5414
|
-
if (!rowNode) {
|
|
5403
|
+
if (!gridApi || startCellEditingInProgressRef.current) {
|
|
5415
5404
|
return;
|
|
5416
5405
|
}
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5406
|
+
startCellEditingInProgressRef.current = true;
|
|
5407
|
+
try {
|
|
5408
|
+
// Edit in progress so don't edit until finished, timeout waiting after 5s
|
|
5409
|
+
if (!(await waitForCondition(() => !anyUpdating(), 5000))) {
|
|
5410
|
+
console.error("Could not start edit because previous edit hasn't finished after 5 seconds");
|
|
5411
|
+
return;
|
|
5412
|
+
}
|
|
5413
|
+
const colDef = gridApi.getColumnDef(colId);
|
|
5414
|
+
if (!colDef) {
|
|
5415
|
+
return;
|
|
5416
|
+
}
|
|
5417
|
+
const rowNode = gridApi.getRowNode(`${rowId}`);
|
|
5418
|
+
if (!rowNode) {
|
|
5419
|
+
return;
|
|
5420
|
+
}
|
|
5421
|
+
prePopupOps();
|
|
5422
|
+
const shouldSelectNode = !rowNode.isSelected();
|
|
5423
|
+
if (shouldSelectNode) {
|
|
5424
|
+
externallySelectedItemsAreInSyncRef.current = false;
|
|
5425
|
+
setExternallySelectedItemsAreInSync(false);
|
|
5426
|
+
rowNode.setSelected(true, true);
|
|
5427
|
+
await waitForExternallySelectedItemsToBeInSync();
|
|
5428
|
+
}
|
|
5429
|
+
const rowIndex = rowNode.rowIndex;
|
|
5430
|
+
if (rowIndex != null) {
|
|
5431
|
+
lodashEs.defer(() => {
|
|
5432
|
+
!gridApi.isDestroyed() &&
|
|
5433
|
+
gridApi.startEditingCell({
|
|
5434
|
+
rowIndex,
|
|
5435
|
+
colKey: colId,
|
|
5436
|
+
});
|
|
5437
|
+
});
|
|
5438
|
+
}
|
|
5438
5439
|
}
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
const
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
const
|
|
5449
|
-
|
|
5440
|
+
finally {
|
|
5441
|
+
startCellEditingInProgressRef.current = false;
|
|
5442
|
+
}
|
|
5443
|
+
}, [anyUpdating, gridApi, prePopupOps, waitForExternallySelectedItemsToBeInSync]);
|
|
5444
|
+
const bulkEditingCompleteCallbackRef = React.useRef();
|
|
5445
|
+
const onBulkEditingComplete = React.useCallback(() => {
|
|
5446
|
+
resetFocusedCellAfterCellEditing();
|
|
5447
|
+
bulkEditingCompleteCallbackRef.current?.();
|
|
5448
|
+
}, [resetFocusedCellAfterCellEditing]);
|
|
5449
|
+
const setOnBulkEditingComplete = React.useCallback((cellEditingCompleteCallback) => {
|
|
5450
|
+
bulkEditingCompleteCallbackRef.current = cellEditingCompleteCallback;
|
|
5450
5451
|
}, []);
|
|
5451
5452
|
/**
|
|
5452
5453
|
* Returns true if an editable cell on same row was selected, else false.
|
|
5453
5454
|
*/
|
|
5454
5455
|
const selectNextEditableCell = React.useCallback(async (tabDirection) => {
|
|
5455
5456
|
// Pretend it succeeded to prevent unwanted cellEditingCompleteCallback
|
|
5456
|
-
if (!gridApi)
|
|
5457
|
+
if (!gridApi) {
|
|
5457
5458
|
return true;
|
|
5459
|
+
}
|
|
5458
5460
|
const focusedCellIsEditable = () => {
|
|
5459
5461
|
const focusedCell = gridApi.isDestroyed() ? null : gridApi.getFocusedCell();
|
|
5460
5462
|
const nextColumn = focusedCell?.column;
|
|
@@ -5470,16 +5472,16 @@ const GridContextProvider = (props) => {
|
|
|
5470
5472
|
if (gridApi.isDestroyed()) {
|
|
5471
5473
|
return true;
|
|
5472
5474
|
}
|
|
5475
|
+
// Prevent resetting focus to original editing cell
|
|
5476
|
+
prePopupFocusedCell.current = undefined;
|
|
5473
5477
|
const preRow = gridApi.getFocusedCell();
|
|
5474
5478
|
if (tabDirection === 1) {
|
|
5479
|
+
gridApi.stopEditing();
|
|
5475
5480
|
gridApi.tabToNextCell();
|
|
5476
5481
|
}
|
|
5477
5482
|
else {
|
|
5478
5483
|
gridApi.tabToPreviousCell();
|
|
5479
5484
|
}
|
|
5480
|
-
// If we don't wait the tab to next element won't work
|
|
5481
|
-
// I think this is due to the grid resizing
|
|
5482
|
-
await wait(150);
|
|
5483
5485
|
if (gridApi.isDestroyed()) {
|
|
5484
5486
|
return true;
|
|
5485
5487
|
}
|
|
@@ -5492,64 +5494,71 @@ const GridContextProvider = (props) => {
|
|
|
5492
5494
|
if (focusedCellIsEditable()) {
|
|
5493
5495
|
const focusedCell = gridApi.getFocusedCell();
|
|
5494
5496
|
if (focusedCell) {
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
}
|
|
5497
|
+
const rowNode = gridApi.getDisplayedRowAtIndex(focusedCell.rowIndex);
|
|
5498
|
+
const rowId = rowNode?.data?.id;
|
|
5499
|
+
if (rowId == null) {
|
|
5500
|
+
return false;
|
|
5501
|
+
}
|
|
5502
|
+
await startCellEditing({ rowId, colId: focusedCell.column.getColId() });
|
|
5500
5503
|
return true;
|
|
5501
5504
|
}
|
|
5502
5505
|
}
|
|
5503
5506
|
}
|
|
5504
5507
|
return false;
|
|
5505
|
-
}, [gridApi,
|
|
5508
|
+
}, [gridApi, startCellEditing]);
|
|
5506
5509
|
const updatingCells = React.useCallback(async (props, fnUpdate, setSaving, tabDirection) => {
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5510
|
+
try {
|
|
5511
|
+
setSaving?.(true);
|
|
5512
|
+
return await gridApiOp(async (gridApi) => {
|
|
5513
|
+
const selectedRows = props.selectedRows;
|
|
5514
|
+
let ok = false;
|
|
5515
|
+
await modifyUpdating(props.field ?? '', selectedRows.map((data) => data.id), async () => {
|
|
5516
|
+
// MATT Disabled I don't believe these are needed anymore
|
|
5517
|
+
// I've left them here just in case they are
|
|
5518
|
+
// Need to refresh to get spinners to work on all rows
|
|
5519
|
+
// gridApi.refreshCells({ rowNodes: props.selectedRows as RowNode[], force: true });
|
|
5520
|
+
ok = await fnUpdate(selectedRows).catch((ex) => {
|
|
5521
|
+
console.error('Exception during modifyUpdating', ex);
|
|
5522
|
+
return false;
|
|
5523
|
+
});
|
|
5524
|
+
});
|
|
5512
5525
|
// MATT Disabled I don't believe these are needed anymore
|
|
5513
5526
|
// I've left them here just in case they are
|
|
5514
|
-
//
|
|
5515
|
-
// gridApi.refreshCells({ rowNodes:
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
return false;
|
|
5519
|
-
});
|
|
5520
|
-
});
|
|
5521
|
-
// MATT Disabled I don't believe these are needed anymore
|
|
5522
|
-
// I've left them here just in case they are
|
|
5523
|
-
// async processes need to refresh their own rows
|
|
5524
|
-
// gridApi.refreshCells({ rowNodes: selectedRows as RowNode[], force: true });
|
|
5525
|
-
if (gridApi.isDestroyed()) {
|
|
5526
|
-
return ok;
|
|
5527
|
-
}
|
|
5528
|
-
if (ok) {
|
|
5529
|
-
const cell = gridApi.getFocusedCell();
|
|
5530
|
-
if (cell && gridApi.getFocusedCell() == null) {
|
|
5531
|
-
!gridApi.isDestroyed && gridApi.setFocusedCell(cell.rowIndex, cell.column);
|
|
5527
|
+
// async processes need to refresh their own rows
|
|
5528
|
+
// gridApi.refreshCells({ rowNodes: selectedRows as RowNode[], force: true });
|
|
5529
|
+
if (gridApi.isDestroyed()) {
|
|
5530
|
+
return ok;
|
|
5532
5531
|
}
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
// Only focus next cell if user hasn't already manually changed focus
|
|
5541
|
-
const postPopupFocusedCell = gridApi.getFocusedCell();
|
|
5542
|
-
if (prePopupFocusedCell.current &&
|
|
5543
|
-
postPopupFocusedCell &&
|
|
5544
|
-
prePopupFocusedCell.current.rowIndex == postPopupFocusedCell.rowIndex &&
|
|
5545
|
-
prePopupFocusedCell.current.column.getColId() == postPopupFocusedCell.column.getColId()) {
|
|
5546
|
-
if (!tabDirection || !(await selectNextEditableCell(tabDirection))) {
|
|
5547
|
-
cellEditingCompleteCallbackRef.current && cellEditingCompleteCallbackRef.current();
|
|
5532
|
+
if (ok) {
|
|
5533
|
+
const cell = gridApi.getFocusedCell();
|
|
5534
|
+
if (cell && gridApi.getFocusedCell() == null) {
|
|
5535
|
+
!gridApi.isDestroyed && gridApi.setFocusedCell(cell.rowIndex, cell.column);
|
|
5536
|
+
}
|
|
5537
|
+
// This is needed to trigger postSortRowsHook
|
|
5538
|
+
gridApi.refreshClientSideRowModel();
|
|
5548
5539
|
}
|
|
5549
|
-
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
|
|
5540
|
+
void (async () => {
|
|
5541
|
+
// Only focus next cell if user hasn't already manually changed focus
|
|
5542
|
+
const postPopupFocusedCell = gridApi.getFocusedCell();
|
|
5543
|
+
if (prePopupFocusedCell.current &&
|
|
5544
|
+
postPopupFocusedCell &&
|
|
5545
|
+
prePopupFocusedCell.current.rowIndex == postPopupFocusedCell.rowIndex &&
|
|
5546
|
+
prePopupFocusedCell.current.column.getColId() == postPopupFocusedCell.column.getColId()) {
|
|
5547
|
+
if (!tabDirection || !(await selectNextEditableCell(tabDirection))) {
|
|
5548
|
+
onBulkEditingComplete();
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
else {
|
|
5552
|
+
onBulkEditingComplete();
|
|
5553
|
+
}
|
|
5554
|
+
})();
|
|
5555
|
+
return ok;
|
|
5556
|
+
});
|
|
5557
|
+
}
|
|
5558
|
+
finally {
|
|
5559
|
+
setSaving?.(false);
|
|
5560
|
+
}
|
|
5561
|
+
}, [gridApiOp, modifyUpdating, onBulkEditingComplete, selectNextEditableCell]);
|
|
5553
5562
|
const redrawRows = React.useMemo(() => debounce((rowNodes) => {
|
|
5554
5563
|
try {
|
|
5555
5564
|
gridApi && gridApi.redrawRows(rowNodes ? { rowNodes } : undefined);
|
|
@@ -5580,16 +5589,16 @@ const GridContextProvider = (props) => {
|
|
|
5580
5589
|
preHash !== postHash && gridApi.clearFocusedCell();
|
|
5581
5590
|
}
|
|
5582
5591
|
}, 200), [gridApi]);
|
|
5583
|
-
const addExternalFilter = (filter) => {
|
|
5592
|
+
const addExternalFilter = React.useCallback((filter) => {
|
|
5584
5593
|
externalFilters.current.push(filter);
|
|
5585
5594
|
void onFilterChanged();
|
|
5586
|
-
};
|
|
5587
|
-
const removeExternalFilter = (filter) => {
|
|
5595
|
+
}, [onFilterChanged]);
|
|
5596
|
+
const removeExternalFilter = React.useCallback((filter) => {
|
|
5588
5597
|
lodashEs.remove(externalFilters.current, (v) => v === filter);
|
|
5589
5598
|
void onFilterChanged();
|
|
5590
|
-
};
|
|
5591
|
-
const isExternalFilterPresent = () => !lodashEs.isEmpty(externalFilters.current);
|
|
5592
|
-
const doesExternalFilterPass = (node) => externalFilters.current.every((filter) => filter(node.data, node));
|
|
5599
|
+
}, [onFilterChanged]);
|
|
5600
|
+
const isExternalFilterPresent = React.useCallback(() => !lodashEs.isEmpty(externalFilters.current), []);
|
|
5601
|
+
const doesExternalFilterPass = React.useCallback((node) => externalFilters.current.every((filter) => filter(node.data, node)), []);
|
|
5593
5602
|
const getColDef = React.useCallback((colId) => (!!colId && gridApi?.getColumnDef(colId)) || undefined, [gridApi]);
|
|
5594
5603
|
const showNoRowsOverlay = React.useCallback(() => {
|
|
5595
5604
|
gridApi?.showNoRowsOverlay();
|
|
@@ -5645,7 +5654,6 @@ const GridContextProvider = (props) => {
|
|
|
5645
5654
|
setInvisibleColumnIds,
|
|
5646
5655
|
gridReady,
|
|
5647
5656
|
prePopupOps,
|
|
5648
|
-
postPopupOps,
|
|
5649
5657
|
setApis,
|
|
5650
5658
|
setQuickFilter,
|
|
5651
5659
|
selectRowsById,
|
|
@@ -5666,8 +5674,7 @@ const GridContextProvider = (props) => {
|
|
|
5666
5674
|
sizeColumnsToFit,
|
|
5667
5675
|
autoSizeColumns,
|
|
5668
5676
|
startCellEditing,
|
|
5669
|
-
|
|
5670
|
-
cancelEdit,
|
|
5677
|
+
resetFocusedCellAfterCellEditing,
|
|
5671
5678
|
updatingCells,
|
|
5672
5679
|
redrawRows,
|
|
5673
5680
|
externallySelectedItemsAreInSync,
|
|
@@ -5678,7 +5685,8 @@ const GridContextProvider = (props) => {
|
|
|
5678
5685
|
isExternalFilterPresent,
|
|
5679
5686
|
doesExternalFilterPass,
|
|
5680
5687
|
downloadCsv,
|
|
5681
|
-
|
|
5688
|
+
onBulkEditingComplete,
|
|
5689
|
+
setOnBulkEditingComplete,
|
|
5682
5690
|
showNoRowsOverlay,
|
|
5683
5691
|
}, children: props.children }));
|
|
5684
5692
|
};
|
|
@@ -5725,12 +5733,23 @@ const downloadCsvUseValueFormattersProcessCellCallback = (params) => {
|
|
|
5725
5733
|
// We add an extra encodeToString here just in case valueFormatter is returning non string values
|
|
5726
5734
|
return encodeToString(result);
|
|
5727
5735
|
};
|
|
5736
|
+
const waitForCondition = async (condition, timeoutMs) => {
|
|
5737
|
+
const endTime = Date.now() + timeoutMs;
|
|
5738
|
+
while (Date.now() < endTime) {
|
|
5739
|
+
if (condition()) {
|
|
5740
|
+
return true;
|
|
5741
|
+
}
|
|
5742
|
+
await wait(100);
|
|
5743
|
+
}
|
|
5744
|
+
console.warn('waitForCondition failed');
|
|
5745
|
+
return false;
|
|
5746
|
+
};
|
|
5728
5747
|
|
|
5729
5748
|
const GridUpdatingContextProvider = (props) => {
|
|
5730
5749
|
const updatingBlocks = React.useRef({});
|
|
5731
5750
|
const updating = React.useRef({});
|
|
5732
5751
|
const [updatedDep, setUpdatedDep] = React.useState(0);
|
|
5733
|
-
const resetUpdating = () => {
|
|
5752
|
+
const resetUpdating = React.useCallback(() => {
|
|
5734
5753
|
const mergedUpdatingBlocks = {};
|
|
5735
5754
|
for (const key in updatingBlocks.current) {
|
|
5736
5755
|
const arr = lodashEs.flatten(updatingBlocks.current[key]);
|
|
@@ -5740,9 +5759,9 @@ const GridUpdatingContextProvider = (props) => {
|
|
|
5740
5759
|
}
|
|
5741
5760
|
updating.current = mergedUpdatingBlocks;
|
|
5742
5761
|
setUpdatedDep((updatedDep) => updatedDep + 1);
|
|
5743
|
-
};
|
|
5744
|
-
const updatingCols = () => Object.keys(updating.current);
|
|
5745
|
-
const modifyUpdating = async (fields, ids, fn) => {
|
|
5762
|
+
}, []);
|
|
5763
|
+
const updatingCols = React.useCallback(() => Object.keys(updating.current), []);
|
|
5764
|
+
const modifyUpdating = React.useCallback(async (fields, ids, fn) => {
|
|
5746
5765
|
const idRef = [...ids];
|
|
5747
5766
|
lodashEs.castArray(fields).forEach((field) => {
|
|
5748
5767
|
const fieldUpdatingIds = updatingBlocks.current[field] ?? (updatingBlocks.current[field] = []);
|
|
@@ -5755,9 +5774,12 @@ const GridUpdatingContextProvider = (props) => {
|
|
|
5755
5774
|
lodashEs.remove(fieldUpdatingIds, (idList) => idList === idRef);
|
|
5756
5775
|
});
|
|
5757
5776
|
resetUpdating();
|
|
5758
|
-
};
|
|
5759
|
-
const
|
|
5760
|
-
|
|
5777
|
+
}, [resetUpdating]);
|
|
5778
|
+
const anyUpdating = React.useCallback(() => {
|
|
5779
|
+
return !lodashEs.isEmpty(updating.current);
|
|
5780
|
+
}, []);
|
|
5781
|
+
const checkUpdating = React.useCallback((fields, id) => lodashEs.castArray(fields).some((f) => updating.current[f]?.includes(id)), []);
|
|
5782
|
+
return (jsxRuntime.jsx(GridUpdatingContext.Provider, { value: { modifyUpdating, anyUpdating, checkUpdating, updatingCols, updatedDep }, children: props.children }));
|
|
5761
5783
|
};
|
|
5762
5784
|
|
|
5763
5785
|
var css_248z = ".ActionButton{align-items:center;display:flex}.ActionButton-inProgress .LuiIcon{visibility:hidden}.ActionButton-minimal.lui-button-lg.lui-button-icon-right{padding-right:38px}.ActionButton.lui-button-lg.lui-button-icon-right:not(.ActionButton-tight) .LuiIcon{margin:0 4px}.ActionButton.ActionButton-tight.lui-button-lg.lui-button-icon-right .LuiIcon{margin:0}.ActionButton-iconOnly.lui-button-lg.lui-button-icon-right:not(.ActionButton-tight){padding:8px 5px}.ActionButton-iconOnly.lui-button-lg.lui-button-icon-right.ActionButton-tight{padding:0}.ActionButton-minimalArea{position:relative}.ActionButton-minimalAreaDisplay{position:absolute}.ActionButton-minimalAreaExpand{visibility:hidden}.ActionButton-inProgress.lui-button-lg.lui-button-icon-right{background-color:#e2f3f7;color:#007198;cursor:progress}.ActionButton-fill{justify-content:center;width:100%}";
|