@gridsuite/commons-ui 0.197.0 → 0.199.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/components/index.js +2 -1
- package/dist/components/network-modification-table/drag-forbidden-chip.d.ts +2 -0
- package/dist/components/network-modification-table/drag-forbidden-chip.js +39 -0
- package/dist/components/network-modification-table/index.js +2 -1
- package/dist/components/network-modification-table/network-modifications-table.js +16 -8
- package/dist/components/network-modification-table/renderers/select-cell.js +21 -32
- package/dist/components/network-modification-table/renderers/select-header-cell.js +1 -1
- package/dist/components/network-modification-table/use-modifications-drag-and-drop.d.ts +3 -3
- package/dist/components/network-modification-table/use-modifications-drag-and-drop.js +37 -14
- package/dist/components/network-modification-table/use-modifications-selection.d.ts +15 -0
- package/dist/components/network-modification-table/use-modifications-selection.js +80 -0
- package/dist/components/network-modification-table/utils.d.ts +1 -0
- package/dist/components/network-modification-table/utils.js +2 -0
- package/dist/index.js +2 -1
- package/dist/utils/types/network-modification-metadata.d.ts +1 -0
- package/package.json +1 -1
package/dist/components/index.js
CHANGED
|
@@ -256,7 +256,7 @@ import { SelectCell } from "./network-modification-table/renderers/select-cell.j
|
|
|
256
256
|
import { SelectHeaderCell } from "./network-modification-table/renderers/select-header-cell.js";
|
|
257
257
|
import { DragCloneRow } from "./network-modification-table/row/drag-row-clone.js";
|
|
258
258
|
import { ModificationRow } from "./network-modification-table/row/modification-row.js";
|
|
259
|
-
import { fetchSubModificationsForExpandedRows, findAllLoadedCompositeModifications, findModificationInTree, formatToComposedModification, isCompositeModification, mergeSubModificationsIntoTree, moveSubModificationInTree, updateModificationFieldInTree, updateSubModificationsOfACompositeInTree } from "./network-modification-table/utils.js";
|
|
259
|
+
import { MAX_COMPOSITE_NESTING_DEPTH, fetchSubModificationsForExpandedRows, findAllLoadedCompositeModifications, findModificationInTree, formatToComposedModification, isCompositeModification, mergeSubModificationsIntoTree, moveSubModificationInTree, updateModificationFieldInTree, updateSubModificationsOfACompositeInTree } from "./network-modification-table/utils.js";
|
|
260
260
|
export {
|
|
261
261
|
ACCURACY,
|
|
262
262
|
ACTIVE,
|
|
@@ -464,6 +464,7 @@ export {
|
|
|
464
464
|
MAP_BASE_MAP,
|
|
465
465
|
MAP_MANUAL_REFRESH,
|
|
466
466
|
MARGIN_CALCULATION_START_TIME,
|
|
467
|
+
MAX_COMPOSITE_NESTING_DEPTH,
|
|
467
468
|
MAX_ROWS_NUMBER,
|
|
468
469
|
MAX_VALUE_ALLOWED_FOR_LIMIT_REDUCTION,
|
|
469
470
|
MIN_VALUE_ALLOWED_FOR_LIMIT_REDUCTION,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const CHIP_ATTR = "data-drag-depth-chip";
|
|
2
|
+
const createDragForbiddenChip = ({ side, chipStyle, label, title }) => {
|
|
3
|
+
const chip = document.createElement("span");
|
|
4
|
+
chip.setAttribute(CHIP_ATTR, side);
|
|
5
|
+
chip.setAttribute("style", `${chipStyle}; ${side}: 0px`);
|
|
6
|
+
chip.textContent = label;
|
|
7
|
+
if (title) {
|
|
8
|
+
chip.title = title;
|
|
9
|
+
}
|
|
10
|
+
return chip;
|
|
11
|
+
};
|
|
12
|
+
const injectForbiddenChips = (container, rowEl, isMovingDown) => {
|
|
13
|
+
container.querySelectorAll(`[${CHIP_ATTR}]`).forEach((c) => c.remove());
|
|
14
|
+
const containerRect = container.getBoundingClientRect();
|
|
15
|
+
const rowRect = rowEl.getBoundingClientRect();
|
|
16
|
+
const shadowLineY = isMovingDown ? rowRect.bottom - containerRect.top + container.scrollTop : rowRect.top - containerRect.top + container.scrollTop;
|
|
17
|
+
const chipStyle = [
|
|
18
|
+
"position: absolute",
|
|
19
|
+
`top: ${shadowLineY}px`,
|
|
20
|
+
"transform: translateY(-50%)",
|
|
21
|
+
"display: flex",
|
|
22
|
+
"align-items: center",
|
|
23
|
+
"justify-content: center",
|
|
24
|
+
"height: 20px",
|
|
25
|
+
"min-width: 20px",
|
|
26
|
+
"padding: 0 6px",
|
|
27
|
+
"border-radius: 10px",
|
|
28
|
+
"font-size: 11px",
|
|
29
|
+
"background-color: #d32f2f",
|
|
30
|
+
"color: #ffffff",
|
|
31
|
+
"z-index: 10",
|
|
32
|
+
"box-shadow: 0 1px 3px rgba(0,0,0,0.3)"
|
|
33
|
+
].join("; ");
|
|
34
|
+
container.appendChild(createDragForbiddenChip({ side: "left", chipStyle, label: "✕" }));
|
|
35
|
+
};
|
|
36
|
+
export {
|
|
37
|
+
CHIP_ATTR,
|
|
38
|
+
injectForbiddenChips
|
|
39
|
+
};
|
|
@@ -10,7 +10,7 @@ import { SelectCell } from "./renderers/select-cell.js";
|
|
|
10
10
|
import { SelectHeaderCell } from "./renderers/select-header-cell.js";
|
|
11
11
|
import { DragCloneRow } from "./row/drag-row-clone.js";
|
|
12
12
|
import { ModificationRow } from "./row/modification-row.js";
|
|
13
|
-
import { fetchSubModificationsForExpandedRows, findAllLoadedCompositeModifications, findModificationInTree, formatToComposedModification, isCompositeModification, mergeSubModificationsIntoTree, moveSubModificationInTree, updateModificationFieldInTree, updateSubModificationsOfACompositeInTree } from "./utils.js";
|
|
13
|
+
import { MAX_COMPOSITE_NESTING_DEPTH, fetchSubModificationsForExpandedRows, findAllLoadedCompositeModifications, findModificationInTree, formatToComposedModification, isCompositeModification, mergeSubModificationsIntoTree, moveSubModificationInTree, updateModificationFieldInTree, updateSubModificationsOfACompositeInTree } from "./utils.js";
|
|
14
14
|
export {
|
|
15
15
|
AUTO_EXTENSIBLE_COLUMNS,
|
|
16
16
|
BASE_MODIFICATION_TABLE_COLUMNS,
|
|
@@ -23,6 +23,7 @@ export {
|
|
|
23
23
|
DepthBox,
|
|
24
24
|
DragCloneRow,
|
|
25
25
|
DragHandleCell,
|
|
26
|
+
MAX_COMPOSITE_NESTING_DEPTH,
|
|
26
27
|
MODIFICATION_ROW_HEIGHT,
|
|
27
28
|
ModificationRow,
|
|
28
29
|
NameCell,
|
|
@@ -7,6 +7,7 @@ import { useVirtualizer } from "@tanstack/react-virtual";
|
|
|
7
7
|
import { MODIFICATION_ROW_HEIGHT, networkModificationTableStyles, createHeaderCellStyle } from "./network-modification-table-styles.js";
|
|
8
8
|
import { AUTO_EXTENSIBLE_COLUMNS } from "./columns-definition.js";
|
|
9
9
|
import { useModificationsDragAndDrop } from "./use-modifications-drag-and-drop.js";
|
|
10
|
+
import { useModificationsSelection } from "./use-modifications-selection.js";
|
|
10
11
|
import { formatToComposedModification, mergeSubModificationsIntoTree, findAllLoadedCompositeModifications, fetchSubModificationsForExpandedRows, isCompositeModification } from "./utils.js";
|
|
11
12
|
import "@mui/icons-material";
|
|
12
13
|
import "react-intl";
|
|
@@ -33,11 +34,14 @@ function NetworkModificationsTable({
|
|
|
33
34
|
}) {
|
|
34
35
|
const theme = useTheme();
|
|
35
36
|
const containerRef = useRef(null);
|
|
36
|
-
const lastClickedIndex = useRef(null);
|
|
37
37
|
const [expanded, setExpanded] = useState({});
|
|
38
38
|
const [composedModifications, setComposedModifications] = useState(
|
|
39
39
|
formatToComposedModification(modifications)
|
|
40
40
|
);
|
|
41
|
+
const { rowSelection, onRowSelectionChange, lastClickedRowId, emitSelection } = useModificationsSelection({
|
|
42
|
+
modifications: composedModifications,
|
|
43
|
+
onRowSelected
|
|
44
|
+
});
|
|
41
45
|
const columns = useMemo(
|
|
42
46
|
() => createAllColumns(
|
|
43
47
|
isRowDragDisabled ?? false,
|
|
@@ -77,19 +81,23 @@ function NetworkModificationsTable({
|
|
|
77
81
|
const table = useReactTable({
|
|
78
82
|
data: composedModifications,
|
|
79
83
|
columns,
|
|
80
|
-
state: { expanded },
|
|
84
|
+
state: { expanded, rowSelection },
|
|
81
85
|
getCoreRowModel: getCoreRowModel(),
|
|
82
86
|
getExpandedRowModel: getExpandedRowModel(),
|
|
83
87
|
getSubRows: (row) => row.subModifications,
|
|
84
88
|
getRowId: (row) => row.uuid,
|
|
85
89
|
getRowCanExpand: (row) => isCompositeModification(row.original),
|
|
86
90
|
enableRowSelection: true,
|
|
87
|
-
enableSubRowSelection:
|
|
91
|
+
enableSubRowSelection: true,
|
|
88
92
|
enableExpanding: true,
|
|
89
93
|
onExpandedChange: handleExpandRow,
|
|
90
|
-
|
|
94
|
+
onRowSelectionChange,
|
|
95
|
+
meta: { lastClickedRowId, onRowSelected }
|
|
91
96
|
});
|
|
92
|
-
const { rows } = table.getRowModel();
|
|
97
|
+
const { rows, flatRows } = table.getRowModel();
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
emitSelection(flatRows);
|
|
100
|
+
}, [rowSelection, flatRows, emitSelection]);
|
|
93
101
|
const virtualizer = useVirtualizer({
|
|
94
102
|
count: rows.length,
|
|
95
103
|
getScrollElement: () => containerRef.current,
|
|
@@ -98,7 +106,7 @@ function NetworkModificationsTable({
|
|
|
98
106
|
});
|
|
99
107
|
const virtualItems = virtualizer.getVirtualItems();
|
|
100
108
|
const { handleDragUpdate, handleDragEnd, renderClone } = useModificationsDragAndDrop({
|
|
101
|
-
|
|
109
|
+
table,
|
|
102
110
|
containerRef,
|
|
103
111
|
composedModifications,
|
|
104
112
|
setComposedModifications,
|
|
@@ -109,8 +117,8 @@ function NetworkModificationsTable({
|
|
|
109
117
|
useEffect(() => {
|
|
110
118
|
table.resetRowSelection();
|
|
111
119
|
table.resetExpanded();
|
|
112
|
-
|
|
113
|
-
}, [table]);
|
|
120
|
+
lastClickedRowId.current = null;
|
|
121
|
+
}, [lastClickedRowId, table, currentNodeId]);
|
|
114
122
|
useEffect(() => {
|
|
115
123
|
if (highlightedModificationUuid && containerRef.current) {
|
|
116
124
|
const rowIndex = rows.findIndex((row) => row.original.uuid === highlightedModificationUuid);
|
|
@@ -1,54 +1,43 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback
|
|
2
|
+
import { useCallback } from "react";
|
|
3
3
|
import { Checkbox } from "@mui/material";
|
|
4
4
|
import { networkModificationTableStyles } from "../network-modification-table-styles.js";
|
|
5
|
+
function toggleRange(rows, from, to, targetSelected) {
|
|
6
|
+
const [start, end] = from <= to ? [from, to] : [to, from];
|
|
7
|
+
rows.slice(start, end + 1).forEach((r) => {
|
|
8
|
+
if (r.getCanSelect()) {
|
|
9
|
+
r.toggleSelected(targetSelected);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}
|
|
5
13
|
function SelectCell({ row, table }) {
|
|
6
14
|
const { meta } = table.options;
|
|
15
|
+
const isSelected = row.getIsSelected();
|
|
16
|
+
const isIndeterminate = !isSelected && row.getIsSomeSelected();
|
|
7
17
|
const handleChange = useCallback(
|
|
8
18
|
(event) => {
|
|
9
19
|
const rows = table.getRowModel().flatRows;
|
|
10
20
|
const currentIndex = rows.indexOf(row);
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
rows.slice(from, to + 1).forEach((r) => {
|
|
17
|
-
if (r.getCanSelect()) {
|
|
18
|
-
r.toggleSelected(!isRowSelected);
|
|
19
|
-
if (isRowSelected) {
|
|
20
|
-
delete nextSelection[r.id];
|
|
21
|
-
} else {
|
|
22
|
-
nextSelection[r.id] = true;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
});
|
|
21
|
+
const anchorRowId = meta?.lastClickedRowId.current;
|
|
22
|
+
const anchorIndex = anchorRowId == null ? null : rows.findIndex((candidate) => candidate.id === anchorRowId);
|
|
23
|
+
const targetSelected = !isSelected;
|
|
24
|
+
if (event.shiftKey && anchorIndex != null && anchorIndex !== -1) {
|
|
25
|
+
toggleRange(rows, anchorIndex, currentIndex, targetSelected);
|
|
26
26
|
} else {
|
|
27
|
-
row.toggleSelected();
|
|
28
|
-
if (row.getIsSelected()) {
|
|
29
|
-
delete nextSelection[row.id];
|
|
30
|
-
} else {
|
|
31
|
-
nextSelection[row.id] = true;
|
|
32
|
-
}
|
|
27
|
+
row.toggleSelected(targetSelected);
|
|
33
28
|
}
|
|
34
29
|
if (meta) {
|
|
35
|
-
meta.
|
|
36
|
-
const selectedRows = rows.filter((r) => nextSelection[r.id]).map((r) => r.original);
|
|
37
|
-
meta.onRowSelected?.(selectedRows);
|
|
30
|
+
meta.lastClickedRowId.current = row.id;
|
|
38
31
|
}
|
|
39
32
|
},
|
|
40
|
-
[table, row, meta]
|
|
41
|
-
);
|
|
42
|
-
const hasPartiallySelectedSubRows = useMemo(
|
|
43
|
-
() => row.subRows.some((subRow) => subRow.getIsSelected()) && !row.getIsSelected(),
|
|
44
|
-
[row]
|
|
33
|
+
[table, row, meta, isSelected]
|
|
45
34
|
);
|
|
46
35
|
return /* @__PURE__ */ jsx(
|
|
47
36
|
Checkbox,
|
|
48
37
|
{
|
|
49
38
|
size: "small",
|
|
50
|
-
checked:
|
|
51
|
-
indeterminate:
|
|
39
|
+
checked: isSelected,
|
|
40
|
+
indeterminate: isIndeterminate,
|
|
52
41
|
disabled: !row.getCanSelect(),
|
|
53
42
|
onClick: handleChange,
|
|
54
43
|
sx: networkModificationTableStyles.selectCheckBox
|
|
@@ -7,7 +7,7 @@ function SelectHeaderCell({ table }) {
|
|
|
7
7
|
if (meta) {
|
|
8
8
|
const nextSelectedRows = table.getIsAllRowsSelected() ? [] : table.getCoreRowModel().rows.map((r) => r.original);
|
|
9
9
|
meta.onRowSelected?.(nextSelectedRows);
|
|
10
|
-
meta.
|
|
10
|
+
meta.lastClickedRowId.current = null;
|
|
11
11
|
}
|
|
12
12
|
table.toggleAllRowsSelected();
|
|
13
13
|
}, [table]);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { default as React, JSX, RefObject } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Table } from '@tanstack/react-table';
|
|
3
3
|
import { DraggableProvided, DraggableRubric, DraggableStateSnapshot, DragUpdate, DropResult } from '@hello-pangea/dnd';
|
|
4
4
|
import { UUID } from 'node:crypto';
|
|
5
5
|
import { ComposedModificationMetadata } from '../../utils';
|
|
6
6
|
interface UseModificationsDragAndDropParams {
|
|
7
|
-
|
|
7
|
+
table: Table<ComposedModificationMetadata>;
|
|
8
8
|
containerRef: RefObject<HTMLDivElement | null>;
|
|
9
9
|
composedModifications: ComposedModificationMetadata[];
|
|
10
10
|
setComposedModifications: React.Dispatch<React.SetStateAction<ComposedModificationMetadata[]>>;
|
|
@@ -17,5 +17,5 @@ interface UseModificationsDragAndDropReturn {
|
|
|
17
17
|
handleDragEnd: (result: DropResult) => void;
|
|
18
18
|
renderClone: (provided: DraggableProvided, snapshot: DraggableStateSnapshot, rubric: DraggableRubric) => JSX.Element;
|
|
19
19
|
}
|
|
20
|
-
export declare const useModificationsDragAndDrop: ({
|
|
20
|
+
export declare const useModificationsDragAndDrop: ({ table, containerRef, composedModifications, setComposedModifications, onDragEnd, studyUuid, currentNodeUuid, }: UseModificationsDragAndDropParams) => UseModificationsDragAndDropReturn;
|
|
21
21
|
export {};
|
|
@@ -7,12 +7,13 @@ import "@hello-pangea/dnd";
|
|
|
7
7
|
import "react-intl";
|
|
8
8
|
import "./columns-definition.js";
|
|
9
9
|
import { DROP_FORBIDDEN_INDICATOR_BOTTOM, DROP_FORBIDDEN_INDICATOR_TOP, DROP_INDICATOR_BOTTOM, DROP_INDICATOR_TOP } from "./network-modification-table-styles.js";
|
|
10
|
-
import {
|
|
10
|
+
import { isCompositeModification, MAX_COMPOSITE_NESTING_DEPTH, findModificationInTree, moveSubModificationInTree } from "./utils.js";
|
|
11
11
|
import "../../utils/conversionUtils.js";
|
|
12
12
|
import { snackWithFallback } from "../../utils/error.js";
|
|
13
13
|
import "../../utils/types/equipmentType.js";
|
|
14
14
|
import "@mui/icons-material";
|
|
15
15
|
import "../../utils/yupConfig.js";
|
|
16
|
+
import { injectForbiddenChips, CHIP_ATTR } from "./drag-forbidden-chip.js";
|
|
16
17
|
import { changeCompositeSubModificationOrder, changeNetworkModificationOrder } from "../../services/networkModification.js";
|
|
17
18
|
import "localized-countries";
|
|
18
19
|
import "localized-countries/data/fr";
|
|
@@ -23,13 +24,7 @@ const clearRowDragIndicators = (container) => {
|
|
|
23
24
|
rowElements?.forEach((rowElement) => {
|
|
24
25
|
rowElement.style.boxShadow = "";
|
|
25
26
|
});
|
|
26
|
-
};
|
|
27
|
-
const isDropForbidden = (sourceRow, targetRow) => {
|
|
28
|
-
const isDraggingDown = targetRow.index > sourceRow.index;
|
|
29
|
-
if (isCompositeModification(sourceRow.original) && (isCompositeModification(targetRow.original) && targetRow.getIsExpanded() && isDraggingDown || isCompositeModification(targetRow.getParentRow()?.original))) {
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
return !!(isCompositeModification(sourceRow.original) && findModificationInTree(targetRow.original.uuid, [sourceRow.original]));
|
|
27
|
+
container?.querySelectorAll(`[${CHIP_ATTR}]`).forEach((chip) => chip.remove());
|
|
33
28
|
};
|
|
34
29
|
function getTargetCompositeUuid(droppingIntoExpandedComposite, targetRow) {
|
|
35
30
|
if (droppingIntoExpandedComposite) {
|
|
@@ -47,7 +42,7 @@ function getContainerShadow(forbidden, isMovingDown) {
|
|
|
47
42
|
return isMovingDown ? DROP_INDICATOR_BOTTOM : DROP_INDICATOR_TOP;
|
|
48
43
|
}
|
|
49
44
|
const useModificationsDragAndDrop = ({
|
|
50
|
-
|
|
45
|
+
table,
|
|
51
46
|
containerRef,
|
|
52
47
|
composedModifications,
|
|
53
48
|
setComposedModifications,
|
|
@@ -56,6 +51,30 @@ const useModificationsDragAndDrop = ({
|
|
|
56
51
|
currentNodeUuid = void 0
|
|
57
52
|
}) => {
|
|
58
53
|
const { snackError } = useSnackMessage();
|
|
54
|
+
const { rows } = table.getRowModel();
|
|
55
|
+
const computeTargetDepth = useCallback(
|
|
56
|
+
(sourceRow, targetRow) => {
|
|
57
|
+
const sourceRowIndex = table.getRowModel().flatRows.findIndex((row) => {
|
|
58
|
+
return row.id === sourceRow.id;
|
|
59
|
+
});
|
|
60
|
+
const targetRowIndex = table.getRowModel().flatRows.findIndex((row) => {
|
|
61
|
+
return row.id === targetRow.id;
|
|
62
|
+
});
|
|
63
|
+
const isDraggingDown = sourceRowIndex < targetRowIndex;
|
|
64
|
+
return isCompositeModification(targetRow.original) && targetRow.getIsExpanded() && isDraggingDown ? targetRow.depth + 1 : targetRow.depth;
|
|
65
|
+
},
|
|
66
|
+
[table]
|
|
67
|
+
);
|
|
68
|
+
const isDropForbidden = useCallback(
|
|
69
|
+
(sourceRow, targetRow) => {
|
|
70
|
+
if (isCompositeModification(sourceRow.original)) {
|
|
71
|
+
const targetDepth = computeTargetDepth(sourceRow, targetRow);
|
|
72
|
+
return (sourceRow.original.maxDepth ?? 0) + targetDepth > MAX_COMPOSITE_NESTING_DEPTH || !!(isCompositeModification(sourceRow.original) && findModificationInTree(targetRow.original.uuid, [sourceRow.original]));
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
},
|
|
76
|
+
[computeTargetDepth]
|
|
77
|
+
);
|
|
59
78
|
const handleDragUpdate = useCallback(
|
|
60
79
|
(update) => {
|
|
61
80
|
clearRowDragIndicators(containerRef.current);
|
|
@@ -72,8 +91,11 @@ const useModificationsDragAndDrop = ({
|
|
|
72
91
|
const forbidden = isDropForbidden(sourceRow, targetRow);
|
|
73
92
|
const isMovingDown = destination.index > source.index;
|
|
74
93
|
el.style.boxShadow = getContainerShadow(forbidden, isMovingDown);
|
|
94
|
+
if (forbidden && containerRef.current) {
|
|
95
|
+
injectForbiddenChips(containerRef.current, el, isMovingDown);
|
|
96
|
+
}
|
|
75
97
|
},
|
|
76
|
-
[
|
|
98
|
+
[containerRef, isDropForbidden, rows]
|
|
77
99
|
);
|
|
78
100
|
const handleDragEndComposite = useCallback(
|
|
79
101
|
(sourceRow, targetRow, droppingIntoExpandedComposite, isDraggingDown) => {
|
|
@@ -151,12 +173,13 @@ const useModificationsDragAndDrop = ({
|
|
|
151
173
|
containerRef,
|
|
152
174
|
onDragEnd,
|
|
153
175
|
rows,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
snackError,
|
|
176
|
+
isDropForbidden,
|
|
177
|
+
handleDragEndComposite,
|
|
157
178
|
composedModifications,
|
|
179
|
+
currentNodeUuid,
|
|
158
180
|
setComposedModifications,
|
|
159
|
-
|
|
181
|
+
studyUuid,
|
|
182
|
+
snackError
|
|
160
183
|
]
|
|
161
184
|
);
|
|
162
185
|
const renderClone = useCallback(
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
import { Row, RowSelectionState, Updater } from '@tanstack/react-table';
|
|
3
|
+
import { ComposedModificationMetadata } from '../../utils';
|
|
4
|
+
interface UseModificationsSelectionParams {
|
|
5
|
+
modifications: ComposedModificationMetadata[];
|
|
6
|
+
onRowSelected: (selectedRows: ComposedModificationMetadata[]) => void;
|
|
7
|
+
}
|
|
8
|
+
interface UseModificationsSelectionResult {
|
|
9
|
+
rowSelection: RowSelectionState;
|
|
10
|
+
onRowSelectionChange: (updater: Updater<RowSelectionState>) => void;
|
|
11
|
+
lastClickedRowId: RefObject<string | null>;
|
|
12
|
+
emitSelection: (flatRows: Row<ComposedModificationMetadata>[]) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare function useModificationsSelection({ modifications, onRowSelected, }: UseModificationsSelectionParams): UseModificationsSelectionResult;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useState, useRef, useCallback, useEffect } from "react";
|
|
2
|
+
function normalizeCompositeSelection(rawSelection, roots) {
|
|
3
|
+
const next = { ...rawSelection };
|
|
4
|
+
const visit = (node) => {
|
|
5
|
+
const children = node.subModifications;
|
|
6
|
+
if (!children || children.length === 0) {
|
|
7
|
+
return next[node.uuid];
|
|
8
|
+
}
|
|
9
|
+
const everyChildSelected = children.every((child) => visit(child));
|
|
10
|
+
if (everyChildSelected) {
|
|
11
|
+
next[node.uuid] = true;
|
|
12
|
+
} else {
|
|
13
|
+
delete next[node.uuid];
|
|
14
|
+
}
|
|
15
|
+
return everyChildSelected;
|
|
16
|
+
};
|
|
17
|
+
roots.forEach((root) => visit(root));
|
|
18
|
+
return next;
|
|
19
|
+
}
|
|
20
|
+
function collectSelection(flatRows) {
|
|
21
|
+
const acc = [];
|
|
22
|
+
let skipBelowDepth = -1;
|
|
23
|
+
flatRows.forEach((row) => {
|
|
24
|
+
if (skipBelowDepth >= 0 && row.depth > skipBelowDepth) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
skipBelowDepth = -1;
|
|
28
|
+
if (row.getIsSelected()) {
|
|
29
|
+
acc.push(row.original);
|
|
30
|
+
skipBelowDepth = row.depth;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return acc;
|
|
34
|
+
}
|
|
35
|
+
function propagateSelectionToLoadedDescendants(selection, roots) {
|
|
36
|
+
let next = selection;
|
|
37
|
+
let mutated = false;
|
|
38
|
+
const visit = (node, ancestorSelected) => {
|
|
39
|
+
const effectiveSelected = ancestorSelected || next[node.uuid];
|
|
40
|
+
if (effectiveSelected && !next[node.uuid]) {
|
|
41
|
+
if (!mutated) {
|
|
42
|
+
next = { ...selection };
|
|
43
|
+
mutated = true;
|
|
44
|
+
}
|
|
45
|
+
next[node.uuid] = true;
|
|
46
|
+
}
|
|
47
|
+
node.subModifications?.forEach((child) => visit(child, effectiveSelected));
|
|
48
|
+
};
|
|
49
|
+
roots.forEach((root) => visit(root, false));
|
|
50
|
+
return mutated ? next : selection;
|
|
51
|
+
}
|
|
52
|
+
function useModificationsSelection({
|
|
53
|
+
modifications,
|
|
54
|
+
onRowSelected
|
|
55
|
+
}) {
|
|
56
|
+
const [rowSelection, setRowSelection] = useState({});
|
|
57
|
+
const lastClickedRowId = useRef(null);
|
|
58
|
+
const onRowSelectionChange = useCallback(
|
|
59
|
+
(updater) => {
|
|
60
|
+
setRowSelection((prev) => {
|
|
61
|
+
const raw = typeof updater === "function" ? updater(prev) : updater;
|
|
62
|
+
return normalizeCompositeSelection(raw, modifications);
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
[modifications]
|
|
66
|
+
);
|
|
67
|
+
const emitSelection = useCallback(
|
|
68
|
+
(flatRows) => {
|
|
69
|
+
onRowSelected(collectSelection(flatRows));
|
|
70
|
+
},
|
|
71
|
+
[onRowSelected]
|
|
72
|
+
);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
setRowSelection((prev) => propagateSelectionToLoadedDescendants(prev, modifications));
|
|
75
|
+
}, [modifications]);
|
|
76
|
+
return { rowSelection, onRowSelectionChange, lastClickedRowId, emitSelection };
|
|
77
|
+
}
|
|
78
|
+
export {
|
|
79
|
+
useModificationsSelection
|
|
80
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Dispatch, SetStateAction } from 'react';
|
|
2
2
|
import { UUID } from 'node:crypto';
|
|
3
3
|
import { ComposedModificationMetadata, NetworkModificationMetadata } from '../../utils';
|
|
4
|
+
export declare const MAX_COMPOSITE_NESTING_DEPTH = 5;
|
|
4
5
|
export declare const formatToComposedModification: (modifications: NetworkModificationMetadata[]) => ComposedModificationMetadata[];
|
|
5
6
|
export declare function isCompositeModification(modification: ComposedModificationMetadata | undefined): boolean;
|
|
6
7
|
/**
|
|
@@ -5,6 +5,7 @@ import "react/jsx-runtime";
|
|
|
5
5
|
import "@mui/icons-material";
|
|
6
6
|
import "../../utils/yupConfig.js";
|
|
7
7
|
import { getNetworkModificationsFromComposite } from "../../services/networkModification.js";
|
|
8
|
+
const MAX_COMPOSITE_NESTING_DEPTH = 5;
|
|
8
9
|
const formatToComposedModification = (modifications) => {
|
|
9
10
|
return modifications.map((modification) => ({ ...modification, subModifications: [] }));
|
|
10
11
|
};
|
|
@@ -152,6 +153,7 @@ function fetchSubModificationsForExpandedRows(expandedIds, mods, setMods, force
|
|
|
152
153
|
});
|
|
153
154
|
}
|
|
154
155
|
export {
|
|
156
|
+
MAX_COMPOSITE_NESTING_DEPTH,
|
|
155
157
|
fetchSubModificationsForExpandedRows,
|
|
156
158
|
findAllLoadedCompositeModifications,
|
|
157
159
|
findModificationInTree,
|
package/dist/index.js
CHANGED
|
@@ -309,7 +309,7 @@ import { SelectCell } from "./components/network-modification-table/renderers/se
|
|
|
309
309
|
import { SelectHeaderCell } from "./components/network-modification-table/renderers/select-header-cell.js";
|
|
310
310
|
import { DragCloneRow } from "./components/network-modification-table/row/drag-row-clone.js";
|
|
311
311
|
import { ModificationRow } from "./components/network-modification-table/row/modification-row.js";
|
|
312
|
-
import { fetchSubModificationsForExpandedRows, findAllLoadedCompositeModifications, findModificationInTree, formatToComposedModification, isCompositeModification, mergeSubModificationsIntoTree, moveSubModificationInTree, updateModificationFieldInTree, updateSubModificationsOfACompositeInTree } from "./components/network-modification-table/utils.js";
|
|
312
|
+
import { MAX_COMPOSITE_NESTING_DEPTH, fetchSubModificationsForExpandedRows, findAllLoadedCompositeModifications, findModificationInTree, formatToComposedModification, isCompositeModification, mergeSubModificationsIntoTree, moveSubModificationInTree, updateModificationFieldInTree, updateSubModificationsOfACompositeInTree } from "./components/network-modification-table/utils.js";
|
|
313
313
|
import { useStateBoolean } from "./hooks/customStates/useStateBoolean.js";
|
|
314
314
|
import { useStateNumber } from "./hooks/customStates/useStateNumber.js";
|
|
315
315
|
import { useModificationLabelComputer } from "./hooks/useModificationLabelComputer.js";
|
|
@@ -651,6 +651,7 @@ export {
|
|
|
651
651
|
MAP_MANUAL_REFRESH,
|
|
652
652
|
MARGIN_CALCULATION_START_TIME,
|
|
653
653
|
MAX_CHAR_DESCRIPTION,
|
|
654
|
+
MAX_COMPOSITE_NESTING_DEPTH,
|
|
654
655
|
MAX_ROWS_NUMBER,
|
|
655
656
|
MAX_VALUE_ALLOWED_FOR_LIMIT_REDUCTION,
|
|
656
657
|
MEGA_VAR,
|