@linzjs/step-ag-grid 1.5.4 → 2.0.0
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.d.ts +2 -2
- package/dist/index.js +241 -200
- package/dist/index.js.map +1 -1
- package/dist/src/components/GridCell.d.ts +18 -27
- package/dist/src/components/GridPopoverHook.d.ts +4 -2
- package/dist/src/components/gridForm/GridFormDropDown.d.ts +8 -3
- package/dist/src/components/gridForm/GridFormEditBearing.d.ts +3 -4
- package/dist/src/components/gridForm/GridFormMessage.d.ts +4 -5
- package/dist/src/components/gridForm/GridFormMultiSelect.d.ts +2 -3
- package/dist/src/components/gridForm/GridFormPopoutMenu.d.ts +2 -3
- package/dist/src/components/gridForm/GridFormTextArea.d.ts +2 -3
- package/dist/src/components/gridForm/GridFormTextInput.d.ts +2 -3
- package/dist/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.d.ts +3 -2
- package/dist/src/components/gridPopoverEdit/GridPopoverEditBearing.d.ts +5 -270
- package/dist/src/components/gridPopoverEdit/GridPopoverEditDropDown.d.ts +3 -2
- package/dist/src/components/gridPopoverEdit/GridPopoverMenu.d.ts +2 -2
- package/dist/src/components/gridPopoverEdit/GridPopoverMessage.d.ts +3 -2
- package/dist/src/components/gridPopoverEdit/GridPopoverTextArea.d.ts +3 -2
- package/dist/src/components/gridPopoverEdit/GridPopoverTextInput.d.ts +3 -2
- package/dist/src/components/gridRender/GridRenderGenericCell.d.ts +1 -3
- package/dist/src/contexts/GridPopoverContext.d.ts +17 -0
- package/dist/src/contexts/GridPopoverContextProvider.d.ts +6 -0
- package/dist/src/contexts/{UpdatingContext.d.ts → GridUpdatingContext.d.ts} +2 -2
- package/dist/src/contexts/GridUpdatingContextProvider.d.ts +7 -0
- package/dist/src/stories/components/FormTest.d.ts +1 -2
- package/dist/step-ag-grid.esm.js +238 -198
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Grid.tsx +2 -2
- package/src/components/GridCell.tsx +57 -79
- package/src/components/GridLoadableCell.tsx +4 -1
- package/src/components/GridPopoverHook.tsx +10 -14
- package/src/components/gridForm/GridFormDropDown.tsx +41 -30
- package/src/components/gridForm/GridFormEditBearing.tsx +13 -13
- package/src/components/gridForm/GridFormMessage.tsx +8 -13
- package/src/components/gridForm/GridFormMultiSelect.tsx +19 -19
- package/src/components/gridForm/GridFormPopoutMenu.tsx +7 -8
- package/src/components/gridForm/GridFormTextArea.tsx +16 -17
- package/src/components/gridForm/GridFormTextInput.tsx +17 -17
- package/src/components/gridPopoverEdit/GridPopoutEditMultiSelect.ts +17 -16
- package/src/components/gridPopoverEdit/GridPopoverEditBearing.ts +53 -45
- package/src/components/gridPopoverEdit/GridPopoverEditDropDown.ts +17 -16
- package/src/components/gridPopoverEdit/GridPopoverMenu.tsx +20 -21
- package/src/components/gridPopoverEdit/GridPopoverMessage.ts +18 -16
- package/src/components/gridPopoverEdit/GridPopoverTextArea.ts +12 -16
- package/src/components/gridPopoverEdit/GridPopoverTextInput.ts +15 -15
- package/src/components/gridRender/GridRenderGenericCell.tsx +3 -5
- package/src/components/gridRender/GridRenderPopoutMenuCell.tsx +2 -2
- package/src/contexts/GridContextProvider.tsx +3 -5
- package/src/contexts/GridPopoverContext.tsx +32 -0
- package/src/contexts/GridPopoverContextProvider.tsx +53 -0
- package/src/contexts/{UpdatingContext.tsx → GridUpdatingContext.tsx} +2 -2
- package/src/contexts/{UpdatingContextProvider.tsx → GridUpdatingContextProvider.tsx} +8 -6
- package/src/stories/components/FormTest.tsx +4 -3
- package/src/stories/components/GridPopoutBearing.stories.tsx +28 -25
- package/src/stories/components/GridPopoutEditDropDown.stories.tsx +91 -50
- package/src/stories/components/GridPopoutEditGeneric.stories.tsx +18 -13
- package/src/stories/components/GridPopoutEditGenericTextArea.stories.tsx +76 -61
- package/src/stories/components/GridPopoutEditMultiSelect.stories.tsx +58 -51
- package/src/stories/components/GridReadOnly.stories.tsx +73 -57
- package/dist/src/contexts/UpdatingContextProvider.d.ts +0 -7
package/package.json
CHANGED
package/src/components/Grid.tsx
CHANGED
|
@@ -12,7 +12,7 @@ import { GridContext } from "@contexts/GridContext";
|
|
|
12
12
|
import { usePostSortRowsHook } from "./PostSortRowsHook";
|
|
13
13
|
import { isNotEmpty } from "@utils/util";
|
|
14
14
|
import { GridHeaderSelect } from "./gridHeader/GridHeaderSelect";
|
|
15
|
-
import {
|
|
15
|
+
import { GridUpdatingContext } from "@contexts/GridUpdatingContext";
|
|
16
16
|
|
|
17
17
|
export interface GridBaseRow {
|
|
18
18
|
id: string | number;
|
|
@@ -47,7 +47,7 @@ export const Grid = (params: GridProps): JSX.Element => {
|
|
|
47
47
|
ensureSelectedRowIsVisible,
|
|
48
48
|
sizeColumnsToFit,
|
|
49
49
|
} = useContext(GridContext);
|
|
50
|
-
const { checkUpdating } = useContext(
|
|
50
|
+
const { checkUpdating } = useContext(GridUpdatingContext);
|
|
51
51
|
|
|
52
52
|
const [internalQuickFilter, setInternalQuickFilter] = useState("");
|
|
53
53
|
const lastSelectedIds = useRef<number[]>([]);
|
|
@@ -1,40 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { forwardRef, useContext } from "react";
|
|
2
2
|
import { GridBaseRow } from "./Grid";
|
|
3
|
-
import {
|
|
4
|
-
import { GridContext } from "@contexts/GridContext";
|
|
3
|
+
import { GridUpdatingContext } from "@contexts/GridUpdatingContext";
|
|
5
4
|
import { GenericMultiEditCellClass } from "./GenericCellClass";
|
|
6
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
GenericCellColDef,
|
|
7
|
+
GenericCellRendererParams,
|
|
8
|
+
GridRendererGenericCell,
|
|
9
|
+
} from "./gridRender/GridRenderGenericCell";
|
|
7
10
|
import { ColDef, ICellEditorParams, ICellRendererParams } from "ag-grid-community";
|
|
8
11
|
import { GridLoadableCell } from "./GridLoadableCell";
|
|
9
12
|
import { GridIcon } from "@components/GridIcon";
|
|
10
13
|
import { ValueFormatterParams } from "ag-grid-community/dist/lib/entities/colDef";
|
|
14
|
+
import { GridPopoverContext } from "@contexts/GridPopoverContext";
|
|
15
|
+
import { GridPopoverContextProvider } from "@contexts/GridPopoverContextProvider";
|
|
11
16
|
|
|
12
|
-
export interface
|
|
13
|
-
cellEditorParams: ICellEditorParams;
|
|
14
|
-
updateValue: (saveFn: (selectedRows: RowType[]) => Promise<boolean>) => Promise<boolean>;
|
|
15
|
-
saving: boolean;
|
|
16
|
-
data: RowType;
|
|
17
|
-
value: any;
|
|
18
|
-
field: string | undefined;
|
|
19
|
-
selectedRows: RowType[];
|
|
20
|
-
formProps: Record<string, any>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface GenericCellEditorParams<RowType extends GridBaseRow> {
|
|
17
|
+
export interface GenericCellEditorProps<E> {
|
|
24
18
|
multiEdit?: boolean;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export interface GenericCellEditorColDef<
|
|
29
|
-
RowType extends GridBaseRow,
|
|
30
|
-
FormProps extends GenericCellEditorParams<RowType>,
|
|
31
|
-
> extends ColDef {
|
|
32
|
-
cellEditorParams?: FormProps;
|
|
33
|
-
cellRendererParams?: GenericCellRendererParams<RowType>;
|
|
19
|
+
editor?: (editorProps: E) => JSX.Element;
|
|
20
|
+
editorParams?: E; // Omit<E, keyof CellParams<IFormTestRow>>
|
|
34
21
|
}
|
|
35
22
|
|
|
36
23
|
export const GridCellRenderer = (props: ICellRendererParams) => {
|
|
37
|
-
const { checkUpdating } = useContext(
|
|
24
|
+
const { checkUpdating } = useContext(GridUpdatingContext);
|
|
38
25
|
const colDef = props.colDef as ColDef;
|
|
39
26
|
|
|
40
27
|
const rendererParams = colDef.cellRendererParams as GenericCellRendererParams<any> | undefined;
|
|
@@ -56,19 +43,32 @@ export const GridCellRenderer = (props: ICellRendererParams) => {
|
|
|
56
43
|
);
|
|
57
44
|
};
|
|
58
45
|
|
|
59
|
-
|
|
46
|
+
// This is so that typescript retains the row type to pass to the GridCells
|
|
47
|
+
export interface ColDefT<RowType extends GridBaseRow> extends ColDef {
|
|
48
|
+
_?: RowType;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*
|
|
60
52
|
* For editing a text area.
|
|
61
53
|
*/
|
|
62
|
-
export const GridCell = <RowType extends GridBaseRow,
|
|
63
|
-
props:
|
|
64
|
-
|
|
54
|
+
export const GridCell = <RowType extends GridBaseRow, Props>(
|
|
55
|
+
props: GenericCellColDef<RowType>,
|
|
56
|
+
custom?: {
|
|
57
|
+
multiEdit?: boolean;
|
|
58
|
+
editor?: (editorProps: Props) => JSX.Element;
|
|
59
|
+
editorParams?: Props;
|
|
60
|
+
},
|
|
61
|
+
): ColDefT<RowType> => {
|
|
65
62
|
return {
|
|
66
63
|
sortable: !!(props?.field || props?.valueGetter),
|
|
67
64
|
resizable: true,
|
|
68
|
-
...(
|
|
69
|
-
cellClass:
|
|
70
|
-
editable: true,
|
|
71
|
-
cellEditor: GenericCellEditorComponent,
|
|
65
|
+
...(custom?.editor && {
|
|
66
|
+
cellClass: custom?.multiEdit ? GenericMultiEditCellClass : undefined,
|
|
67
|
+
editable: props.editable ?? true,
|
|
68
|
+
cellEditor: GenericCellEditorComponent(custom.editor),
|
|
69
|
+
}),
|
|
70
|
+
...(custom?.editorParams && {
|
|
71
|
+
cellEditorParams: { ...custom.editorParams, multiEdit: custom.multiEdit },
|
|
72
72
|
}),
|
|
73
73
|
// Default value formatter, otherwise react freaks out on objects
|
|
74
74
|
valueFormatter: (params: ValueFormatterParams) => {
|
|
@@ -86,59 +86,37 @@ export const GridCell = <RowType extends GridBaseRow, FormProps extends GenericC
|
|
|
86
86
|
};
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
interface
|
|
90
|
-
|
|
89
|
+
export interface CellParams<RowType extends GridBaseRow> {
|
|
90
|
+
value: any;
|
|
91
91
|
data: RowType;
|
|
92
|
-
|
|
92
|
+
field: string | undefined;
|
|
93
|
+
selectedRows: RowType[];
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
// TODO memo?
|
|
97
|
+
export const GenericCellEditorComponent = (editor: (props: any) => JSX.Element) =>
|
|
98
|
+
forwardRef(function GenericCellEditorComponent2(props: ICellEditorParams, _) {
|
|
99
|
+
return (
|
|
100
|
+
<GridPopoverContextProvider>
|
|
101
|
+
<GenericCellEditorComponent3 {...{ ...props, editor }} />
|
|
102
|
+
</GridPopoverContextProvider>
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const GenericCellEditorComponent3 = (props: ICellEditorParams & { editor: (props: any) => JSX.Element }) => {
|
|
107
|
+
const { setProps, propsRef } = useContext(GridPopoverContext);
|
|
108
|
+
|
|
109
|
+
const { colDef } = props;
|
|
110
|
+
const { cellEditorParams } = colDef;
|
|
103
111
|
const multiEdit = cellEditorParams?.multiEdit ?? false;
|
|
104
|
-
const field = props.colDef.field ?? "";
|
|
105
|
-
|
|
106
|
-
const formProps = colDef.cellEditorParams ?? {};
|
|
107
|
-
const value = props.value;
|
|
108
|
-
|
|
109
|
-
const selectedRows = useMemo(
|
|
110
|
-
() => (multiEdit ? getSelectedRows<RowType>() : [data]),
|
|
111
|
-
[data, getSelectedRows, multiEdit],
|
|
112
|
-
);
|
|
113
112
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const updateValue = useCallback(
|
|
117
|
-
async (saveFn: (selectedRows: any[]) => Promise<boolean>): Promise<boolean> => {
|
|
118
|
-
return !saving && (await updatingCells({ selectedRows, field }, saveFn, setSaving));
|
|
119
|
-
},
|
|
120
|
-
[field, saving, selectedRows, updatingCells],
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
if (cellEditorParams == null) return <></>;
|
|
113
|
+
// TODO don't need all these props in context
|
|
114
|
+
setProps(props, multiEdit);
|
|
124
115
|
|
|
125
116
|
return (
|
|
126
117
|
<>
|
|
127
|
-
<div>{colDef.cellRenderer ? <colDef.cellRenderer {...props}
|
|
128
|
-
{
|
|
129
|
-
<cellEditorParams.form
|
|
130
|
-
cellEditorParams={props}
|
|
131
|
-
updateValue={updateValue}
|
|
132
|
-
saving={saving}
|
|
133
|
-
formProps={formProps}
|
|
134
|
-
data={data}
|
|
135
|
-
value={value}
|
|
136
|
-
field={field}
|
|
137
|
-
selectedRows={selectedRows}
|
|
138
|
-
/>
|
|
139
|
-
)}
|
|
118
|
+
<div>{colDef.cellRenderer ? <colDef.cellRenderer {...props} /> : props.value}</div>
|
|
119
|
+
{props?.editor && <props.editor {...cellEditorParams} {...propsRef.current} />}
|
|
140
120
|
</>
|
|
141
121
|
);
|
|
142
122
|
};
|
|
143
|
-
|
|
144
|
-
export const GenericCellEditorComponent = forwardRef(GenericCellEditorComponentFr);
|
|
@@ -2,6 +2,8 @@ import "./GridLoadableCell.scss";
|
|
|
2
2
|
|
|
3
3
|
import { LuiMiniSpinner } from "@linzjs/lui";
|
|
4
4
|
import clsx from "clsx";
|
|
5
|
+
import { useContext } from "react";
|
|
6
|
+
import { GridPopoverContext } from "@contexts/GridPopoverContext";
|
|
5
7
|
|
|
6
8
|
export const GridLoadableCell = (props: {
|
|
7
9
|
isLoading: boolean;
|
|
@@ -9,7 +11,8 @@ export const GridLoadableCell = (props: {
|
|
|
9
11
|
children: JSX.Element | string;
|
|
10
12
|
className?: string;
|
|
11
13
|
}): JSX.Element => {
|
|
12
|
-
|
|
14
|
+
const { saving } = useContext(GridPopoverContext);
|
|
15
|
+
|
|
13
16
|
if (props.isLoading) {
|
|
14
17
|
return (
|
|
15
18
|
<div style={{ display: "flex", alignItems: "center" }}>
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
import { ICellEditorParams } from "ag-grid-community";
|
|
2
1
|
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
3
2
|
import { GridContext } from "@contexts/GridContext";
|
|
4
|
-
import { GridFormProps } from "./GridCell";
|
|
5
3
|
import { GridBaseRow } from "./Grid";
|
|
6
4
|
import { ControlledMenu } from "@react-menu3";
|
|
5
|
+
import { GridPopoverContext } from "@contexts/GridPopoverContext";
|
|
7
6
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const { eGridCell } = cellEditorParams as ICellEditorParams;
|
|
7
|
+
export interface GridPopoverHookProps<RowType> {
|
|
8
|
+
save?: (selectedRows: RowType[]) => Promise<boolean>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const useGridPopoverHook = <RowType extends GridBaseRow>(props: GridPopoverHookProps<RowType> = {}) => {
|
|
14
12
|
const { stopEditing } = useContext(GridContext);
|
|
13
|
+
const { anchorRef, saving, updateValueRef } = useContext(GridPopoverContext);
|
|
15
14
|
const saveButtonRef = useRef<HTMLButtonElement>(null);
|
|
16
|
-
const anchorRef = useRef(eGridCell);
|
|
17
|
-
anchorRef.current = eGridCell;
|
|
18
15
|
const [isOpen, setOpen] = useState(false);
|
|
19
16
|
|
|
20
17
|
useEffect(() => {
|
|
@@ -23,12 +20,12 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(
|
|
|
23
20
|
|
|
24
21
|
const triggerSave = useCallback(
|
|
25
22
|
async (reason?: string) => {
|
|
26
|
-
if (reason == "cancel" || !save || (await
|
|
23
|
+
if (reason == "cancel" || !props.save || (updateValueRef.current && (await updateValueRef.current(props.save)))) {
|
|
27
24
|
setOpen(false);
|
|
28
25
|
stopEditing();
|
|
29
26
|
}
|
|
30
27
|
},
|
|
31
|
-
[
|
|
28
|
+
[props, stopEditing, updateValueRef],
|
|
32
29
|
);
|
|
33
30
|
|
|
34
31
|
const popoverWrapper = useCallback(
|
|
@@ -44,7 +41,6 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(
|
|
|
44
41
|
saveButtonRef={saveButtonRef}
|
|
45
42
|
menuClassName={"lui-menu"}
|
|
46
43
|
onClose={(event: { reason: string }) => triggerSave(event.reason).then()}
|
|
47
|
-
reposition={"initial"}
|
|
48
44
|
viewScroll={"auto"}
|
|
49
45
|
dontShrinkIfDirectionIsTop={true}
|
|
50
46
|
>
|
|
@@ -68,7 +64,7 @@ export const useGridPopoverHook = <RowType extends GridBaseRow>(
|
|
|
68
64
|
</>
|
|
69
65
|
);
|
|
70
66
|
},
|
|
71
|
-
[isOpen, saving, triggerSave],
|
|
67
|
+
[anchorRef, isOpen, saving, triggerSave],
|
|
72
68
|
);
|
|
73
69
|
|
|
74
70
|
return {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import "../../react-menu3/styles/index.scss";
|
|
2
2
|
|
|
3
|
-
import { MenuItem, MenuDivider, FocusableItem } from "@react-menu3";
|
|
3
|
+
import { MenuItem, MenuDivider, FocusableItem, MenuHeader } from "@react-menu3";
|
|
4
4
|
import { useCallback, useContext, useEffect, useRef, useState, KeyboardEvent } from "react";
|
|
5
5
|
import { GridBaseRow } from "../Grid";
|
|
6
6
|
import { ComponentLoadingWrapper } from "../ComponentLoadingWrapper";
|
|
7
7
|
import { GridContext } from "@contexts/GridContext";
|
|
8
8
|
import { delay } from "lodash-es";
|
|
9
9
|
import debounce from "debounce-promise";
|
|
10
|
-
import {
|
|
10
|
+
import { CellParams } from "../GridCell";
|
|
11
11
|
import { useGridPopoverHook } from "../GridPopoverHook";
|
|
12
12
|
|
|
13
13
|
export interface GridPopoutEditDropDownSelectedItem<RowType, ValueType> {
|
|
@@ -24,10 +24,14 @@ interface FinalSelectOption<ValueType> {
|
|
|
24
24
|
export const MenuSeparatorString = "_____MENU_SEPARATOR_____";
|
|
25
25
|
export const MenuSeparator = Object.freeze({ value: MenuSeparatorString });
|
|
26
26
|
|
|
27
|
+
export const MenuHeaderString = "_____MENU_HEADER_____";
|
|
28
|
+
export const MenuHeaderItem = (title: string) => {
|
|
29
|
+
return { label: title, value: MenuHeaderString };
|
|
30
|
+
};
|
|
31
|
+
|
|
27
32
|
export type SelectOption<ValueType> = ValueType | FinalSelectOption<ValueType>;
|
|
28
33
|
|
|
29
|
-
export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow, ValueType>
|
|
30
|
-
extends GenericCellEditorParams<RowType> {
|
|
34
|
+
export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow, ValueType> {
|
|
31
35
|
filtered?: "local" | "reload";
|
|
32
36
|
filterPlaceholder?: string;
|
|
33
37
|
onSelectedItem?: (props: GridPopoutEditDropDownSelectedItem<RowType, ValueType>) => Promise<void>;
|
|
@@ -36,12 +40,13 @@ export interface GridFormPopoutDropDownProps<RowType extends GridBaseRow, ValueT
|
|
|
36
40
|
| SelectOption<ValueType>[]
|
|
37
41
|
| ((selectedRows: RowType[], filter?: string) => Promise<SelectOption<ValueType>[]> | SelectOption<ValueType>[]);
|
|
38
42
|
optionsRequestCancel?: () => void;
|
|
43
|
+
maxRows?: number;
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(
|
|
47
|
+
_props: GridFormPopoutDropDownProps<RowType, ValueType>,
|
|
48
|
+
) => {
|
|
49
|
+
const props = _props as GridFormPopoutDropDownProps<RowType, ValueType> & CellParams<RowType>;
|
|
45
50
|
const { updatingCells, stopEditing } = useContext(GridContext);
|
|
46
51
|
|
|
47
52
|
const [filter, setFilter] = useState("");
|
|
@@ -55,8 +60,8 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
55
60
|
return await updatingCells({ selectedRows: props.selectedRows, field }, async (selectedRows) => {
|
|
56
61
|
const hasChanged = selectedRows.some((row) => row[field as keyof RowType] !== value);
|
|
57
62
|
if (hasChanged) {
|
|
58
|
-
if (
|
|
59
|
-
await
|
|
63
|
+
if (props.onSelectedItem) {
|
|
64
|
+
await props.onSelectedItem({ selectedRows, value });
|
|
60
65
|
} else {
|
|
61
66
|
selectedRows.forEach((row) => (row[field as keyof RowType] = value));
|
|
62
67
|
}
|
|
@@ -64,27 +69,27 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
64
69
|
return true;
|
|
65
70
|
});
|
|
66
71
|
},
|
|
67
|
-
[
|
|
72
|
+
[props, updatingCells],
|
|
68
73
|
);
|
|
69
74
|
|
|
70
75
|
const selectFilterHandler = useCallback(
|
|
71
76
|
async (value: string): Promise<boolean> => {
|
|
72
77
|
const field = props.field;
|
|
73
78
|
return await updatingCells({ selectedRows: props.selectedRows, field }, async (selectedRows) => {
|
|
74
|
-
if (
|
|
75
|
-
await
|
|
79
|
+
if (props.onSelectFilter) {
|
|
80
|
+
await props.onSelectFilter({ selectedRows, value });
|
|
76
81
|
}
|
|
77
82
|
return true;
|
|
78
83
|
});
|
|
79
84
|
},
|
|
80
|
-
[
|
|
85
|
+
[props, updatingCells],
|
|
81
86
|
);
|
|
82
87
|
|
|
83
88
|
// Load up options list if it's async function
|
|
84
89
|
useEffect(() => {
|
|
85
90
|
if (options || optionsInitialising.current) return;
|
|
86
91
|
optionsInitialising.current = true;
|
|
87
|
-
let optionsConf =
|
|
92
|
+
let optionsConf = props.options ?? [];
|
|
88
93
|
|
|
89
94
|
(async () => {
|
|
90
95
|
if (typeof optionsConf == "function") {
|
|
@@ -98,7 +103,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
98
103
|
return item;
|
|
99
104
|
}) as any as FinalSelectOption<ValueType>[];
|
|
100
105
|
|
|
101
|
-
if (
|
|
106
|
+
if (props.filtered) {
|
|
102
107
|
// This is needed otherwise when filter input is rendered and sets autofocus
|
|
103
108
|
// the mouse up of the double click edit triggers the cell to cancel editing
|
|
104
109
|
delay(() => setOptions(optionsList), 100);
|
|
@@ -107,11 +112,11 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
107
112
|
}
|
|
108
113
|
optionsInitialising.current = false;
|
|
109
114
|
})();
|
|
110
|
-
}, [filter, options,
|
|
115
|
+
}, [filter, options, props]);
|
|
111
116
|
|
|
112
|
-
// Local filtering
|
|
117
|
+
// Local filtering.
|
|
113
118
|
useEffect(() => {
|
|
114
|
-
if (
|
|
119
|
+
if (props.filtered == "local") {
|
|
115
120
|
if (options == null) return;
|
|
116
121
|
setFilteredValues(
|
|
117
122
|
options
|
|
@@ -126,7 +131,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
126
131
|
.filter((r) => r !== undefined),
|
|
127
132
|
);
|
|
128
133
|
}
|
|
129
|
-
}, [
|
|
134
|
+
}, [props.filtered, filter, options]);
|
|
130
135
|
|
|
131
136
|
const researchOnFilterChange = debounce(
|
|
132
137
|
useCallback(() => {
|
|
@@ -137,14 +142,14 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
137
142
|
|
|
138
143
|
const previousFilter = useRef<string>(filter);
|
|
139
144
|
|
|
140
|
-
// Reload filtering
|
|
145
|
+
// Reload filtering.
|
|
141
146
|
useEffect(() => {
|
|
142
|
-
if (previousFilter.current != filter &&
|
|
147
|
+
if (previousFilter.current != filter && props.filtered == "reload") {
|
|
143
148
|
previousFilter.current = filter;
|
|
144
|
-
|
|
149
|
+
props.optionsRequestCancel && props.optionsRequestCancel();
|
|
145
150
|
researchOnFilterChange().then();
|
|
146
151
|
}
|
|
147
|
-
}, [filter,
|
|
152
|
+
}, [filter, props, researchOnFilterChange]);
|
|
148
153
|
|
|
149
154
|
const onFilterKeyDown = useCallback(
|
|
150
155
|
async (e: KeyboardEvent) => {
|
|
@@ -154,7 +159,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
154
159
|
if (activeOptions.length == 1) {
|
|
155
160
|
await selectItemHandler(activeOptions[0].value);
|
|
156
161
|
stopEditing();
|
|
157
|
-
} else if (
|
|
162
|
+
} else if (props.onSelectFilter) {
|
|
158
163
|
await selectFilterHandler(filter);
|
|
159
164
|
stopEditing();
|
|
160
165
|
} else {
|
|
@@ -163,12 +168,16 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
163
168
|
}
|
|
164
169
|
}
|
|
165
170
|
},
|
|
166
|
-
[filteredValues, options, selectItemHandler, selectFilterHandler, stopEditing, filter,
|
|
171
|
+
[filteredValues, options, selectItemHandler, selectFilterHandler, stopEditing, filter, props],
|
|
167
172
|
);
|
|
168
173
|
|
|
174
|
+
const maxRowsStyles =
|
|
175
|
+
props.maxRows !== undefined ? { maxHeight: 62 + 34 * props.maxRows, overFlowY: "auto" } : undefined;
|
|
176
|
+
|
|
177
|
+
const { popoverWrapper } = useGridPopoverHook();
|
|
169
178
|
return popoverWrapper(
|
|
170
179
|
<>
|
|
171
|
-
{
|
|
180
|
+
{props.filtered && (
|
|
172
181
|
<>
|
|
173
182
|
<FocusableItem className={"filter-item"}>
|
|
174
183
|
{({ ref }: any) => (
|
|
@@ -179,7 +188,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
179
188
|
style={{ border: "0px" }}
|
|
180
189
|
ref={ref}
|
|
181
190
|
type="text"
|
|
182
|
-
placeholder={
|
|
191
|
+
placeholder={props.filterPlaceholder ?? "Placeholder"}
|
|
183
192
|
data-testid={"filteredMenu-free-text-input"}
|
|
184
193
|
defaultValue={filter}
|
|
185
194
|
onChange={(e) => setFilter(e.target.value.toLowerCase())}
|
|
@@ -192,11 +201,13 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
192
201
|
</>
|
|
193
202
|
)}
|
|
194
203
|
<ComponentLoadingWrapper loading={!options}>
|
|
195
|
-
|
|
204
|
+
<div style={maxRowsStyles}>
|
|
196
205
|
{options && options.length == filteredValues?.length && <MenuItem>[Empty]</MenuItem>}
|
|
197
206
|
{options?.map((item, index) =>
|
|
198
207
|
item.value === MenuSeparatorString ? (
|
|
199
208
|
<MenuDivider key={`$$divider_${index}`} />
|
|
209
|
+
) : item.value === MenuHeaderString ? (
|
|
210
|
+
<MenuHeader>{item.label}</MenuHeader>
|
|
200
211
|
) : filteredValues.includes(item.value) ? null : (
|
|
201
212
|
<MenuItem
|
|
202
213
|
key={`${props.field}-${index}`}
|
|
@@ -209,7 +220,7 @@ export const GridFormDropDown = <RowType extends GridBaseRow, ValueType>(props:
|
|
|
209
220
|
</MenuItem>
|
|
210
221
|
),
|
|
211
222
|
)}
|
|
212
|
-
|
|
223
|
+
</div>
|
|
213
224
|
</ComponentLoadingWrapper>
|
|
214
225
|
</>,
|
|
215
226
|
);
|
|
@@ -4,19 +4,18 @@ import { useCallback, useState } from "react";
|
|
|
4
4
|
import { GridBaseRow } from "../Grid";
|
|
5
5
|
import { TextInputFormatted } from "../../lui/TextInputFormatted";
|
|
6
6
|
import { bearingNumberParser, bearingStringValidator, convertDDToDMS } from "@utils/bearing";
|
|
7
|
-
import { GenericCellEditorParams, GridFormProps } from "../GridCell";
|
|
8
7
|
import { useGridPopoverHook } from "../GridPopoverHook";
|
|
8
|
+
import { CellParams } from "@components/GridCell";
|
|
9
9
|
|
|
10
|
-
export interface GridFormEditBearingProps<RowType extends GridBaseRow>
|
|
11
|
-
placeHolder
|
|
10
|
+
export interface GridFormEditBearingProps<RowType extends GridBaseRow> {
|
|
11
|
+
placeHolder?: string;
|
|
12
12
|
range?: (value: number | null) => string | null;
|
|
13
13
|
onSave?: (selectedRows: RowType[], value: number | null) => Promise<boolean>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export const GridFormEditBearing = <RowType extends GridBaseRow>(
|
|
17
|
-
const
|
|
16
|
+
export const GridFormEditBearing = <RowType extends GridBaseRow>(_props: GridFormEditBearingProps<RowType>) => {
|
|
17
|
+
const props = _props as GridFormEditBearingProps<RowType> & CellParams<RowType>;
|
|
18
18
|
const [value, setValue] = useState<string>(`${props.value ?? ""}`);
|
|
19
|
-
|
|
20
19
|
const save = useCallback(
|
|
21
20
|
async (selectedRows: RowType[]): Promise<boolean> => {
|
|
22
21
|
if (bearingStringValidator(value)) return false;
|
|
@@ -25,8 +24,9 @@ export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridForm
|
|
|
25
24
|
if (parsedValue === props.value) {
|
|
26
25
|
return true;
|
|
27
26
|
}
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
|
|
28
|
+
if (props.onSave) {
|
|
29
|
+
return await props.onSave(selectedRows, parsedValue);
|
|
30
30
|
} else {
|
|
31
31
|
const field = props.field;
|
|
32
32
|
if (field == null) {
|
|
@@ -37,9 +37,9 @@ export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridForm
|
|
|
37
37
|
}
|
|
38
38
|
return true;
|
|
39
39
|
},
|
|
40
|
-
[
|
|
40
|
+
[props, value],
|
|
41
41
|
);
|
|
42
|
-
const {
|
|
42
|
+
const { triggerSave, popoverWrapper } = useGridPopoverHook({ save });
|
|
43
43
|
|
|
44
44
|
return popoverWrapper(
|
|
45
45
|
<div className={"GridFormEditBearing-input Grid-popoverContainer"}>
|
|
@@ -50,13 +50,13 @@ export const GridFormEditBearing = <RowType extends GridBaseRow>(props: GridForm
|
|
|
50
50
|
}}
|
|
51
51
|
inputProps={{
|
|
52
52
|
autoFocus: true,
|
|
53
|
-
placeholder:
|
|
53
|
+
placeholder: props.placeHolder,
|
|
54
54
|
disabled: false,
|
|
55
55
|
maxLength: 16,
|
|
56
56
|
onKeyDown: async (e) => e.key === "Enter" && triggerSave().then(),
|
|
57
57
|
}}
|
|
58
|
-
formatted={bearingStringValidator(value,
|
|
59
|
-
error={bearingStringValidator(value,
|
|
58
|
+
formatted={bearingStringValidator(value, props.range) ? "?" : convertDDToDMS(bearingNumberParser(value))}
|
|
59
|
+
error={bearingStringValidator(value, props.range)}
|
|
60
60
|
/>
|
|
61
61
|
</div>,
|
|
62
62
|
);
|
|
@@ -1,28 +1,23 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
|
-
import { GenericCellEditorParams, GridFormProps } from "../GridCell";
|
|
3
|
-
import { ICellEditorParams } from "ag-grid-community";
|
|
4
2
|
import { ComponentLoadingWrapper } from "../ComponentLoadingWrapper";
|
|
5
3
|
import { GridBaseRow } from "../Grid";
|
|
6
4
|
import { useGridPopoverHook } from "../GridPopoverHook";
|
|
5
|
+
import { CellParams } from "@components/GridCell";
|
|
7
6
|
|
|
8
|
-
export interface GridFormMessageProps<RowType extends GridBaseRow>
|
|
9
|
-
message: (
|
|
10
|
-
selectedRows: RowType[],
|
|
11
|
-
cellEditorParams: ICellEditorParams,
|
|
12
|
-
) => Promise<string | JSX.Element> | string | JSX.Element;
|
|
7
|
+
export interface GridFormMessageProps<RowType extends GridBaseRow> {
|
|
8
|
+
message: (cellParams: CellParams<RowType>) => Promise<string | JSX.Element> | string | JSX.Element;
|
|
13
9
|
}
|
|
14
10
|
|
|
15
|
-
export const GridFormMessage = <RowType extends GridBaseRow>(
|
|
16
|
-
const
|
|
17
|
-
|
|
11
|
+
export const GridFormMessage = <RowType extends GridBaseRow>(_props: GridFormMessageProps<RowType>) => {
|
|
12
|
+
const props = _props as GridFormMessageProps<RowType> & CellParams<RowType>;
|
|
18
13
|
const [message, setMessage] = useState<string | JSX.Element | null>(null);
|
|
19
|
-
const { popoverWrapper } = useGridPopoverHook(
|
|
14
|
+
const { popoverWrapper } = useGridPopoverHook();
|
|
20
15
|
|
|
21
16
|
useEffect(() => {
|
|
22
17
|
(async () => {
|
|
23
|
-
setMessage(await
|
|
18
|
+
setMessage(await props.message(props));
|
|
24
19
|
})().then();
|
|
25
|
-
}, [
|
|
20
|
+
}, [props]);
|
|
26
21
|
|
|
27
22
|
return popoverWrapper(
|
|
28
23
|
<ComponentLoadingWrapper loading={message === null}>
|