@linzjs/step-ag-grid 29.1.1 → 29.1.3
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/src/components/Grid.d.ts +1 -1
- package/dist/src/components/GridPopoverHook.d.ts +2 -1
- package/dist/src/contexts/GridContext.d.ts +2 -2
- package/dist/src/index.d.ts +1 -0
- package/dist/src/utils/waitForCondition.d.ts +1 -0
- package/dist/step-ag-grid.cjs +89 -65
- package/dist/step-ag-grid.cjs.map +1 -1
- package/dist/step-ag-grid.esm.js +88 -66
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Grid.tsx +1 -1
- package/src/components/GridCell.tsx +34 -14
- package/src/components/GridPopoverHook.tsx +16 -17
- package/src/components/gridForm/GridFormDropDown.tsx +10 -3
- package/src/components/gridForm/GridFormMultiSelect.tsx +12 -4
- package/src/components/gridPopoverEdit/GridPopoverMessage.ts +1 -0
- package/src/contexts/GridContext.tsx +2 -2
- package/src/contexts/GridContextProvider.tsx +41 -37
- package/src/index.ts +1 -0
- package/src/stories/grid/GridPopoutEditGeneric.stories.tsx +1 -1
- package/src/stories/grid/GridPopoverEditMultiSelect.stories.tsx +1 -1
- package/src/stories/grid/GridPopoverEditMultiSelectGrid.stories.tsx +1 -1
- package/src/stories/grid/gridFormInteraction/GridFormDropDownInteraction.stories.tsx +4 -12
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx +5 -11
- package/src/stories/grid/gridFormInteraction/GridFormEditBearingInteraction.stories.tsx +4 -11
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectGridInteraction.stories.tsx +8 -10
- package/src/stories/grid/gridFormInteraction/GridFormMultiSelectInteraction.stories.tsx +5 -11
- package/src/stories/grid/gridFormInteraction/GridFormPopoverMenuInteraction.stories.tsx +5 -12
- package/src/stories/grid/gridFormInteraction/GridFormTextAreaInteraction.stories.tsx +4 -11
- package/src/stories/grid/gridFormInteraction/GridFormTextInputInteraction.stories.tsx +4 -11
- package/src/stories/grid/interactions/GridKeyboardInteractions.stories.tsx +56 -13
- package/src/utils/waitForCondition.tsx +17 -0
package/package.json
CHANGED
package/src/components/Grid.tsx
CHANGED
|
@@ -101,7 +101,7 @@ export interface GridProps<TData extends GridBaseRow = GridBaseRow> {
|
|
|
101
101
|
* When pressing tab whilst editing the grid will select and edit the next cell if available.
|
|
102
102
|
* Once the last cell to edit closes this callback is called.
|
|
103
103
|
*/
|
|
104
|
-
onBulkEditingComplete?: () => void;
|
|
104
|
+
onBulkEditingComplete?: () => Promise<void> | void;
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* Context menu definition if required.
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
ValueFormatterParams,
|
|
12
12
|
ValueGetterFunc,
|
|
13
13
|
} from 'ag-grid-community';
|
|
14
|
-
import {
|
|
14
|
+
import { defer } from 'lodash-es';
|
|
15
|
+
import { forwardRef, ReactElement, useContext, useEffect } from 'react';
|
|
15
16
|
|
|
16
17
|
import { GridPopoverContextProvider } from '../contexts/GridPopoverContextProvider';
|
|
17
18
|
import { GridUpdatingContext } from '../contexts/GridUpdatingContext';
|
|
@@ -153,20 +154,25 @@ export const GridCell = <TData extends GridBaseRow, TValue = any, Props extends
|
|
|
153
154
|
sortable: true,
|
|
154
155
|
resizable: true,
|
|
155
156
|
valueSetter: custom?.editor ? blockValueSetter : undefined,
|
|
156
|
-
editable: props.editable ??
|
|
157
|
-
...(custom?.editor
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
157
|
+
editable: props.editable ?? !!custom?.editor,
|
|
158
|
+
...(custom?.editor
|
|
159
|
+
? {
|
|
160
|
+
cellClassRules: GridCellMultiSelectClassRules,
|
|
161
|
+
cellEditor: GenericCellEditorComponentWrapper(custom?.editor),
|
|
162
|
+
}
|
|
163
|
+
: {
|
|
164
|
+
cellEditor: CellEditorToBlockEditing,
|
|
165
|
+
}),
|
|
162
166
|
suppressKeyboardEvent: suppressCellKeyboardEvents,
|
|
163
|
-
...(custom?.editorParams
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
...(custom?.editorParams
|
|
168
|
+
? {
|
|
169
|
+
cellEditorParams: {
|
|
170
|
+
...custom.editorParams,
|
|
171
|
+
multiEdit: custom.multiEdit,
|
|
172
|
+
preventAutoEdit: custom.preventAutoEdit ?? !custom?.editor,
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
: { cellEditorParams: { preventAutoEdit: !custom?.editor } }),
|
|
170
176
|
// If there's a valueFormatter and no filterValueGetter then create a filterValueGetter
|
|
171
177
|
getQuickFilterText: filterValueGetter as any,
|
|
172
178
|
// Default value formatter, otherwise react freaks out on objects
|
|
@@ -184,6 +190,20 @@ export const GridCell = <TData extends GridBaseRow, TValue = any, Props extends
|
|
|
184
190
|
};
|
|
185
191
|
};
|
|
186
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Ag-grid will start its own editor if editable is true and there is no cell editor
|
|
195
|
+
* like in the case of a cell that is editable because it triggers a modal.
|
|
196
|
+
* This will block that editor.
|
|
197
|
+
*/
|
|
198
|
+
const CellEditorToBlockEditing = ({ stopEditing }: { stopEditing: () => void }) => {
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
defer(() => {
|
|
201
|
+
stopEditing();
|
|
202
|
+
});
|
|
203
|
+
}, [stopEditing]);
|
|
204
|
+
return <></>;
|
|
205
|
+
};
|
|
206
|
+
|
|
187
207
|
export interface CellEditorCommon {
|
|
188
208
|
className?: string | undefined;
|
|
189
209
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ReactElement, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
|
-
import { useGridContext } from '../contexts/GridContext';
|
|
4
3
|
import { useGridPopoverContext } from '../contexts/GridPopoverContext';
|
|
5
4
|
import { ControlledMenu } from '../react-menu3';
|
|
6
5
|
import { MenuCloseEvent } from '../react-menu3/types';
|
|
@@ -20,8 +19,14 @@ export interface GridPopoverHookProps<TData> {
|
|
|
20
19
|
dontSaveOnExternalClick?: boolean;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
export const
|
|
24
|
-
|
|
22
|
+
export const CancelPromise = () => Promise.resolve(true);
|
|
23
|
+
|
|
24
|
+
export const useGridPopoverHook = <TData extends GridBaseRow>({
|
|
25
|
+
className,
|
|
26
|
+
save,
|
|
27
|
+
invalid,
|
|
28
|
+
dontSaveOnExternalClick,
|
|
29
|
+
}: GridPopoverHookProps<TData>) => {
|
|
25
30
|
const { anchorRef, saving, updateValue, stopEditing } = useGridPopoverContext<TData>();
|
|
26
31
|
const saveButtonRef = useRef<HTMLButtonElement>(null);
|
|
27
32
|
const [isOpen, setOpen] = useState(false);
|
|
@@ -33,32 +38,26 @@ export const useGridPopoverHook = <TData extends GridBaseRow>(props: GridPopover
|
|
|
33
38
|
const triggerSave = useCallback(
|
|
34
39
|
async (reason?: string) => {
|
|
35
40
|
if (reason == CloseReason.CANCEL) {
|
|
41
|
+
await updateValue(CancelPromise, 0);
|
|
36
42
|
stopEditing();
|
|
37
|
-
|
|
43
|
+
|
|
38
44
|
return;
|
|
39
45
|
}
|
|
40
|
-
if (
|
|
46
|
+
if (invalid?.()) {
|
|
41
47
|
// Don't close, don't do anything it's invalid
|
|
42
48
|
return;
|
|
43
49
|
}
|
|
44
50
|
|
|
45
|
-
if (!props.save) {
|
|
46
|
-
// No save method so just close
|
|
47
|
-
stopEditing();
|
|
48
|
-
onBulkEditingComplete();
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
51
|
if (
|
|
53
52
|
await updateValue(
|
|
54
|
-
|
|
53
|
+
save ?? (() => Promise.resolve(true)),
|
|
55
54
|
reason === CloseReason.TAB_FORWARD ? 1 : reason === CloseReason.TAB_BACKWARD ? -1 : 0,
|
|
56
55
|
)
|
|
57
56
|
) {
|
|
58
57
|
stopEditing();
|
|
59
58
|
}
|
|
60
59
|
},
|
|
61
|
-
[
|
|
60
|
+
[invalid, save, stopEditing, updateValue],
|
|
62
61
|
);
|
|
63
62
|
|
|
64
63
|
const popoverWrapper = useCallback(
|
|
@@ -82,7 +81,7 @@ export const useGridPopoverHook = <TData extends GridBaseRow>(props: GridPopover
|
|
|
82
81
|
}}
|
|
83
82
|
viewScroll={'auto'}
|
|
84
83
|
dontShrinkIfDirectionIsTop={true}
|
|
85
|
-
className={
|
|
84
|
+
className={className}
|
|
86
85
|
>
|
|
87
86
|
{saving && ( // This is the overlay that prevents editing when the editor is saving
|
|
88
87
|
<div className={'ComponentLoadingWrapper-saveOverlay'} />
|
|
@@ -93,7 +92,7 @@ export const useGridPopoverHook = <TData extends GridBaseRow>(props: GridPopover
|
|
|
93
92
|
data-reason={''}
|
|
94
93
|
onClick={(e) => {
|
|
95
94
|
let reason = e.currentTarget.getAttribute('data-reason') ?? undefined;
|
|
96
|
-
if (
|
|
95
|
+
if (dontSaveOnExternalClick && reason === CloseReason.BLUR) {
|
|
97
96
|
reason = CloseReason.CANCEL;
|
|
98
97
|
}
|
|
99
98
|
void triggerSave(reason);
|
|
@@ -105,7 +104,7 @@ export const useGridPopoverHook = <TData extends GridBaseRow>(props: GridPopover
|
|
|
105
104
|
</>
|
|
106
105
|
);
|
|
107
106
|
},
|
|
108
|
-
[anchorRef, isOpen,
|
|
107
|
+
[anchorRef, isOpen, className, dontSaveOnExternalClick, saving, triggerSave],
|
|
109
108
|
);
|
|
110
109
|
|
|
111
110
|
return {
|
|
@@ -32,7 +32,7 @@ interface FinalSelectOption<TOptionValue> {
|
|
|
32
32
|
export const primitiveToSelectOption = <T,>(value: T): SelectOption<T> => {
|
|
33
33
|
return {
|
|
34
34
|
value: value,
|
|
35
|
-
label: value ? String(value) : '',
|
|
35
|
+
label: value ? String(value) : '-',
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
38
|
|
|
@@ -178,7 +178,14 @@ export const GridFormDropDown = <TData extends GridBaseRow, TOptionValue>(
|
|
|
178
178
|
if (selectedItem === null) {
|
|
179
179
|
if (props.onSelectFilter) {
|
|
180
180
|
const { onSelectFilter } = props;
|
|
181
|
-
|
|
181
|
+
if (!isEmpty(filter)) {
|
|
182
|
+
await onSelectFilter({
|
|
183
|
+
selectedRows,
|
|
184
|
+
selectedRowIds: selectedRows.map((row) => row.id),
|
|
185
|
+
value: filter as any,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
182
189
|
return true;
|
|
183
190
|
} else {
|
|
184
191
|
if (filteredValues && filteredValues.length === 1) {
|
|
@@ -230,7 +237,7 @@ export const GridFormDropDown = <TData extends GridBaseRow, TOptionValue>(
|
|
|
230
237
|
!props.onSelectFilter &&
|
|
231
238
|
!(filteredValues && filteredValues.length === 1 && !filteredValues[0].subComponent)
|
|
232
239
|
}
|
|
233
|
-
onChange={(e) => setFilter(e.target.value)}
|
|
240
|
+
onChange={(e) => setFilter(e.target.value.trim())}
|
|
234
241
|
/>
|
|
235
242
|
{props.filterHelpText && isNotEmpty(filter) && (
|
|
236
243
|
<FormError error={null} helpText={props.filterHelpText} />
|
|
@@ -98,10 +98,14 @@ export const GridFormMultiSelect = <TData extends GridBaseRow>(props: GridFormMu
|
|
|
98
98
|
|
|
99
99
|
const save = useCallback(
|
|
100
100
|
async (selectedRows: TData[]): Promise<boolean> => {
|
|
101
|
-
if (!options || !props.onSave)
|
|
101
|
+
if (!options || !props.onSave) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
102
104
|
|
|
103
105
|
// Any changes to save?
|
|
104
|
-
if (initialValues === JSON.stringify(options))
|
|
106
|
+
if (initialValues === JSON.stringify(options)) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
105
109
|
|
|
106
110
|
return props.onSave({
|
|
107
111
|
selectedRows,
|
|
@@ -278,7 +282,9 @@ const FilterInput = (props: {
|
|
|
278
282
|
}, [filter, headerGroups, options, setOptions]);
|
|
279
283
|
|
|
280
284
|
const addCustomFilterValue = useCallback(() => {
|
|
281
|
-
if (!options || !onSelectFilter)
|
|
285
|
+
if (!options || !onSelectFilter) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
282
288
|
|
|
283
289
|
const filterTrimmed = filter.trim();
|
|
284
290
|
if (isEmpty(filterTrimmed)) {
|
|
@@ -289,7 +295,9 @@ const FilterInput = (props: {
|
|
|
289
295
|
const preFilterOptions = JSON.stringify(options);
|
|
290
296
|
onSelectFilter({ filter: filterTrimmed, options });
|
|
291
297
|
// Detect if options list changed and update
|
|
292
|
-
if (preFilterOptions === JSON.stringify(options))
|
|
298
|
+
if (preFilterOptions === JSON.stringify(options)) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
293
301
|
|
|
294
302
|
setOptions([...options]);
|
|
295
303
|
setFilter('');
|
|
@@ -63,8 +63,8 @@ export interface GridContextType<TData extends GridBaseRow> {
|
|
|
63
63
|
invisibleColumnIds: string[] | undefined;
|
|
64
64
|
setInvisibleColumnIds: (colIds: string[]) => void;
|
|
65
65
|
downloadCsv: (csvExportParams?: CsvExportParams) => void;
|
|
66
|
-
onBulkEditingComplete: () => void;
|
|
67
|
-
setOnBulkEditingComplete: (callback: (() => void) | undefined) => void;
|
|
66
|
+
onBulkEditingComplete: () => Promise<void> | void;
|
|
67
|
+
setOnBulkEditingComplete: (callback: (() => Promise<void> | void) | undefined) => void;
|
|
68
68
|
showNoRowsOverlay: () => void;
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
CellPosition,
|
|
3
|
+
ColDef,
|
|
4
|
+
CsvExportParams,
|
|
5
|
+
GridApi,
|
|
6
|
+
IRowNode,
|
|
7
|
+
ProcessCellForExportParams,
|
|
8
|
+
RowNode,
|
|
9
|
+
} from 'ag-grid-community';
|
|
3
10
|
import debounce from 'debounce-promise';
|
|
4
11
|
import { compact, defer, delay, difference, filter, isEmpty, last, pull, remove, sortBy, sumBy } from 'lodash-es';
|
|
5
12
|
import { PropsWithChildren, ReactElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
@@ -8,6 +15,7 @@ import { ColDefT, GridBaseRow } from '../components';
|
|
|
8
15
|
import { GridCellFillerColId, isGridCellFiller } from '../components/GridCellFiller';
|
|
9
16
|
import { getColId, isFlexColumn } from '../components/gridUtil';
|
|
10
17
|
import { fnOrVar, isNotEmpty, sanitiseFileName, wait } from '../utils/util';
|
|
18
|
+
import { waitForCondition } from '../utils/waitForCondition';
|
|
11
19
|
import { AutoSizeColumnsProps, AutoSizeColumnsResult, GridContext, GridFilterExternal } from './GridContext';
|
|
12
20
|
import { GridUpdatingContext } from './GridUpdatingContext';
|
|
13
21
|
|
|
@@ -494,8 +502,13 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
|
|
|
494
502
|
|
|
495
503
|
try {
|
|
496
504
|
// Edit in progress so don't edit until finished, timeout waiting after 5s
|
|
497
|
-
if (
|
|
498
|
-
|
|
505
|
+
if (
|
|
506
|
+
!(await waitForCondition(
|
|
507
|
+
'startCellEditing failed as update still in progress, waited for 15 seconds',
|
|
508
|
+
() => !anyUpdating(),
|
|
509
|
+
15000,
|
|
510
|
+
))
|
|
511
|
+
) {
|
|
499
512
|
return;
|
|
500
513
|
}
|
|
501
514
|
|
|
@@ -521,11 +534,12 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
|
|
|
521
534
|
const rowIndex = rowNode.rowIndex;
|
|
522
535
|
if (rowIndex != null) {
|
|
523
536
|
defer(() => {
|
|
524
|
-
!gridApi.isDestroyed()
|
|
537
|
+
if (!gridApi.isDestroyed()) {
|
|
525
538
|
gridApi.startEditingCell({
|
|
526
539
|
rowIndex,
|
|
527
540
|
colKey: colId,
|
|
528
541
|
});
|
|
542
|
+
}
|
|
529
543
|
});
|
|
530
544
|
}
|
|
531
545
|
} finally {
|
|
@@ -535,15 +549,18 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
|
|
|
535
549
|
[anyUpdating, gridApi, prePopupOps, waitForExternallySelectedItemsToBeInSync],
|
|
536
550
|
);
|
|
537
551
|
|
|
538
|
-
const bulkEditingCompleteCallbackRef = useRef<() => void>();
|
|
539
|
-
const onBulkEditingComplete = useCallback(() => {
|
|
552
|
+
const bulkEditingCompleteCallbackRef = useRef<() => Promise<void> | void>();
|
|
553
|
+
const onBulkEditingComplete = useCallback(async () => {
|
|
540
554
|
resetFocusedCellAfterCellEditing();
|
|
541
|
-
bulkEditingCompleteCallbackRef.current?.();
|
|
555
|
+
await bulkEditingCompleteCallbackRef.current?.();
|
|
542
556
|
}, [resetFocusedCellAfterCellEditing]);
|
|
543
557
|
|
|
544
|
-
const setOnBulkEditingComplete = useCallback(
|
|
545
|
-
|
|
546
|
-
|
|
558
|
+
const setOnBulkEditingComplete = useCallback(
|
|
559
|
+
(cellEditingCompleteCallback: (() => Promise<void> | void) | undefined) => {
|
|
560
|
+
bulkEditingCompleteCallbackRef.current = cellEditingCompleteCallback;
|
|
561
|
+
},
|
|
562
|
+
[],
|
|
563
|
+
);
|
|
547
564
|
|
|
548
565
|
/**
|
|
549
566
|
* Returns true if an editable cell on same row was selected, else false.
|
|
@@ -577,8 +594,10 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
|
|
|
577
594
|
prePopupFocusedCell.current = undefined;
|
|
578
595
|
|
|
579
596
|
const preRow = gridApi.getFocusedCell();
|
|
597
|
+
// If we don't do this ag-grid will do its own continuation of an edit on tab, we don't want that as
|
|
598
|
+
// we are managing it ourselves
|
|
599
|
+
gridApi.stopEditing();
|
|
580
600
|
if (tabDirection === 1) {
|
|
581
|
-
gridApi.stopEditing();
|
|
582
601
|
gridApi.tabToNextCell();
|
|
583
602
|
} else {
|
|
584
603
|
gridApi.tabToPreviousCell();
|
|
@@ -621,6 +640,7 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
|
|
|
621
640
|
): Promise<boolean> => {
|
|
622
641
|
try {
|
|
623
642
|
setSaving?.(true);
|
|
643
|
+
|
|
624
644
|
return await gridApiOp(async (gridApi) => {
|
|
625
645
|
const selectedRows = props.selectedRows;
|
|
626
646
|
|
|
@@ -630,10 +650,8 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
|
|
|
630
650
|
props.field ?? '',
|
|
631
651
|
selectedRows.map((data) => data.id),
|
|
632
652
|
async () => {
|
|
633
|
-
// MATT Disabled I don't believe these are needed anymore
|
|
634
|
-
// I've left them here just in case they are
|
|
635
653
|
// Need to refresh to get spinners to work on all rows
|
|
636
|
-
|
|
654
|
+
gridApi.refreshCells({ rowNodes: props.selectedRows as RowNode[], force: true });
|
|
637
655
|
ok = await fnUpdate(selectedRows).catch((ex) => {
|
|
638
656
|
console.error('Exception during modifyUpdating', ex);
|
|
639
657
|
return false;
|
|
@@ -641,23 +659,21 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
|
|
|
641
659
|
},
|
|
642
660
|
);
|
|
643
661
|
|
|
644
|
-
// MATT Disabled I don't believe these are needed anymore
|
|
645
|
-
// I've left them here just in case they are
|
|
646
662
|
// async processes need to refresh their own rows
|
|
647
|
-
|
|
663
|
+
gridApi.refreshCells({ rowNodes: selectedRows as RowNode[], force: true });
|
|
648
664
|
|
|
649
665
|
if (gridApi.isDestroyed()) {
|
|
650
666
|
return ok;
|
|
651
667
|
}
|
|
652
668
|
|
|
653
669
|
if (ok) {
|
|
654
|
-
const cell = gridApi.getFocusedCell();
|
|
655
|
-
if (cell && gridApi.getFocusedCell() == null) {
|
|
656
|
-
|
|
657
|
-
}
|
|
670
|
+
//const cell = gridApi.getFocusedCell();
|
|
671
|
+
//if (cell && gridApi.getFocusedCell() == null) {
|
|
672
|
+
// !gridApi.isDestroyed && gridApi.setFocusedCell(cell.rowIndex, cell.column);
|
|
673
|
+
// }
|
|
658
674
|
|
|
659
675
|
// This is needed to trigger postSortRowsHook
|
|
660
|
-
gridApi.refreshClientSideRowModel();
|
|
676
|
+
!gridApi.isDestroyed && gridApi.refreshClientSideRowModel();
|
|
661
677
|
}
|
|
662
678
|
|
|
663
679
|
void (async () => {
|
|
@@ -670,10 +686,10 @@ export const GridContextProvider = <TData extends GridBaseRow>(props: PropsWithC
|
|
|
670
686
|
prePopupFocusedCell.current.column.getColId() == postPopupFocusedCell.column.getColId()
|
|
671
687
|
) {
|
|
672
688
|
if (!tabDirection || !(await selectNextEditableCell(tabDirection))) {
|
|
673
|
-
onBulkEditingComplete();
|
|
689
|
+
await onBulkEditingComplete();
|
|
674
690
|
}
|
|
675
691
|
} else {
|
|
676
|
-
onBulkEditingComplete();
|
|
692
|
+
await onBulkEditingComplete();
|
|
677
693
|
}
|
|
678
694
|
})();
|
|
679
695
|
|
|
@@ -909,15 +925,3 @@ export const downloadCsvUseValueFormattersProcessCellCallback = (params: Process
|
|
|
909
925
|
// We add an extra encodeToString here just in case valueFormatter is returning non string values
|
|
910
926
|
return encodeToString(result);
|
|
911
927
|
};
|
|
912
|
-
|
|
913
|
-
const waitForCondition = async (condition: () => boolean, timeoutMs: number): Promise<boolean> => {
|
|
914
|
-
const endTime = Date.now() + timeoutMs;
|
|
915
|
-
while (Date.now() < endTime) {
|
|
916
|
-
if (condition()) {
|
|
917
|
-
return true;
|
|
918
|
-
}
|
|
919
|
-
await wait(100);
|
|
920
|
-
}
|
|
921
|
-
console.warn('waitForCondition failed');
|
|
922
|
-
return false;
|
|
923
|
-
};
|
package/src/index.ts
CHANGED
|
@@ -30,7 +30,7 @@ export default {
|
|
|
30
30
|
],
|
|
31
31
|
} as Meta<typeof Grid>;
|
|
32
32
|
|
|
33
|
-
const GridPopoutEditGenericTemplate: StoryFn<typeof Grid
|
|
33
|
+
const GridPopoutEditGenericTemplate: StoryFn<typeof Grid<IFormTestRow>> = (props: GridProps<IFormTestRow>) => {
|
|
34
34
|
const [externalSelectedItems, setExternalSelectedItems] = useState<any[]>([]);
|
|
35
35
|
const columnDefs: ColDefT<IFormTestRow>[] = useMemo(
|
|
36
36
|
() => [
|
|
@@ -49,7 +49,7 @@ interface ITestRow {
|
|
|
49
49
|
position3: string | null;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const GridEditMultiSelectTemplate: StoryFn<typeof Grid
|
|
52
|
+
const GridEditMultiSelectTemplate: StoryFn<typeof Grid<ITestRow>> = (props: GridProps<ITestRow>) => {
|
|
53
53
|
const [externalSelectedItems, setExternalSelectedItems] = useState<any[]>([]);
|
|
54
54
|
|
|
55
55
|
const columnDefs: ColDefT<ITestRow>[] = useMemo(() => {
|
|
@@ -39,7 +39,7 @@ interface ITestRow {
|
|
|
39
39
|
position2: string | null;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
const GridEditMultiSelectGridTemplate: StoryFn<typeof Grid
|
|
42
|
+
const GridEditMultiSelectGridTemplate: StoryFn<typeof Grid<ITestRow>> = (props: GridProps<ITestRow>) => {
|
|
43
43
|
const [externalSelectedItems, setExternalSelectedItems] = useState<any[]>([]);
|
|
44
44
|
|
|
45
45
|
const columnDefs: ColDefT<ITestRow>[] = useMemo(() => {
|
|
@@ -10,8 +10,7 @@ import { expect, fn, userEvent, within } from 'storybook/test';
|
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
12
|
GridBaseRow,
|
|
13
|
-
|
|
14
|
-
GridContextType,
|
|
13
|
+
GridContextProvider,
|
|
15
14
|
GridFormDropDown,
|
|
16
15
|
GridFormDropDownProps,
|
|
17
16
|
GridFormSubComponentTextInput,
|
|
@@ -51,14 +50,7 @@ const Template: StoryFn<typeof GridFormDropDown<GridBaseRow, number>> = (
|
|
|
51
50
|
|
|
52
51
|
return (
|
|
53
52
|
<div className={'react-menu-inline-test'}>
|
|
54
|
-
<
|
|
55
|
-
value={
|
|
56
|
-
{
|
|
57
|
-
onBulkEditingComplete: () => {},
|
|
58
|
-
resetFocusedCellAfterCellEditing: () => {},
|
|
59
|
-
} as unknown as GridContextType<GridBaseRow>
|
|
60
|
-
}
|
|
61
|
-
>
|
|
53
|
+
<GridContextProvider>
|
|
62
54
|
<h6 ref={anchorRef}>Interaction test</h6>
|
|
63
55
|
<GridPopoverContext.Provider
|
|
64
56
|
value={{
|
|
@@ -77,7 +69,7 @@ const Template: StoryFn<typeof GridFormDropDown<GridBaseRow, number>> = (
|
|
|
77
69
|
>
|
|
78
70
|
<GridFormDropDown {...props} {...config} />
|
|
79
71
|
</GridPopoverContext.Provider>
|
|
80
|
-
</
|
|
72
|
+
</GridContextProvider>
|
|
81
73
|
</div>
|
|
82
74
|
);
|
|
83
75
|
};
|
|
@@ -131,7 +123,7 @@ GridFormDropDownInteractions_.play = async ({ canvasElement }) => {
|
|
|
131
123
|
// Test escape to not save
|
|
132
124
|
updateValue.mockClear();
|
|
133
125
|
await userEvent.type(textInput, '{Escape}');
|
|
134
|
-
expect(updateValue).
|
|
126
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), 0);
|
|
135
127
|
|
|
136
128
|
// Test invalid value doesn't save
|
|
137
129
|
updateValue.mockClear();
|
package/src/stories/grid/gridFormInteraction/GridFormEditBearingCorrectionInteraction.stories.tsx
CHANGED
|
@@ -9,7 +9,8 @@ import { useRef } from 'react';
|
|
|
9
9
|
import { expect, fn, userEvent, within } from 'storybook/test';
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
-
|
|
12
|
+
CancelPromise,
|
|
13
|
+
GridContextProvider,
|
|
13
14
|
GridFormEditBearing,
|
|
14
15
|
GridFormEditBearingProps,
|
|
15
16
|
GridPopoverEditBearingCorrectionEditorParams,
|
|
@@ -28,14 +29,7 @@ const Template: StoryFn<typeof GridFormEditBearing> = (props: GridFormEditBearin
|
|
|
28
29
|
|
|
29
30
|
return (
|
|
30
31
|
<div className={'react-menu-inline-test'}>
|
|
31
|
-
<
|
|
32
|
-
value={
|
|
33
|
-
{
|
|
34
|
-
onBulkEditingComplete: () => {},
|
|
35
|
-
resetFocusedCellAfterCellEditing: () => {},
|
|
36
|
-
} as any
|
|
37
|
-
}
|
|
38
|
-
>
|
|
32
|
+
<GridContextProvider>
|
|
39
33
|
<h6 ref={anchorRef}>Interaction Test</h6>
|
|
40
34
|
<GridPopoverContext.Provider
|
|
41
35
|
value={{
|
|
@@ -54,7 +48,7 @@ const Template: StoryFn<typeof GridFormEditBearing> = (props: GridFormEditBearin
|
|
|
54
48
|
>
|
|
55
49
|
<GridFormEditBearing {...props} {...GridPopoverEditBearingCorrectionEditorParams} />
|
|
56
50
|
</GridPopoverContext.Provider>
|
|
57
|
-
</
|
|
51
|
+
</GridContextProvider>
|
|
58
52
|
</div>
|
|
59
53
|
);
|
|
60
54
|
};
|
|
@@ -93,7 +87,7 @@ GridFormEditBearingCorrectionInteractions_.play = async ({ canvasElement }) => {
|
|
|
93
87
|
// Test escape not to save
|
|
94
88
|
updateValue.mockClear();
|
|
95
89
|
await userEvent.type(inputField, '{Escape}');
|
|
96
|
-
expect(updateValue).
|
|
90
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), 0);
|
|
97
91
|
|
|
98
92
|
// Test invalid value doesn't save
|
|
99
93
|
updateValue.mockClear();
|
|
@@ -9,7 +9,7 @@ import { useRef } from 'react';
|
|
|
9
9
|
import { expect, fn, userEvent, within } from 'storybook/test';
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
-
|
|
12
|
+
GridContextProvider,
|
|
13
13
|
GridFormEditBearing,
|
|
14
14
|
GridFormEditBearingProps,
|
|
15
15
|
GridPopoverEditBearingEditorParams,
|
|
@@ -28,14 +28,7 @@ const Template: StoryFn<typeof GridFormEditBearing> = (props: GridFormEditBearin
|
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
30
|
<div className={'react-menu-inline-test'}>
|
|
31
|
-
<
|
|
32
|
-
value={
|
|
33
|
-
{
|
|
34
|
-
onBulkEditingComplete: () => {},
|
|
35
|
-
resetFocusedCellAfterCellEditing: () => {},
|
|
36
|
-
} as any
|
|
37
|
-
}
|
|
38
|
-
>
|
|
31
|
+
<GridContextProvider>
|
|
39
32
|
<h6 ref={anchorRef}>Interaction Test</h6>
|
|
40
33
|
<GridPopoverContext.Provider
|
|
41
34
|
value={{
|
|
@@ -54,7 +47,7 @@ const Template: StoryFn<typeof GridFormEditBearing> = (props: GridFormEditBearin
|
|
|
54
47
|
>
|
|
55
48
|
<GridFormEditBearing {...props} {...GridPopoverEditBearingEditorParams} />
|
|
56
49
|
</GridPopoverContext.Provider>
|
|
57
|
-
</
|
|
50
|
+
</GridContextProvider>
|
|
58
51
|
</div>
|
|
59
52
|
);
|
|
60
53
|
};
|
|
@@ -93,7 +86,7 @@ GridFormEditBearingInteractions_.play = async ({ canvasElement }) => {
|
|
|
93
86
|
// Test escape not to save
|
|
94
87
|
updateValue.mockClear();
|
|
95
88
|
await userEvent.type(inputField, '{Escape}');
|
|
96
|
-
expect(updateValue).
|
|
89
|
+
expect(updateValue).toHaveBeenCalledWith(expect.anything(), 0);
|
|
97
90
|
|
|
98
91
|
// Test invalid value doesn't save
|
|
99
92
|
updateValue.mockClear();
|
|
@@ -8,7 +8,12 @@ import { GridPopoverContext } from 'contexts/GridPopoverContext';
|
|
|
8
8
|
import { useRef } from 'react';
|
|
9
9
|
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
GridContextProvider,
|
|
13
|
+
GridFormMultiSelectGrid,
|
|
14
|
+
GridFormMultiSelectGridProps,
|
|
15
|
+
MultiSelectGridOption,
|
|
16
|
+
} from '../../..';
|
|
12
17
|
|
|
13
18
|
export default {
|
|
14
19
|
title: 'GridForm / Interactions',
|
|
@@ -42,14 +47,7 @@ const Template: StoryFn<typeof GridFormMultiSelectGrid> = (props: GridFormMultiS
|
|
|
42
47
|
|
|
43
48
|
return (
|
|
44
49
|
<div className={'react-menu-inline-test'}>
|
|
45
|
-
<
|
|
46
|
-
value={
|
|
47
|
-
{
|
|
48
|
-
onBulkEditingComplete: () => {},
|
|
49
|
-
resetFocusedCellAfterCellEditing: () => {},
|
|
50
|
-
} as any
|
|
51
|
-
}
|
|
52
|
-
>
|
|
50
|
+
<GridContextProvider>
|
|
53
51
|
<h6 ref={anchorRef}>Interaction test</h6>
|
|
54
52
|
<GridPopoverContext.Provider
|
|
55
53
|
value={{
|
|
@@ -68,7 +66,7 @@ const Template: StoryFn<typeof GridFormMultiSelectGrid> = (props: GridFormMultiS
|
|
|
68
66
|
>
|
|
69
67
|
<GridFormMultiSelectGrid {...props} {...config} />
|
|
70
68
|
</GridPopoverContext.Provider>
|
|
71
|
-
</
|
|
69
|
+
</GridContextProvider>
|
|
72
70
|
</div>
|
|
73
71
|
);
|
|
74
72
|
};
|