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