@gridsuite/commons-ui 0.54.0 → 0.55.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.
@@ -1,25 +1,16 @@
1
1
  import { UUID } from 'crypto';
2
+ import { TreeViewFinderProps } from '../TreeViewFinder/TreeViewFinder';
2
3
  import { FunctionComponent } from 'react';
3
4
 
4
- interface DirectoryItemSelectorProps {
5
+ interface DirectoryItemSelectorProps extends TreeViewFinderProps {
5
6
  open: boolean;
6
- onClose: any;
7
7
  types: string[];
8
8
  equipmentTypes?: string[];
9
- title: string;
10
9
  itemFilter?: any;
11
10
  fetchDirectoryContent: (directoryUuid: UUID, elementTypes: string[]) => Promise<any>;
12
11
  fetchRootFolders: (types: string[]) => Promise<any>;
13
12
  fetchElementsInfos: (ids: UUID[], elementTypes: string[], equipmentTypes: string[]) => Promise<any>;
14
- classes?: any;
15
- contentText?: string;
16
- defaultExpanded?: string[];
17
- defaultSelected?: string[];
18
- validationButtonText?: string;
19
- className?: string;
20
- cancelButtonProps?: any;
21
- onlyLeaves?: boolean;
22
- multiselect?: boolean;
13
+ expanded?: UUID[];
23
14
  }
24
15
  declare const DirectoryItemSelector: FunctionComponent<DirectoryItemSelectorProps>;
25
16
  export default DirectoryItemSelector;
@@ -1,4 +1,4 @@
1
- import { jsx, Fragment } from "react/jsx-runtime";
1
+ import { jsx } from "react/jsx-runtime";
2
2
  import { useState, useRef, useCallback, useEffect } from "react";
3
3
  import { getFileIcon } from "../../utils/ElementIcon.js";
4
4
  import { ElementType } from "../../utils/ElementType.js";
@@ -13,23 +13,14 @@ const styles = {
13
13
  };
14
14
  const DirectoryItemSelector = ({
15
15
  open,
16
- onClose,
17
16
  types,
18
17
  equipmentTypes,
19
- title,
20
18
  itemFilter,
21
19
  fetchDirectoryContent,
22
20
  fetchRootFolders,
23
21
  fetchElementsInfos,
24
- classes,
25
- contentText,
26
- defaultExpanded,
27
- defaultSelected,
28
- validationButtonText,
29
- className,
30
- cancelButtonProps,
31
- onlyLeaves = true,
32
- multiselect = true
22
+ expanded,
23
+ ...otherTreeViewFinderProps
33
24
  }) => {
34
25
  const [data, setData] = useState([]);
35
26
  const [rootDirectories, setRootDirectories] = useState([]);
@@ -39,8 +30,6 @@ const DirectoryItemSelector = ({
39
30
  const rootsRef = useRef([]);
40
31
  rootsRef.current = rootDirectories;
41
32
  const { snackError } = useSnackMessage();
42
- const openRef = useRef();
43
- openRef.current = open;
44
33
  const contentFilter = useCallback(
45
34
  () => /* @__PURE__ */ new Set([ElementType.DIRECTORY, ...types]),
46
35
  [types]
@@ -105,11 +94,6 @@ const DirectoryItemSelector = ({
105
94
  });
106
95
  });
107
96
  }, [convertRoots, types, snackError, fetchRootFolders]);
108
- useEffect(() => {
109
- if (open) {
110
- updateRootDirectories();
111
- }
112
- }, [open, updateRootDirectories]);
113
97
  const fetchDirectory = useCallback(
114
98
  (nodeId) => {
115
99
  fetchDirectoryContent(nodeId, types).then((children) => {
@@ -149,6 +133,16 @@ const DirectoryItemSelector = ({
149
133
  fetchElementsInfos
150
134
  ]
151
135
  );
136
+ useEffect(() => {
137
+ if (open) {
138
+ updateRootDirectories();
139
+ if (expanded) {
140
+ expanded.forEach((nodeId) => {
141
+ fetchDirectory(nodeId);
142
+ });
143
+ }
144
+ }
145
+ }, [open, updateRootDirectories, expanded, fetchDirectory]);
152
146
  function sortHandlingDirectories(a, b) {
153
147
  if (a.children && !b.children) {
154
148
  return -1;
@@ -157,26 +151,19 @@ const DirectoryItemSelector = ({
157
151
  }
158
152
  return a.name.localeCompare(b.name);
159
153
  }
160
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
154
+ return /* @__PURE__ */ jsx(
161
155
  TreeViewFinder,
162
156
  {
163
- multiselect,
164
157
  onTreeBrowse: fetchDirectory,
165
- data,
166
- onlyLeaves,
167
158
  sortMethod: sortHandlingDirectories,
168
- title,
169
- onClose,
159
+ multiSelect: true,
170
160
  open,
171
- classes,
172
- contentText,
173
- defaultExpanded,
174
- defaultSelected,
175
- validationButtonText,
176
- className,
177
- cancelButtonProps
161
+ expanded,
162
+ onlyLeaves: true,
163
+ ...otherTreeViewFinderProps,
164
+ data
178
165
  }
179
- ) });
166
+ );
180
167
  };
181
168
  function updatedTree(prevRoots, prevMap, nodeId, children) {
182
169
  var _a;
@@ -159,6 +159,9 @@ const FlatParameters = ({
159
159
  if (param.name === inEditionParam && uncommitted !== null) {
160
160
  return uncommitted;
161
161
  } else if (initValues && initValues.hasOwnProperty(param.name)) {
162
+ if (param.type === "BOOLEAN") {
163
+ return initValues[param.name] === "false" ? false : initValues[param.name];
164
+ }
162
165
  if (param.type !== "STRING_LIST") {
163
166
  return initValues[param.name];
164
167
  }
@@ -1,12 +1,12 @@
1
1
  export default class LogReport {
2
2
  constructor(jsonReporter: any, parentReportId: any);
3
- id: any;
3
+ id: string;
4
4
  key: any;
5
5
  title: any;
6
6
  subReports: any[];
7
7
  logs: any[];
8
8
  parentReportId: any;
9
- getId(): any;
9
+ getId(): string;
10
10
  getTitle(): any;
11
11
  getSubReports(): any[];
12
12
  getLogs(): any[];
@@ -1,59 +1,33 @@
1
- import { default as PropTypes } from 'prop-types';
2
- export function generateTreeViewFinderClass(className: any): string;
3
- declare const _default: import('@emotion/styled').StyledComponent<Pick<PropTypes.InferProps<{
4
- open: PropTypes.Validator<boolean>;
5
- onClose: PropTypes.Requireable<(...args: any[]) => any>;
6
- data: PropTypes.Validator<(PropTypes.InferProps<{
7
- id: PropTypes.Validator<string>;
8
- name: PropTypes.Validator<string>;
9
- children: PropTypes.Requireable<any[]>;
10
- }> | null | undefined)[]>;
11
- onTreeBrowse: PropTypes.Requireable<(...args: any[]) => any>;
12
- classes: PropTypes.Requireable<object>;
13
- title: PropTypes.Requireable<string>;
14
- contentText: PropTypes.Requireable<string>;
15
- validationButtonText: PropTypes.Requireable<string>;
16
- defaultSelected: PropTypes.Requireable<(string | null | undefined)[]>;
17
- defaultExpanded: PropTypes.Requireable<(string | null | undefined)[]>;
18
- onlyLeaves: PropTypes.Requireable<boolean>;
19
- multiselect: PropTypes.Requireable<boolean>;
20
- sortMethod: PropTypes.Requireable<(...args: any[]) => any>;
21
- cancelButtonProps: PropTypes.Requireable<object>;
22
- className: PropTypes.Requireable<string>;
23
- }>, "className" | "title" | "onClose" | "onTreeBrowse" | "contentText" | "validationButtonText" | "cancelButtonProps" | PropTypes.RequiredKeys<{
24
- open: PropTypes.Validator<boolean>;
25
- onClose: PropTypes.Requireable<(...args: any[]) => any>;
26
- data: PropTypes.Validator<(PropTypes.InferProps<{
27
- id: PropTypes.Validator<string>;
28
- name: PropTypes.Validator<string>;
29
- children: PropTypes.Requireable<any[]>;
30
- }> | null | undefined)[]>;
31
- onTreeBrowse: PropTypes.Requireable<(...args: any[]) => any>;
32
- classes: PropTypes.Requireable<object>;
33
- title: PropTypes.Requireable<string>;
34
- contentText: PropTypes.Requireable<string>;
35
- validationButtonText: PropTypes.Requireable<string>;
36
- defaultSelected: PropTypes.Requireable<(string | null | undefined)[]>;
37
- defaultExpanded: PropTypes.Requireable<(string | null | undefined)[]>;
38
- onlyLeaves: PropTypes.Requireable<boolean>;
39
- multiselect: PropTypes.Requireable<boolean>;
40
- sortMethod: PropTypes.Requireable<(...args: any[]) => any>;
41
- cancelButtonProps: PropTypes.Requireable<object>;
42
- className: PropTypes.Requireable<string>;
43
- }>> & {
44
- classes?: object | null | undefined;
45
- defaultSelected?: (string | null | undefined)[] | null | undefined;
46
- defaultExpanded?: (string | null | undefined)[] | null | undefined;
47
- onlyLeaves?: boolean | null | undefined;
48
- multiselect?: boolean | null | undefined;
49
- sortMethod?: ((...args: any[]) => any) | null | undefined;
50
- } & {} & import("@mui/system").MUIStyledCommonProps<import("@mui/system").Theme>, {}, {}>;
1
+ import { TreeViewClasses } from '@mui/x-tree-view';
2
+ import { ButtonProps, ModalProps } from '@mui/material';
3
+ import { ReactElement } from 'react';
4
+
5
+ export declare const generateTreeViewFinderClass: (className: string) => string;
6
+ export interface TreeViewFinderNodeProps {
7
+ id: string;
8
+ name: string;
9
+ icon?: ReactElement;
10
+ childrenCount?: number;
11
+ children?: TreeViewFinderNodeProps[];
12
+ }
13
+ export interface TreeViewFinderProps {
14
+ defaultExpanded?: string[];
15
+ defaultSelected?: string[];
16
+ selected?: string[];
17
+ expanded?: string[];
18
+ multiSelect?: boolean;
19
+ classes?: Partial<TreeViewClasses>;
20
+ className?: string;
21
+ contentText?: string;
22
+ open: ModalProps['open'];
23
+ onClose: (nodes: TreeViewFinderNodeProps[]) => void;
24
+ validationButtonText?: string;
25
+ cancelButtonProps?: ButtonProps;
26
+ title?: string;
27
+ onlyLeaves?: boolean;
28
+ data?: TreeViewFinderNodeProps[];
29
+ onTreeBrowse?: (nodeId: string) => void;
30
+ sortMethod?: (a: TreeViewFinderNodeProps, b: TreeViewFinderNodeProps) => number;
31
+ }
32
+ declare const _default: import('@emotion/styled').StyledComponent<TreeViewFinderProps & import("@mui/system").MUIStyledCommonProps<import("@mui/system").Theme>, {}, {}>;
51
33
  export default _default;
52
- /**
53
- * This callback type is called `onTreeBrowseCallback` and is displayed as a global symbol.
54
- */
55
- export type onTreeBrowseCallback = (nodeId: string) => any;
56
- /**
57
- * - callback to update data prop when walk into Tree
58
- */
59
- export type onTreeBrowse = (defaultSelected?: any[] | undefined, defaultExpanded?: any[] | undefined, validationButtonText?: string | undefined, onlyLeaves?: boolean | undefined, multiselect?: boolean | undefined, cancelButtonProps?: Object | undefined) => any;
@@ -1,7 +1,6 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { useState, useCallback, useEffect } from "react";
2
+ import { useState, useRef, useCallback, useEffect } from "react";
3
3
  import { useIntl } from "react-intl";
4
- import PropTypes from "prop-types";
5
4
  import { toNestedGlobalSelectors, makeComposeClasses } from "../../utils/styles.js";
6
5
  import { styled } from "@mui/system";
7
6
  import { Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button, Typography } from "@mui/material";
@@ -39,7 +38,7 @@ const composeClasses = makeComposeClasses(generateTreeViewFinderClass);
39
38
  const TreeViewFinder = (props) => {
40
39
  const intl = useIntl();
41
40
  const {
42
- classes,
41
+ classes = {},
43
42
  title,
44
43
  contentText,
45
44
  open,
@@ -49,52 +48,63 @@ const TreeViewFinder = (props) => {
49
48
  onClose,
50
49
  onTreeBrowse,
51
50
  validationButtonText,
52
- onlyLeaves,
53
- multiselect,
51
+ onlyLeaves = true,
52
+ multiSelect = false,
54
53
  sortMethod,
55
54
  className,
56
- cancelButtonProps
55
+ cancelButtonProps,
56
+ selected: selectedProp,
57
+ expanded: expandedProp
57
58
  } = props;
58
59
  const [mapPrintedNodes, setMapPrintedNodes] = useState({});
59
- const [expanded, setExpanded] = useState(defaultExpanded);
60
- const [selected, setSelected] = useState(defaultSelected);
60
+ const [expanded, setExpanded] = useState(
61
+ defaultExpanded ?? []
62
+ );
63
+ const [selected, setSelected] = useState(
64
+ defaultSelected ?? []
65
+ );
66
+ const scrollRef = useRef([]);
67
+ const [autoScrollAllowed, setAutoScrollAllowed] = useState(true);
61
68
  const isSelectable = (node) => {
62
69
  return onlyLeaves ? isLeaf(node) : true;
63
70
  };
64
71
  const isLeaf = (node) => {
65
72
  return node && node.children === void 0;
66
73
  };
67
- const computeMapPrintedNodes = useCallback((nodes) => {
68
- let newMapPrintedNodes = {};
69
- nodes.forEach((node) => {
70
- newMapPrintedNodes[node.id] = node;
71
- if (!isLeaf(node)) {
72
- Object.assign(
73
- newMapPrintedNodes,
74
- computeMapPrintedNodes(node.children)
75
- );
76
- }
77
- });
78
- return newMapPrintedNodes;
79
- }, []);
74
+ const isValidationDisabled = () => {
75
+ return (selected == null ? void 0 : selected.length) === 0 || (selected == null ? void 0 : selected.length) === (selectedProp == null ? void 0 : selectedProp.length) && (selected == null ? void 0 : selected.every((nodeId) => selectedProp == null ? void 0 : selectedProp.includes(nodeId)));
76
+ };
77
+ const computeMapPrintedNodes = useCallback(
78
+ (nodes) => {
79
+ let newMapPrintedNodes = {};
80
+ nodes == null ? void 0 : nodes.forEach((node) => {
81
+ newMapPrintedNodes[node.id] = node;
82
+ if (!isLeaf(node)) {
83
+ Object.assign(
84
+ newMapPrintedNodes,
85
+ computeMapPrintedNodes(node.children)
86
+ );
87
+ }
88
+ });
89
+ return newMapPrintedNodes;
90
+ },
91
+ []
92
+ );
80
93
  useEffect(() => {
81
94
  let newMapPrintedNodes = computeMapPrintedNodes(data);
82
- console.debug(
83
- "data updated, new mapPrintedNodes (nbNodes = ",
84
- Object.keys(newMapPrintedNodes).length,
85
- ") : ",
86
- newMapPrintedNodes
87
- );
88
95
  setMapPrintedNodes(newMapPrintedNodes);
89
96
  }, [data, computeMapPrintedNodes]);
90
97
  const computeSelectedNodes = () => {
91
- return selected.map((nodeId) => {
98
+ if (!selected) {
99
+ return [];
100
+ }
101
+ return selected == null ? void 0 : selected.map((nodeId) => {
92
102
  return mapPrintedNodes[nodeId];
93
103
  });
94
104
  };
95
- const handleNodeToggle = (e, nodeIds) => {
105
+ const handleNodeToggle = (_e, nodeIds) => {
96
106
  nodeIds.every((nodeId) => {
97
- if (!expanded.includes(nodeId)) {
107
+ if (!(expanded == null ? void 0 : expanded.includes(nodeId))) {
98
108
  onTreeBrowse && onTreeBrowse(nodeId);
99
109
  return false;
100
110
  }
@@ -102,18 +112,61 @@ const TreeViewFinder = (props) => {
102
112
  });
103
113
  setExpanded(nodeIds);
104
114
  };
105
- const handleNodeSelect = (e, values) => {
106
- if (multiselect) {
115
+ useEffect(() => {
116
+ if (!selectedProp) {
117
+ return;
118
+ }
119
+ if (selectedProp.length > 0) {
120
+ setSelected((oldSelectedNodes) => [
121
+ ...oldSelectedNodes ? oldSelectedNodes : [],
122
+ ...selectedProp
123
+ ]);
124
+ }
125
+ }, [selectedProp]);
126
+ useEffect(() => {
127
+ if (!expandedProp || expandedProp.length === 0) {
128
+ return;
129
+ }
130
+ if (expandedProp.length > 0) {
131
+ setExpanded((oldExpandedNodes) => [
132
+ ...oldExpandedNodes ? oldExpandedNodes : [],
133
+ ...expandedProp
134
+ ]);
135
+ }
136
+ }, [expandedProp]);
137
+ useEffect(() => {
138
+ if (!selectedProp) {
139
+ return;
140
+ }
141
+ if (selectedProp.length > 0 && autoScrollAllowed) {
142
+ const isNodeExpanded = expandedProp == null ? void 0 : expandedProp.every(
143
+ (nodeId) => expanded == null ? void 0 : expanded.includes(nodeId)
144
+ );
145
+ const lastScrollRef = scrollRef.current[scrollRef.current.length - 1];
146
+ if (isNodeExpanded && lastScrollRef) {
147
+ lastScrollRef.scrollIntoView({
148
+ behavior: "smooth",
149
+ block: "center",
150
+ inline: "center"
151
+ });
152
+ setAutoScrollAllowed(false);
153
+ }
154
+ }
155
+ }, [expanded, selectedProp, expandedProp, data, autoScrollAllowed]);
156
+ const handleNodeSelect = (_e, values) => {
157
+ if (multiSelect && Array.isArray(values)) {
107
158
  setSelected(
108
159
  values.filter((nodeId) => isSelectable(mapPrintedNodes[nodeId]))
109
160
  );
110
161
  } else {
111
- if (selected.includes(values)) {
112
- setSelected([]);
113
- } else {
114
- setSelected(
115
- isSelectable(mapPrintedNodes[values]) ? [values] : []
116
- );
162
+ if (!Array.isArray(values)) {
163
+ if (selected == null ? void 0 : selected.includes(values)) {
164
+ setSelected([]);
165
+ } else {
166
+ setSelected(
167
+ isSelectable(mapPrintedNodes[values]) ? [values] : []
168
+ );
169
+ }
117
170
  }
118
171
  }
119
172
  };
@@ -121,10 +174,16 @@ const TreeViewFinder = (props) => {
121
174
  if (validationButtonText) {
122
175
  return validationButtonText;
123
176
  } else {
177
+ let buttonLabelId = "";
178
+ if (Array.isArray(selectedProp)) {
179
+ buttonLabelId = (selectedProp == null ? void 0 : selectedProp.length) > 0 ? "treeview_finder/replaceElementsValidation" : "treeview_finder/addElementsValidation";
180
+ } else {
181
+ buttonLabelId = selectedProp ? "treeview_finder/replaceElementsValidation" : "treeview_finder/addElementsValidation";
182
+ }
124
183
  return intl.formatMessage(
125
- { id: "treeview_finder/addElementsValidation" },
184
+ { id: buttonLabelId },
126
185
  {
127
- nbElements: selected.length
186
+ nbElements: selected == null ? void 0 : selected.length
128
187
  }
129
188
  );
130
189
  }
@@ -133,7 +192,7 @@ const TreeViewFinder = (props) => {
133
192
  if (!node) {
134
193
  return null;
135
194
  }
136
- if (isSelectable(node) && selected.find((nodeId) => nodeId === node.id)) {
195
+ if (isSelectable(node) && (selected == null ? void 0 : selected.find((nodeId) => nodeId === node.id))) {
137
196
  return /* @__PURE__ */ jsx(Check, { className: composeClasses(classes, cssLabelIcon) });
138
197
  } else {
139
198
  if (node.icon) {
@@ -173,18 +232,35 @@ const TreeViewFinder = (props) => {
173
232
  className: composeClasses(classes, cssIcon)
174
233
  }
175
234
  ) : null,
235
+ ref: (element) => {
236
+ if (selectedProp == null ? void 0 : selectedProp.includes(node.id)) {
237
+ scrollRef.current.push(element);
238
+ }
239
+ },
176
240
  children: Array.isArray(node.children) ? node.children.length ? node.children.sort(sortMethod).map((child) => renderTree(child)) : [false] : null
177
241
  },
178
242
  node.id
179
243
  );
180
244
  };
245
+ const getTreeViewSelectionProps = () => {
246
+ if (!multiSelect) {
247
+ return {
248
+ multiSelect: false,
249
+ selected: selected && selected.length > 0 ? selected.at(0) : ""
250
+ };
251
+ }
252
+ return {
253
+ multiSelect: true,
254
+ selected: selected ?? []
255
+ };
256
+ };
181
257
  return /* @__PURE__ */ jsxs(
182
258
  Dialog,
183
259
  {
184
260
  open,
185
261
  onClose: (e, r) => {
186
262
  if (r === "escapeKeyDown" || r === "backdropClick") {
187
- onClose([]);
263
+ onClose && onClose([]);
188
264
  setSelected([]);
189
265
  }
190
266
  },
@@ -196,21 +272,20 @@ const TreeViewFinder = (props) => {
196
272
  children: [
197
273
  /* @__PURE__ */ jsx(DialogTitle, { id: "TreeViewFindertitle", children: title ? title : intl.formatMessage(
198
274
  { id: "treeview_finder/finderTitle" },
199
- { multiselect }
275
+ { multiSelect }
200
276
  ) }),
201
277
  /* @__PURE__ */ jsxs(DialogContent, { children: [
202
278
  /* @__PURE__ */ jsx(DialogContentText, { children: contentText ? contentText : intl.formatMessage(
203
279
  { id: "treeview_finder/contentText" },
204
- { multiselect }
280
+ { multiSelect }
205
281
  ) }),
206
282
  /* @__PURE__ */ jsx(
207
283
  TreeView,
208
284
  {
209
285
  expanded,
210
- selected,
211
286
  onNodeToggle: handleNodeToggle,
212
287
  onNodeSelect: handleNodeSelect,
213
- multiSelect: multiselect,
288
+ ...getTreeViewSelectionProps(),
214
289
  children: data && Array.isArray(data) ? data.sort(sortMethod).map((child) => renderTree(child)) : null
215
290
  }
216
291
  )
@@ -221,8 +296,9 @@ const TreeViewFinder = (props) => {
221
296
  {
222
297
  style: { float: "left", margin: "5px" },
223
298
  onClick: () => {
224
- onClose([]);
299
+ onClose && onClose([]);
225
300
  setSelected([]);
301
+ setAutoScrollAllowed(true);
226
302
  },
227
303
  ...cancelButtonProps
228
304
  }
@@ -233,10 +309,11 @@ const TreeViewFinder = (props) => {
233
309
  variant: "outlined",
234
310
  style: { float: "left", margin: "5px" },
235
311
  onClick: () => {
236
- onClose(computeSelectedNodes());
312
+ onClose && onClose(computeSelectedNodes());
237
313
  setSelected([]);
314
+ setAutoScrollAllowed(true);
238
315
  },
239
- disabled: selected.length === 0,
316
+ disabled: isValidationDisabled(),
240
317
  children: getValidationButtonText()
241
318
  }
242
319
  )
@@ -245,39 +322,6 @@ const TreeViewFinder = (props) => {
245
322
  }
246
323
  );
247
324
  };
248
- TreeViewFinder.propTypes = {
249
- // Controlled
250
- open: PropTypes.bool.isRequired,
251
- onClose: PropTypes.func,
252
- data: PropTypes.arrayOf(
253
- PropTypes.shape({
254
- id: PropTypes.string.isRequired,
255
- name: PropTypes.string.isRequired,
256
- children: PropTypes.array
257
- })
258
- ).isRequired,
259
- onTreeBrowse: PropTypes.func,
260
- //uncontrolled
261
- classes: PropTypes.object,
262
- title: PropTypes.string,
263
- contentText: PropTypes.string,
264
- validationButtonText: PropTypes.string,
265
- defaultSelected: PropTypes.arrayOf(PropTypes.string),
266
- defaultExpanded: PropTypes.arrayOf(PropTypes.string),
267
- onlyLeaves: PropTypes.bool,
268
- multiselect: PropTypes.bool,
269
- sortMethod: PropTypes.func,
270
- cancelButtonProps: PropTypes.object,
271
- className: PropTypes.string
272
- };
273
- TreeViewFinder.defaultProps = {
274
- defaultSelected: [],
275
- defaultExpanded: [],
276
- onlyLeaves: true,
277
- multiselect: false,
278
- sortMethod: void 0,
279
- classes: {}
280
- };
281
325
  const nestedGlobalSelectorsStyles = toNestedGlobalSelectors(
282
326
  defaultStyles,
283
327
  generateTreeViewFinderClass
@@ -2,7 +2,7 @@ import { UUID } from 'crypto';
2
2
  import { FunctionComponent } from 'react';
3
3
 
4
4
  export declare const NAME = "name";
5
- interface DirectoryItemsInputProps {
5
+ export interface DirectoryItemsInputProps {
6
6
  label: string | undefined;
7
7
  name: string;
8
8
  elementType: string;
@@ -17,6 +17,7 @@ interface DirectoryItemsInputProps {
17
17
  fetchRootFolders: (types: string[]) => Promise<any>;
18
18
  fetchElementsInfos: (ids: UUID[], elementTypes: string[], equipmentTypes?: string[]) => Promise<any>;
19
19
  labelRequiredFromContext?: boolean;
20
+ fetchDirectoryElementPath?: (id: UUID) => Promise<any[]>;
20
21
  }
21
22
  declare const DirectoryItemsInput: FunctionComponent<DirectoryItemsInputProps>;
22
23
  export default DirectoryItemsInput;
@@ -4,7 +4,7 @@ import { OverflowableText } from "../OverflowableText/overflowable-text.js";
4
4
  import { useSnackMessage } from "../../hooks/useSnackMessage.js";
5
5
  import FieldLabel from "./utils/field-label.js";
6
6
  import FolderIcon from "@mui/icons-material/Folder";
7
- import { useMemo, useState, useCallback } from "react";
7
+ import { useState, useMemo, useCallback } from "react";
8
8
  import { useFieldArray, useController } from "react-hook-form";
9
9
  import { useIntl } from "react-intl";
10
10
  import ErrorInput from "./error-management/error-input.js";
@@ -60,10 +60,14 @@ const DirectoryItemsInput = ({
60
60
  fetchDirectoryContent,
61
61
  fetchRootFolders,
62
62
  fetchElementsInfos,
63
- labelRequiredFromContext = true
63
+ labelRequiredFromContext = true,
64
+ fetchDirectoryElementPath
64
65
  }) => {
65
66
  const { snackError } = useSnackMessage();
66
67
  const intl = useIntl();
68
+ const [selected, setSelected] = useState([]);
69
+ const [expanded, setExpanded] = useState([]);
70
+ const [multiSelect, setMultiSelect] = useState(true);
67
71
  const types = useMemo(() => [elementType], [elementType]);
68
72
  const [directoryItemSelectorOpen, setDirectoryItemSelectorOpen] = useState(false);
69
73
  const {
@@ -82,6 +86,18 @@ const DirectoryItemsInput = ({
82
86
  });
83
87
  const addElements = useCallback(
84
88
  (values) => {
89
+ if (!values) {
90
+ return;
91
+ }
92
+ if ((selected == null ? void 0 : selected.length) > 0 && (values == null ? void 0 : values.length) > 0) {
93
+ selected.forEach((chip) => {
94
+ remove(
95
+ getValues(name).findIndex(
96
+ (item) => item.id === chip
97
+ )
98
+ );
99
+ });
100
+ }
85
101
  values.forEach((value) => {
86
102
  const { icon, children, ...otherElementAttributes } = value;
87
103
  if (getValues(name).find(
@@ -98,8 +114,18 @@ const DirectoryItemsInput = ({
98
114
  }
99
115
  });
100
116
  setDirectoryItemSelectorOpen(false);
117
+ setSelected([]);
101
118
  },
102
- [append, getValues, snackError, name, onRowChanged, onChange]
119
+ [
120
+ append,
121
+ getValues,
122
+ snackError,
123
+ name,
124
+ onRowChanged,
125
+ onChange,
126
+ selected,
127
+ remove
128
+ ]
103
129
  );
104
130
  const removeElements = useCallback(
105
131
  (index) => {
@@ -109,6 +135,23 @@ const DirectoryItemsInput = ({
109
135
  },
110
136
  [onRowChanged, remove, getValues, name, onChange]
111
137
  );
138
+ const handleChipClick = useCallback(
139
+ (index) => {
140
+ var _a;
141
+ const chips = getValues(name);
142
+ const chip = (_a = chips.at(index)) == null ? void 0 : _a.id;
143
+ if (chip && fetchDirectoryElementPath) {
144
+ fetchDirectoryElementPath(chip).then((response) => {
145
+ const path = response.reverse().filter((e) => e.elementUuid !== chip).map((e) => e.elementUuid);
146
+ setExpanded(path);
147
+ setSelected([chip]);
148
+ setDirectoryItemSelectorOpen(true);
149
+ setMultiSelect(false);
150
+ });
151
+ }
152
+ },
153
+ [getValues, name, fetchDirectoryElementPath]
154
+ );
112
155
  return /* @__PURE__ */ jsxs(Fragment, { children: [
113
156
  /* @__PURE__ */ jsxs(
114
157
  FormControl,
@@ -135,6 +178,7 @@ const DirectoryItemsInput = ({
135
178
  {
136
179
  size: "small",
137
180
  onDelete: () => removeElements(index),
181
+ onClick: () => handleChipClick(index),
138
182
  label: /* @__PURE__ */ jsx(
139
183
  OverflowableText,
140
184
  {
@@ -150,16 +194,19 @@ const DirectoryItemsInput = ({
150
194
  },
151
195
  item.id
152
196
  )) }),
153
- /* @__PURE__ */ jsx(Grid, { item: true, xs: true, children: /* @__PURE__ */ jsx(Grid, { container: true, direction: "row-reverse", children: /* @__PURE__ */ jsx(Tooltip, { title: intl.formatMessage({ id: titleId }), children: /* @__PURE__ */ jsx(
197
+ /* @__PURE__ */ jsx(Grid, { item: true, xs: true, children: /* @__PURE__ */ jsx(Grid, { container: true, direction: "row-reverse", children: /* @__PURE__ */ jsx(Tooltip, { title: intl.formatMessage({ id: titleId }), children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
154
198
  IconButton,
155
199
  {
156
200
  sx: styles.addDirectoryElements,
157
201
  size: "small",
158
202
  disabled: disable,
159
- onClick: () => setDirectoryItemSelectorOpen(true),
203
+ onClick: () => {
204
+ setDirectoryItemSelectorOpen(true);
205
+ setMultiSelect(true);
206
+ },
160
207
  children: /* @__PURE__ */ jsx(FolderIcon, {})
161
208
  }
162
- ) }) }) })
209
+ ) }) }) }) })
163
210
  ]
164
211
  }
165
212
  ),
@@ -175,7 +222,10 @@ const DirectoryItemsInput = ({
175
222
  itemFilter,
176
223
  fetchDirectoryContent,
177
224
  fetchRootFolders,
178
- fetchElementsInfos
225
+ fetchElementsInfos,
226
+ selected,
227
+ expanded,
228
+ multiSelect
179
229
  }
180
230
  )
181
231
  ] });
@@ -13,4 +13,5 @@ declare const treeview_finder_en: {
13
13
  'treeview_finder/contentText': string;
14
14
  'treeview_finder/finderTitle': string;
15
15
  'treeview_finder/addElementsValidation': string;
16
+ 'treeview_finder/replaceElementsValidation': string;
16
17
  };
@@ -3,9 +3,10 @@ const treeview_finder_en = {
3
3
  "treeview_finder/validate": "Validate",
4
4
  "treeview_finder/add": "Add...",
5
5
  "treeview_finder/deleteSelection": "Delete selection",
6
- "treeview_finder/contentText": "{multiselect, select, true {Please choose one or more element(s).} false {Please choose one element.} other {}}",
7
- "treeview_finder/finderTitle": "{multiselect, select, true {Please choose one or more element(s).} false {Please choose one element.} other {}}",
8
- "treeview_finder/addElementsValidation": "{nbElements, plural, =0 {Please select an element} =1 {Add this element} other{Add # elements}}"
6
+ "treeview_finder/contentText": "{multiSelect, select, true {Please choose one or more element(s).} false {Please choose one element.} other {}}",
7
+ "treeview_finder/finderTitle": "{multiSelect, select, true {Please choose one or more element(s).} false {Please choose one element.} other {}}",
8
+ "treeview_finder/addElementsValidation": "{nbElements, plural, =0 {Please select an element} =1 {Add this element} other{Add # elements}}",
9
+ "treeview_finder/replaceElementsValidation": "{nbElements, plural, =0 {Please select an element} =1 {Replace with this element} other{Replace with # elements}}"
9
10
  };
10
11
  export {
11
12
  treeview_finder_en as default
@@ -13,4 +13,5 @@ declare const treeview_finder_fr: {
13
13
  'treeview_finder/contentText': string;
14
14
  'treeview_finder/finderTitle': string;
15
15
  'treeview_finder/addElementsValidation': string;
16
+ 'treeview_finder/replaceElementsValidation': string;
16
17
  };
@@ -3,9 +3,10 @@ const treeview_finder_fr = {
3
3
  "treeview_finder/validate": "Valider",
4
4
  "treeview_finder/add": "Ajouter...",
5
5
  "treeview_finder/deleteSelection": "Supprimer la selection",
6
- "treeview_finder/contentText": "{multiselect, select, true {Veuillez choisir un ou plusieurs éléments.} false {Veuillez choisir un élément.} other {}}",
7
- "treeview_finder/finderTitle": "{multiselect, select, true {Veuillez choisir un ou plusieurs éléments.} false {Veuillez choisir un élément.} other {}}",
8
- "treeview_finder/addElementsValidation": "{nbElements, plural, =0 {Veuillez sélectionner un élément} =1 {Ajouter cet élément} other {Ajouter # éléments}}"
6
+ "treeview_finder/contentText": "{multiSelect, select, true {Veuillez choisir un ou plusieurs éléments.} false {Veuillez choisir un élément.} other {}}",
7
+ "treeview_finder/finderTitle": "{multiSelect, select, true {Veuillez choisir un ou plusieurs éléments.} false {Veuillez choisir un élément.} other {}}",
8
+ "treeview_finder/addElementsValidation": "{nbElements, plural, =0 {Veuillez sélectionner un élément} =1 {Ajouter cet élément} other {Ajouter # éléments}}",
9
+ "treeview_finder/replaceElementsValidation": "{nbElements, plural, =0 {Veuillez sélectionner un élément} =1 {Remplacer par cet élément} other {Remplacer par # éléments}}"
9
10
  };
10
11
  export {
11
12
  treeview_finder_fr as default
package/dist/index.d.ts CHANGED
@@ -7,7 +7,11 @@ import { FunctionComponent, ReactElement } from 'react';
7
7
  * Section to export generated type declarations
8
8
  */
9
9
 
10
- export { default as TreeViewFinder } from './components/TreeViewFinder';
10
+ export {
11
+ default as TreeViewFinder,
12
+ TreeViewFinderProps,
13
+ TreeViewFinderNodeProps,
14
+ } from './components/TreeViewFinder';
11
15
  export { default as AboutDialog } from './components/TopBar/AboutDialog';
12
16
  export { default as AuthenticationRouter } from './components/AuthenticationRouter';
13
17
  export { default as MuiVirtualizedTable } from './components/MuiVirtualizedTable';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gridsuite/commons-ui",
3
- "version": "0.54.0",
3
+ "version": "0.55.0",
4
4
  "description": "common react components for gridsuite applications",
5
5
  "engines": {
6
6
  "npm": ">=9",
@@ -68,8 +68,18 @@
68
68
  "@mui/material": "^5.15.14",
69
69
  "@mui/x-tree-view": "^6.17.0",
70
70
  "@react-hook/window-size": "^3.1.1",
71
- "@types/react": "^18.2.73",
72
- "@types/react-dom": "^18.2.23",
71
+ "@types/autosuggest-highlight": "^3.2.3",
72
+ "@types/eslint": "^8.56.7",
73
+ "@types/eslint-config-prettier": "^6.11.3",
74
+ "@types/license-checker": "^25.0.6",
75
+ "@types/node": "^18.19.31",
76
+ "@types/prop-types": "^15.7.12",
77
+ "@types/react": "^18.2.75",
78
+ "@types/react-dom": "^18.2.24",
79
+ "@types/react-resizable": "^3.0.7",
80
+ "@types/react-virtualized": "^9.21.29",
81
+ "@types/utf-8-validate": "^5.0.2",
82
+ "@types/uuid": "^9.0.8",
73
83
  "@typescript-eslint/eslint-plugin": "^6.21.0",
74
84
  "@typescript-eslint/parser": "^6.21.0",
75
85
  "@vitejs/plugin-react": "^4.2.1",