@gridsuite/commons-ui 0.195.0 → 0.196.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.d.ts +1 -0
- package/dist/components/index.js +53 -0
- package/dist/components/network-modification-table/columns-definition.d.ts +26 -0
- package/dist/components/network-modification-table/columns-definition.js +36 -0
- package/dist/components/network-modification-table/index.d.ts +13 -0
- package/dist/components/network-modification-table/index.js +55 -0
- package/dist/components/network-modification-table/network-modification-table-styles.d.ts +210 -0
- package/dist/components/network-modification-table/network-modification-table-styles.js +333 -0
- package/dist/components/network-modification-table/network-modifications-table.d.ts +20 -0
- package/dist/components/network-modification-table/network-modifications-table.js +166 -0
- package/dist/components/network-modification-table/renderers/depth-box.d.ts +6 -0
- package/dist/components/network-modification-table/renderers/depth-box.js +21 -0
- package/dist/components/network-modification-table/renderers/drag-handle-cell.d.ts +5 -0
- package/dist/components/network-modification-table/renderers/drag-handle-cell.js +10 -0
- package/dist/components/network-modification-table/renderers/index.d.ts +12 -0
- package/dist/components/network-modification-table/renderers/index.js +14 -0
- package/dist/components/network-modification-table/renderers/name-cell.d.ts +7 -0
- package/dist/components/network-modification-table/renderers/name-cell.js +84 -0
- package/dist/components/network-modification-table/renderers/network-modification-node-editor-name-header.d.ts +14 -0
- package/dist/components/network-modification-table/renderers/network-modification-node-editor-name-header.js +40 -0
- package/dist/components/network-modification-table/renderers/select-cell.d.ts +8 -0
- package/dist/components/network-modification-table/renderers/select-cell.js +60 -0
- package/dist/components/network-modification-table/renderers/select-header-cell.d.ts +7 -0
- package/dist/components/network-modification-table/renderers/select-header-cell.js +26 -0
- package/dist/components/network-modification-table/row/drag-row-clone.d.ts +7 -0
- package/dist/components/network-modification-table/row/drag-row-clone.js +35 -0
- package/dist/components/network-modification-table/row/index.d.ts +8 -0
- package/dist/components/network-modification-table/row/index.js +6 -0
- package/dist/components/network-modification-table/row/modification-row.d.ts +12 -0
- package/dist/components/network-modification-table/row/modification-row.js +117 -0
- package/dist/components/network-modification-table/use-modifications-drag-and-drop.d.ts +21 -0
- package/dist/components/network-modification-table/use-modifications-drag-and-drop.js +170 -0
- package/dist/components/network-modification-table/utils.d.ts +40 -0
- package/dist/components/network-modification-table/utils.js +164 -0
- package/dist/hooks/useModificationLabelComputer.d.ts +1 -12
- package/dist/index.js +59 -1
- package/dist/module-tanstack.d.js +1 -0
- package/dist/services/index.js +6 -1
- package/dist/services/networkModification.d.ts +21 -0
- package/dist/services/networkModification.js +34 -0
- package/dist/utils/types/index.d.ts +1 -0
- package/dist/utils/types/network-modification-metadata.d.ts +15 -0
- package/dist/utils/types/network-modification-metadata.js +1 -0
- package/dist/utils/types/network-modification-types.d.ts +5 -6
- package/package.json +3 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
*/
|
|
7
|
+
export interface NetworkModificationEditorNameHeaderProps {
|
|
8
|
+
modificationCount?: number;
|
|
9
|
+
notificationMessageId?: string;
|
|
10
|
+
isFetchingModifications: boolean;
|
|
11
|
+
isImpactedByNotification: () => boolean;
|
|
12
|
+
pendingState: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function NetworkModificationEditorNameHeader({ modificationCount, isFetchingModifications, isImpactedByNotification, notificationMessageId, pendingState, }: Readonly<NetworkModificationEditorNameHeaderProps>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, CircularProgress, Typography } from "@mui/material";
|
|
3
|
+
import { FormattedMessage } from "react-intl";
|
|
4
|
+
import { networkModificationTableStyles } from "../network-modification-table-styles.js";
|
|
5
|
+
function NetworkModificationEditorNameHeader({
|
|
6
|
+
modificationCount,
|
|
7
|
+
isFetchingModifications,
|
|
8
|
+
isImpactedByNotification,
|
|
9
|
+
notificationMessageId,
|
|
10
|
+
pendingState
|
|
11
|
+
}) {
|
|
12
|
+
if (isImpactedByNotification() && notificationMessageId) {
|
|
13
|
+
return /* @__PURE__ */ jsxs(Box, { sx: networkModificationTableStyles.modificationNameHeader, children: [
|
|
14
|
+
/* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.icon, children: /* @__PURE__ */ jsx(CircularProgress, { size: "1em", sx: networkModificationTableStyles.modificationCircularProgress }) }),
|
|
15
|
+
/* @__PURE__ */ jsx(Typography, { noWrap: true, children: /* @__PURE__ */ jsx(FormattedMessage, { id: notificationMessageId }) })
|
|
16
|
+
] });
|
|
17
|
+
}
|
|
18
|
+
if (isFetchingModifications) {
|
|
19
|
+
return /* @__PURE__ */ jsxs(Box, { sx: networkModificationTableStyles.modificationNameHeader, children: [
|
|
20
|
+
/* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.icon, children: /* @__PURE__ */ jsx(CircularProgress, { size: "1em", sx: networkModificationTableStyles.modificationCircularProgress }) }),
|
|
21
|
+
/* @__PURE__ */ jsx(Typography, { noWrap: true, children: /* @__PURE__ */ jsx(FormattedMessage, { id: "network_modifications.modifications" }) })
|
|
22
|
+
] });
|
|
23
|
+
}
|
|
24
|
+
return /* @__PURE__ */ jsxs(Box, { sx: networkModificationTableStyles.modificationNameHeader, children: [
|
|
25
|
+
pendingState && /* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.icon, children: /* @__PURE__ */ jsx(CircularProgress, { size: "1em", sx: networkModificationTableStyles.modificationCircularProgress }) }),
|
|
26
|
+
/* @__PURE__ */ jsx(Typography, { noWrap: true, children: /* @__PURE__ */ jsx(
|
|
27
|
+
FormattedMessage,
|
|
28
|
+
{
|
|
29
|
+
id: "network_modifications.modificationsCount",
|
|
30
|
+
values: {
|
|
31
|
+
count: modificationCount ?? "",
|
|
32
|
+
hide: pendingState
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
) })
|
|
36
|
+
] });
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
NetworkModificationEditorNameHeader
|
|
40
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Row, Table } from '@tanstack/react-table';
|
|
2
|
+
import { ComposedModificationMetadata } from '../../../utils';
|
|
3
|
+
interface SelectCellRendererProps {
|
|
4
|
+
row: Row<ComposedModificationMetadata>;
|
|
5
|
+
table: Table<ComposedModificationMetadata>;
|
|
6
|
+
}
|
|
7
|
+
export declare function SelectCell({ row, table }: Readonly<SelectCellRendererProps>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useMemo } from "react";
|
|
3
|
+
import { Checkbox } from "@mui/material";
|
|
4
|
+
import { networkModificationTableStyles } from "../network-modification-table-styles.js";
|
|
5
|
+
function SelectCell({ row, table }) {
|
|
6
|
+
const { meta } = table.options;
|
|
7
|
+
const handleChange = useCallback(
|
|
8
|
+
(event) => {
|
|
9
|
+
const rows = table.getRowModel().flatRows;
|
|
10
|
+
const currentIndex = rows.indexOf(row);
|
|
11
|
+
const nextSelection = { ...table.getState().rowSelection };
|
|
12
|
+
if (event.shiftKey && meta?.lastClickedIndex.current !== null && meta?.lastClickedIndex.current !== void 0) {
|
|
13
|
+
const lastIndex = meta.lastClickedIndex.current;
|
|
14
|
+
const [from, to] = lastIndex < currentIndex ? [lastIndex, currentIndex] : [currentIndex, lastIndex];
|
|
15
|
+
const isRowSelected = row.getIsSelected();
|
|
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
|
+
});
|
|
26
|
+
} else {
|
|
27
|
+
row.toggleSelected();
|
|
28
|
+
if (row.getIsSelected()) {
|
|
29
|
+
delete nextSelection[row.id];
|
|
30
|
+
} else {
|
|
31
|
+
nextSelection[row.id] = true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (meta) {
|
|
35
|
+
meta.lastClickedIndex.current = currentIndex;
|
|
36
|
+
const selectedRows = rows.filter((r) => nextSelection[r.id]).map((r) => r.original);
|
|
37
|
+
meta.onRowSelected?.(selectedRows);
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
[table, row, meta]
|
|
41
|
+
);
|
|
42
|
+
const hasPartiallySelectedSubRows = useMemo(
|
|
43
|
+
() => row.subRows.some((subRow) => subRow.getIsSelected()) && !row.getIsSelected(),
|
|
44
|
+
[row]
|
|
45
|
+
);
|
|
46
|
+
return /* @__PURE__ */ jsx(
|
|
47
|
+
Checkbox,
|
|
48
|
+
{
|
|
49
|
+
size: "small",
|
|
50
|
+
checked: row.getIsSelected(),
|
|
51
|
+
indeterminate: hasPartiallySelectedSubRows,
|
|
52
|
+
disabled: !row.getCanSelect(),
|
|
53
|
+
onClick: handleChange,
|
|
54
|
+
sx: networkModificationTableStyles.selectCheckBox
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
SelectCell
|
|
60
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Table } from '@tanstack/react-table';
|
|
2
|
+
import { ComposedModificationMetadata } from '../../../utils';
|
|
3
|
+
interface SelectHeaderCellProps {
|
|
4
|
+
table: Table<ComposedModificationMetadata>;
|
|
5
|
+
}
|
|
6
|
+
export declare function SelectHeaderCell({ table }: Readonly<SelectHeaderCellProps>): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
import { Checkbox } from "@mui/material";
|
|
4
|
+
function SelectHeaderCell({ table }) {
|
|
5
|
+
const handleClick = useCallback(() => {
|
|
6
|
+
const { meta } = table.options;
|
|
7
|
+
if (meta) {
|
|
8
|
+
const nextSelectedRows = table.getIsAllRowsSelected() ? [] : table.getCoreRowModel().rows.map((r) => r.original);
|
|
9
|
+
meta.onRowSelected?.(nextSelectedRows);
|
|
10
|
+
meta.lastClickedIndex.current = null;
|
|
11
|
+
}
|
|
12
|
+
table.toggleAllRowsSelected();
|
|
13
|
+
}, [table]);
|
|
14
|
+
return /* @__PURE__ */ jsx(
|
|
15
|
+
Checkbox,
|
|
16
|
+
{
|
|
17
|
+
size: "small",
|
|
18
|
+
checked: table.getIsAllRowsSelected(),
|
|
19
|
+
indeterminate: table.getSelectedRowModel().flatRows.length !== 0 && !table.getIsAllRowsSelected(),
|
|
20
|
+
onClick: handleClick
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
SelectHeaderCell
|
|
26
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Row } from '@tanstack/react-table';
|
|
2
|
+
import { ComposedModificationMetadata } from '../../../utils';
|
|
3
|
+
interface DragCloneRowProps {
|
|
4
|
+
row: Row<ComposedModificationMetadata>;
|
|
5
|
+
}
|
|
6
|
+
export declare function DragCloneRow({ row }: Readonly<DragCloneRowProps>): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@mui/material";
|
|
3
|
+
import { DragIndicator } from "@mui/icons-material";
|
|
4
|
+
import { useCallback } from "react";
|
|
5
|
+
import { useIntl } from "react-intl";
|
|
6
|
+
import { networkModificationTableStyles } from "../network-modification-table-styles.js";
|
|
7
|
+
import { useModificationLabelComputer } from "../../../hooks/useModificationLabelComputer.js";
|
|
8
|
+
import "../../../utils/conversionUtils.js";
|
|
9
|
+
import "../../../utils/types/equipmentType.js";
|
|
10
|
+
import { mergeSx } from "../../../utils/styles.js";
|
|
11
|
+
import "../../../utils/yupConfig.js";
|
|
12
|
+
import "localized-countries";
|
|
13
|
+
import "localized-countries/data/fr";
|
|
14
|
+
import "localized-countries/data/en";
|
|
15
|
+
import "notistack";
|
|
16
|
+
function DragCloneRow({ row }) {
|
|
17
|
+
const intl = useIntl();
|
|
18
|
+
const { computeLabel } = useModificationLabelComputer();
|
|
19
|
+
const getModificationLabel = useCallback(
|
|
20
|
+
(modification, formatBold = true) => {
|
|
21
|
+
return intl.formatMessage(
|
|
22
|
+
{ id: `network_modifications.${modification.messageType}` },
|
|
23
|
+
{ ...modification, ...computeLabel(modification, formatBold) }
|
|
24
|
+
);
|
|
25
|
+
},
|
|
26
|
+
[computeLabel, intl]
|
|
27
|
+
);
|
|
28
|
+
return /* @__PURE__ */ jsxs(Box, { sx: networkModificationTableStyles.dragRowClone, children: [
|
|
29
|
+
/* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.tableCell, children: /* @__PURE__ */ jsx(Box, { sx: mergeSx(networkModificationTableStyles.dragHandle, { opacity: 1 }), children: /* @__PURE__ */ jsx(DragIndicator, { sx: networkModificationTableStyles.dragIndicatorIcon }) }) }),
|
|
30
|
+
/* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.tableCell, children: /* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.modificationLabel, children: getModificationLabel(row.original) }) })
|
|
31
|
+
] });
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
DragCloneRow
|
|
35
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, RTE (http://www.rte-france.com)
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
5
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
6
|
+
*/
|
|
7
|
+
export * from './drag-row-clone';
|
|
8
|
+
export * from './modification-row';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Row } from '@tanstack/react-table';
|
|
2
|
+
import { VirtualItem } from '@tanstack/react-virtual';
|
|
3
|
+
import { ComposedModificationMetadata } from '../../../utils';
|
|
4
|
+
interface ModificationRowProps {
|
|
5
|
+
virtualRow: VirtualItem;
|
|
6
|
+
row: Row<ComposedModificationMetadata>;
|
|
7
|
+
handleCellClick?: (modification: ComposedModificationMetadata) => void;
|
|
8
|
+
isRowDragDisabled: boolean;
|
|
9
|
+
highlightedModificationUuid: string | null;
|
|
10
|
+
}
|
|
11
|
+
export declare function ModificationRow({ virtualRow, row, handleCellClick, isRowDragDisabled, highlightedModificationUuid, }: Readonly<ModificationRowProps>): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
import { flexRender } from "@tanstack/react-table";
|
|
4
|
+
import { useTheme, TableRow, TableCell, Tooltip, Box } from "@mui/material";
|
|
5
|
+
import { Draggable } from "@hello-pangea/dnd";
|
|
6
|
+
import { FormattedMessage } from "react-intl";
|
|
7
|
+
import { BASE_MODIFICATION_TABLE_COLUMNS, AUTO_EXTENSIBLE_COLUMNS } from "../columns-definition.js";
|
|
8
|
+
import { COLUMNS_WITHOUT_BORDER, createCellStyle, createCellContentWrapperSx, createRowSx, networkModificationTableStyles } from "../network-modification-table-styles.js";
|
|
9
|
+
import { isCompositeModification } from "../utils.js";
|
|
10
|
+
import "../../../utils/conversionUtils.js";
|
|
11
|
+
import "../../../utils/types/equipmentType.js";
|
|
12
|
+
import "@mui/icons-material";
|
|
13
|
+
import { mergeSx } from "../../../utils/styles.js";
|
|
14
|
+
import "../../../utils/yupConfig.js";
|
|
15
|
+
function ModificationRow({
|
|
16
|
+
virtualRow,
|
|
17
|
+
row,
|
|
18
|
+
handleCellClick,
|
|
19
|
+
isRowDragDisabled,
|
|
20
|
+
highlightedModificationUuid
|
|
21
|
+
}) {
|
|
22
|
+
const isHighlighted = row.original.uuid === highlightedModificationUuid;
|
|
23
|
+
const theme = useTheme();
|
|
24
|
+
const isExpanded = row.getIsExpanded() && row.subRows.length > 0;
|
|
25
|
+
const handleCellClickCallback = useCallback(
|
|
26
|
+
(columnId) => {
|
|
27
|
+
if (columnId === BASE_MODIFICATION_TABLE_COLUMNS.NAME.id) {
|
|
28
|
+
handleCellClick?.(row.original);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
[handleCellClick, row.original]
|
|
32
|
+
);
|
|
33
|
+
return /* @__PURE__ */ jsx(Draggable, { draggableId: row.id, index: virtualRow.index, isDragDisabled: isRowDragDisabled, children: (provided, snapshot) => {
|
|
34
|
+
const { style, ...draggablePropsWithoutStyle } = provided.draggableProps;
|
|
35
|
+
return /* @__PURE__ */ jsx(
|
|
36
|
+
TableRow,
|
|
37
|
+
{
|
|
38
|
+
ref: provided.innerRef,
|
|
39
|
+
...draggablePropsWithoutStyle,
|
|
40
|
+
"data-row-id": row.original.uuid,
|
|
41
|
+
sx: mergeSx(
|
|
42
|
+
networkModificationTableStyles.tableRow,
|
|
43
|
+
createRowSx(
|
|
44
|
+
theme,
|
|
45
|
+
isHighlighted,
|
|
46
|
+
snapshot.isDragging,
|
|
47
|
+
virtualRow,
|
|
48
|
+
row.depth,
|
|
49
|
+
isCompositeModification(row.original)
|
|
50
|
+
)
|
|
51
|
+
),
|
|
52
|
+
children: row.getVisibleCells().map((cell) => {
|
|
53
|
+
const isNameColumn = cell.column.id === BASE_MODIFICATION_TABLE_COLUMNS.NAME.id;
|
|
54
|
+
const isDragHandle = cell.column.id === BASE_MODIFICATION_TABLE_COLUMNS.DRAG_HANDLE.id;
|
|
55
|
+
const isCheckboxColumn = cell.column.id === BASE_MODIFICATION_TABLE_COLUMNS.SELECT.id;
|
|
56
|
+
const cellContent = flexRender(cell.column.columnDef.cell, cell.getContext());
|
|
57
|
+
const cellWithoutBorders = (isExpanded || row.depth > 0) && COLUMNS_WITHOUT_BORDER.has(cell.column.columnDef.id ?? "");
|
|
58
|
+
if (isDragHandle) {
|
|
59
|
+
return /* @__PURE__ */ jsx(
|
|
60
|
+
TableCell,
|
|
61
|
+
{
|
|
62
|
+
sx: createCellStyle(cell, AUTO_EXTENSIBLE_COLUMNS.includes(cell.column.id)),
|
|
63
|
+
children: /* @__PURE__ */ jsx(Tooltip, { title: /* @__PURE__ */ jsx(FormattedMessage, { id: "moveModification" }), arrow: true, children: /* @__PURE__ */ jsx(
|
|
64
|
+
Box,
|
|
65
|
+
{
|
|
66
|
+
sx: createCellContentWrapperSx(theme, cellWithoutBorders),
|
|
67
|
+
...provided.dragHandleProps,
|
|
68
|
+
children: cellContent
|
|
69
|
+
}
|
|
70
|
+
) })
|
|
71
|
+
},
|
|
72
|
+
cell.id
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
if (isCheckboxColumn) {
|
|
76
|
+
return /* @__PURE__ */ jsx(
|
|
77
|
+
TableCell,
|
|
78
|
+
{
|
|
79
|
+
sx: createCellStyle(cell, AUTO_EXTENSIBLE_COLUMNS.includes(cell.column.id)),
|
|
80
|
+
onClick: () => handleCellClickCallback(cell.column.id),
|
|
81
|
+
children: /* @__PURE__ */ jsx(
|
|
82
|
+
Tooltip,
|
|
83
|
+
{
|
|
84
|
+
title: /* @__PURE__ */ jsx(
|
|
85
|
+
FormattedMessage,
|
|
86
|
+
{
|
|
87
|
+
id: row.getIsSelected() ? "deselectModification" : "selectModification"
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
arrow: true,
|
|
91
|
+
children: /* @__PURE__ */ jsx(Box, { sx: createCellContentWrapperSx(theme, cellWithoutBorders), children: cellContent })
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
},
|
|
95
|
+
cell.id
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
return /* @__PURE__ */ jsx(
|
|
99
|
+
TableCell,
|
|
100
|
+
{
|
|
101
|
+
sx: createCellStyle(cell, AUTO_EXTENSIBLE_COLUMNS.includes(cell.column.id)),
|
|
102
|
+
onClick: () => handleCellClickCallback(cell.column.id),
|
|
103
|
+
children: isNameColumn ? (
|
|
104
|
+
// NameCell owns its own borders entirely
|
|
105
|
+
flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
106
|
+
) : /* @__PURE__ */ jsx(Box, { sx: createCellContentWrapperSx(theme, cellWithoutBorders), children: cellContent })
|
|
107
|
+
},
|
|
108
|
+
cell.id
|
|
109
|
+
);
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
} });
|
|
114
|
+
}
|
|
115
|
+
export {
|
|
116
|
+
ModificationRow
|
|
117
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { default as React, JSX, RefObject } from 'react';
|
|
2
|
+
import { Row } from '@tanstack/react-table';
|
|
3
|
+
import { DraggableProvided, DraggableRubric, DraggableStateSnapshot, DragUpdate, DropResult } from '@hello-pangea/dnd';
|
|
4
|
+
import { UUID } from 'node:crypto';
|
|
5
|
+
import { ComposedModificationMetadata } from '../../utils';
|
|
6
|
+
interface UseModificationsDragAndDropParams {
|
|
7
|
+
rows: Row<ComposedModificationMetadata>[];
|
|
8
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
9
|
+
composedModifications: ComposedModificationMetadata[];
|
|
10
|
+
setComposedModifications: React.Dispatch<React.SetStateAction<ComposedModificationMetadata[]>>;
|
|
11
|
+
onDragEnd: () => void;
|
|
12
|
+
studyUuid: UUID | null;
|
|
13
|
+
currentNodeUuid?: UUID;
|
|
14
|
+
}
|
|
15
|
+
interface UseModificationsDragAndDropReturn {
|
|
16
|
+
handleDragUpdate: (update: DragUpdate) => void;
|
|
17
|
+
handleDragEnd: (result: DropResult) => void;
|
|
18
|
+
renderClone: (provided: DraggableProvided, snapshot: DraggableStateSnapshot, rubric: DraggableRubric) => JSX.Element;
|
|
19
|
+
}
|
|
20
|
+
export declare const useModificationsDragAndDrop: ({ rows, containerRef, composedModifications, setComposedModifications, onDragEnd, studyUuid, currentNodeUuid, }: UseModificationsDragAndDropParams) => UseModificationsDragAndDropReturn;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from "react";
|
|
3
|
+
import { DragCloneRow } from "./row/drag-row-clone.js";
|
|
4
|
+
import "@tanstack/react-table";
|
|
5
|
+
import "@mui/material";
|
|
6
|
+
import "@hello-pangea/dnd";
|
|
7
|
+
import "react-intl";
|
|
8
|
+
import "./columns-definition.js";
|
|
9
|
+
import { DROP_FORBIDDEN_INDICATOR_BOTTOM, DROP_FORBIDDEN_INDICATOR_TOP, DROP_INDICATOR_BOTTOM, DROP_INDICATOR_TOP } from "./network-modification-table-styles.js";
|
|
10
|
+
import { moveSubModificationInTree, isCompositeModification, findModificationInTree } from "./utils.js";
|
|
11
|
+
import "../../utils/conversionUtils.js";
|
|
12
|
+
import { snackWithFallback } from "../../utils/error.js";
|
|
13
|
+
import "../../utils/types/equipmentType.js";
|
|
14
|
+
import "@mui/icons-material";
|
|
15
|
+
import "../../utils/yupConfig.js";
|
|
16
|
+
import { changeCompositeSubModificationOrder, changeNetworkModificationOrder } from "../../services/networkModification.js";
|
|
17
|
+
import "localized-countries";
|
|
18
|
+
import "localized-countries/data/fr";
|
|
19
|
+
import "localized-countries/data/en";
|
|
20
|
+
import { useSnackMessage } from "../../hooks/useSnackMessage.js";
|
|
21
|
+
const clearRowDragIndicators = (container) => {
|
|
22
|
+
const rowElements = container?.querySelectorAll("[data-row-id]");
|
|
23
|
+
rowElements?.forEach((rowElement) => {
|
|
24
|
+
rowElement.style.boxShadow = "";
|
|
25
|
+
});
|
|
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]));
|
|
33
|
+
};
|
|
34
|
+
function getTargetCompositeUuid(droppingIntoExpandedComposite, targetRow) {
|
|
35
|
+
if (droppingIntoExpandedComposite) {
|
|
36
|
+
return targetRow.original.uuid;
|
|
37
|
+
}
|
|
38
|
+
return targetRow.depth > 0 ? targetRow.getParentRow()?.original.uuid ?? null : null;
|
|
39
|
+
}
|
|
40
|
+
function getTargetSiblings(targetCompositeUuid, rows) {
|
|
41
|
+
return targetCompositeUuid ? rows.filter((r) => r.depth > 0 && r.getParentRow()?.original.uuid === targetCompositeUuid) : rows.filter((r) => r.depth === 0);
|
|
42
|
+
}
|
|
43
|
+
function getContainerShadow(forbidden, isMovingDown) {
|
|
44
|
+
if (forbidden) {
|
|
45
|
+
return isMovingDown ? DROP_FORBIDDEN_INDICATOR_BOTTOM : DROP_FORBIDDEN_INDICATOR_TOP;
|
|
46
|
+
}
|
|
47
|
+
return isMovingDown ? DROP_INDICATOR_BOTTOM : DROP_INDICATOR_TOP;
|
|
48
|
+
}
|
|
49
|
+
const useModificationsDragAndDrop = ({
|
|
50
|
+
rows,
|
|
51
|
+
containerRef,
|
|
52
|
+
composedModifications,
|
|
53
|
+
setComposedModifications,
|
|
54
|
+
onDragEnd,
|
|
55
|
+
studyUuid = null,
|
|
56
|
+
currentNodeUuid = void 0
|
|
57
|
+
}) => {
|
|
58
|
+
const { snackError } = useSnackMessage();
|
|
59
|
+
const handleDragUpdate = useCallback(
|
|
60
|
+
(update) => {
|
|
61
|
+
clearRowDragIndicators(containerRef.current);
|
|
62
|
+
const { source, destination } = update;
|
|
63
|
+
if (!destination || source.index === destination.index) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const sourceRow = rows[source.index];
|
|
67
|
+
const targetRow = rows[destination.index];
|
|
68
|
+
const el = containerRef.current?.querySelector(`[data-row-id="${targetRow?.original.uuid}"]`);
|
|
69
|
+
if (!el) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const forbidden = isDropForbidden(sourceRow, targetRow);
|
|
73
|
+
const isMovingDown = destination.index > source.index;
|
|
74
|
+
el.style.boxShadow = getContainerShadow(forbidden, isMovingDown);
|
|
75
|
+
},
|
|
76
|
+
[rows, containerRef]
|
|
77
|
+
);
|
|
78
|
+
const handleDragEndComposite = useCallback(
|
|
79
|
+
(sourceRow, targetRow, droppingIntoExpandedComposite, isDraggingDown) => {
|
|
80
|
+
const movingUuid = sourceRow.original.uuid;
|
|
81
|
+
const sourceCompositeUuid = sourceRow.depth > 0 ? sourceRow.getParentRow()?.original.uuid ?? null : null;
|
|
82
|
+
const targetCompositeUuid = getTargetCompositeUuid(droppingIntoExpandedComposite, targetRow);
|
|
83
|
+
const targetSiblings = getTargetSiblings(targetCompositeUuid, rows);
|
|
84
|
+
let beforeUuid;
|
|
85
|
+
if (droppingIntoExpandedComposite) {
|
|
86
|
+
beforeUuid = targetSiblings[0]?.original.uuid ?? null;
|
|
87
|
+
} else {
|
|
88
|
+
const landingIndexInSiblings = targetSiblings.findIndex(
|
|
89
|
+
(r) => r.original.uuid === targetRow.original.uuid
|
|
90
|
+
);
|
|
91
|
+
const beforeSiblingIndex = isDraggingDown ? landingIndexInSiblings + 1 : landingIndexInSiblings;
|
|
92
|
+
beforeUuid = targetSiblings[beforeSiblingIndex]?.original.uuid ?? null;
|
|
93
|
+
}
|
|
94
|
+
const previousComposed = composedModifications;
|
|
95
|
+
setComposedModifications(
|
|
96
|
+
(prev) => moveSubModificationInTree(movingUuid, sourceCompositeUuid, targetCompositeUuid, beforeUuid, prev)
|
|
97
|
+
);
|
|
98
|
+
changeCompositeSubModificationOrder(
|
|
99
|
+
studyUuid,
|
|
100
|
+
currentNodeUuid,
|
|
101
|
+
movingUuid,
|
|
102
|
+
sourceCompositeUuid,
|
|
103
|
+
targetCompositeUuid,
|
|
104
|
+
beforeUuid
|
|
105
|
+
).catch((error) => {
|
|
106
|
+
snackWithFallback(snackError, error, { headerId: "errReorderModificationMsg" });
|
|
107
|
+
setComposedModifications(previousComposed);
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
[rows, studyUuid, currentNodeUuid, snackError, composedModifications, setComposedModifications]
|
|
111
|
+
);
|
|
112
|
+
const handleDragEnd = useCallback(
|
|
113
|
+
(result) => {
|
|
114
|
+
clearRowDragIndicators(containerRef.current);
|
|
115
|
+
onDragEnd();
|
|
116
|
+
const { source, destination } = result;
|
|
117
|
+
if (!destination || source.index === destination.index) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const sourceRow = rows[source.index];
|
|
121
|
+
const targetRow = rows[destination.index];
|
|
122
|
+
if (isDropForbidden(sourceRow, targetRow)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const isSubRowInvolved = sourceRow.depth > 0 || targetRow.depth > 0;
|
|
126
|
+
const isDraggingDown = destination.index > source.index;
|
|
127
|
+
const droppingIntoExpandedComposite = isDraggingDown && targetRow.getIsExpanded();
|
|
128
|
+
if (isSubRowInvolved || droppingIntoExpandedComposite) {
|
|
129
|
+
handleDragEndComposite(sourceRow, targetRow, droppingIntoExpandedComposite, isDraggingDown);
|
|
130
|
+
} else {
|
|
131
|
+
const sourceDepth0Uuid = sourceRow.original.uuid;
|
|
132
|
+
const targetDepth0Uuid = targetRow.original.uuid;
|
|
133
|
+
const oldPosition = composedModifications.findIndex((m) => m.uuid === sourceDepth0Uuid);
|
|
134
|
+
const newPosition = composedModifications.findIndex((m) => m.uuid === targetDepth0Uuid);
|
|
135
|
+
if (oldPosition === -1 || newPosition === -1 || oldPosition === newPosition || !currentNodeUuid) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const previousModifications = [...composedModifications];
|
|
139
|
+
const updatedModifications = [...composedModifications];
|
|
140
|
+
const [movedItem] = updatedModifications.splice(oldPosition, 1);
|
|
141
|
+
updatedModifications.splice(newPosition, 0, movedItem);
|
|
142
|
+
setComposedModifications(updatedModifications);
|
|
143
|
+
const before = updatedModifications[newPosition + 1]?.uuid ?? null;
|
|
144
|
+
changeNetworkModificationOrder(studyUuid, currentNodeUuid, movedItem.uuid, before).catch((error) => {
|
|
145
|
+
snackWithFallback(snackError, error, { headerId: "errReorderModificationMsg" });
|
|
146
|
+
setComposedModifications(previousModifications);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
[
|
|
151
|
+
containerRef,
|
|
152
|
+
onDragEnd,
|
|
153
|
+
rows,
|
|
154
|
+
studyUuid,
|
|
155
|
+
currentNodeUuid,
|
|
156
|
+
snackError,
|
|
157
|
+
composedModifications,
|
|
158
|
+
setComposedModifications,
|
|
159
|
+
handleDragEndComposite
|
|
160
|
+
]
|
|
161
|
+
);
|
|
162
|
+
const renderClone = useCallback(
|
|
163
|
+
(provided, _snapshot, rubric) => /* @__PURE__ */ jsx("div", { ref: provided.innerRef, ...provided.draggableProps, ...provided.dragHandleProps, children: /* @__PURE__ */ jsx(DragCloneRow, { row: rows[rubric.source.index] }) }),
|
|
164
|
+
[rows]
|
|
165
|
+
);
|
|
166
|
+
return { handleDragUpdate, handleDragEnd, renderClone };
|
|
167
|
+
};
|
|
168
|
+
export {
|
|
169
|
+
useModificationsDragAndDrop
|
|
170
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
2
|
+
import { UUID } from 'node:crypto';
|
|
3
|
+
import { ComposedModificationMetadata, NetworkModificationMetadata } from '../../utils';
|
|
4
|
+
export declare const formatToComposedModification: (modifications: NetworkModificationMetadata[]) => ComposedModificationMetadata[];
|
|
5
|
+
export declare function isCompositeModification(modification: ComposedModificationMetadata | undefined): boolean;
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param modifications source where the composite modifications are looked for
|
|
9
|
+
* @param composites result : all the composite modifications found
|
|
10
|
+
*/
|
|
11
|
+
export declare function findAllLoadedCompositeModifications(modifications: ComposedModificationMetadata[], composites: ComposedModificationMetadata[]): void;
|
|
12
|
+
export declare function findModificationInTree(uuid: string, mods: ComposedModificationMetadata[]): ComposedModificationMetadata | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* in the tree, replaces the sub-modifications of 'parentModUuid' with 'subModifications' and returns the result
|
|
15
|
+
* @param parentModUuid
|
|
16
|
+
* @param subModifications new subModifications of parentModUuid
|
|
17
|
+
* @param tree all the modifications of the tree
|
|
18
|
+
*/
|
|
19
|
+
export declare function updateSubModificationsOfACompositeInTree(parentModUuid: string, subModifications: ComposedModificationMetadata[], tree: ComposedModificationMetadata[]): ComposedModificationMetadata[];
|
|
20
|
+
/**
|
|
21
|
+
* Recursively merges already-loaded subModifications from the previous tree into a freshly
|
|
22
|
+
* formatted tree (where all subModifications start as []). This ensures that when `modifications`
|
|
23
|
+
* changes, previously fetched children are preserved and do not need to be re-fetched.
|
|
24
|
+
*/
|
|
25
|
+
export declare function mergeSubModificationsIntoTree(nextMods: ComposedModificationMetadata[], prevMods: ComposedModificationMetadata[]): ComposedModificationMetadata[];
|
|
26
|
+
/**
|
|
27
|
+
* Returns a new tree where the modification identified by {@code uuid} has the given
|
|
28
|
+
* partial fields merged in. All other nodes are returned as-is (referentially stable).
|
|
29
|
+
*/
|
|
30
|
+
export declare function updateModificationFieldInTree(uuid: string, fields: Partial<ComposedModificationMetadata>, mods: ComposedModificationMetadata[]): ComposedModificationMetadata[];
|
|
31
|
+
/**
|
|
32
|
+
* @param movingUuid moved submodification uuid
|
|
33
|
+
* @param sourceParentUuid composite from which movingUuid comes from. null if movingUuid is at the root level
|
|
34
|
+
* @param targetParentUuid composite where movingUuid is moved. null if movingUuid is moved to the root level
|
|
35
|
+
* @param beforeUuid movingUuid is moved just before beforeUuid. If null, movingUuid is moved to the end.
|
|
36
|
+
* @param mods all the network modifications of the tree
|
|
37
|
+
* @return mods updated according to the moved submodification
|
|
38
|
+
*/
|
|
39
|
+
export declare function moveSubModificationInTree(movingUuid: UUID, sourceParentUuid: UUID | null, targetParentUuid: UUID | null, beforeUuid: UUID | null, mods: ComposedModificationMetadata[]): ComposedModificationMetadata[];
|
|
40
|
+
export declare function fetchSubModificationsForExpandedRows(expandedIds: string[], mods: ComposedModificationMetadata[], setMods: Dispatch<SetStateAction<ComposedModificationMetadata[]>>, force?: boolean): void;
|