@gridsuite/commons-ui 0.89.4 → 0.91.1

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.
Files changed (25) hide show
  1. package/dist/components/contingencyList/criteriaBased/CriteriaBasedForm.js +1 -1
  2. package/dist/components/customAGGrid/customAggrid.d.ts +0 -1
  3. package/dist/components/customAGGrid/customAggrid.js +2 -3
  4. package/dist/components/customAGGrid/customAggrid.style.d.ts +0 -8
  5. package/dist/components/customAGGrid/customAggrid.style.js +1 -9
  6. package/dist/components/dialogs/elementSaveDialog/ElementSaveDialog.d.ts +56 -0
  7. package/dist/components/dialogs/{elementCreationDialog/ElementCreationDialog.js → elementSaveDialog/ElementSaveDialog.js} +116 -41
  8. package/dist/components/dialogs/{elementCreationDialog → elementSaveDialog}/index.d.ts +2 -2
  9. package/dist/components/dialogs/elementSaveDialog/index.js +4 -0
  10. package/dist/components/dialogs/index.d.ts +1 -1
  11. package/dist/components/dialogs/index.js +2 -2
  12. package/dist/components/directoryItemSelector/DirectoryItemSelector.js +2 -0
  13. package/dist/components/filter/FilterForm.js +1 -1
  14. package/dist/components/filter/expert/ExpertFilterForm.js +1 -1
  15. package/dist/components/filter/explicitNaming/ExplicitNamingFilterForm.js +1 -1
  16. package/dist/components/index.js +2 -2
  17. package/dist/components/inputs/reactHookForm/text/DescriptionField.js +6 -1
  18. package/dist/components/inputs/reactHookForm/text/UniqueNameInput.d.ts +2 -1
  19. package/dist/components/inputs/reactHookForm/text/UniqueNameInput.js +5 -2
  20. package/dist/components/treeViewFinder/TreeViewFinder.d.ts +5 -2
  21. package/dist/components/treeViewFinder/TreeViewFinder.js +29 -3
  22. package/dist/index.js +2 -2
  23. package/package.json +1 -1
  24. package/dist/components/dialogs/elementCreationDialog/ElementCreationDialog.d.ts +0 -28
  25. package/dist/components/dialogs/elementCreationDialog/index.js +0 -4
@@ -8,7 +8,7 @@ import { InputWithPopupConfirmation } from "../../inputs/reactHookForm/selectInp
8
8
  import { useSnackMessage } from "../../../hooks/useSnackMessage.js";
9
9
  import { unscrollableDialogStyles } from "../../dialogs/customMuiDialog/CustomMuiDialog.js";
10
10
  import "../../dialogs/descriptionModificationDialog/DescriptionModificationDialog.js";
11
- import "../../dialogs/elementCreationDialog/ElementCreationDialog.js";
11
+ import "../../dialogs/elementSaveDialog/ElementSaveDialog.js";
12
12
  import "react-intl";
13
13
  import "@mui/icons-material";
14
14
  import "../../treeViewFinder/TreeViewFinder.js";
@@ -2,7 +2,6 @@ import { default as React } from 'react';
2
2
  import { AgGridReact, AgGridReactProps } from 'ag-grid-react';
3
3
  interface CustomAGGGridStyleProps {
4
4
  shouldHidePinnedHeaderRightBorder?: boolean;
5
- showOverlay?: boolean;
6
5
  }
7
6
  export interface CustomAGGridProps extends AgGridReactProps, CustomAGGGridStyleProps {
8
7
  }
@@ -19,7 +19,7 @@ const onColumnResized = (params) => {
19
19
  }
20
20
  };
21
21
  const CustomAGGrid = React.forwardRef((props, ref) => {
22
- const { shouldHidePinnedHeaderRightBorder = false, showOverlay = false, ...agGridReactProps } = props;
22
+ const { shouldHidePinnedHeaderRightBorder = false, ...agGridReactProps } = props;
23
23
  const theme = useTheme();
24
24
  const intl = useIntl();
25
25
  const GRID_PREFIX = "grid.";
@@ -38,8 +38,7 @@ const CustomAGGrid = React.forwardRef((props, ref) => {
38
38
  {
39
39
  sx: mergeSx(
40
40
  styles.grid,
41
- shouldHidePinnedHeaderRightBorder ? styles.noBorderRight : void 0,
42
- showOverlay ? styles.overlayBackground : void 0
41
+ shouldHidePinnedHeaderRightBorder ? styles.noBorderRight : void 0
43
42
  ),
44
43
  className: `${theme.aggrid.theme} ${CUSTOM_AGGRID_THEME}`,
45
44
  children: /* @__PURE__ */ jsx(
@@ -8,12 +8,4 @@ export declare const styles: {
8
8
  borderRight: string;
9
9
  };
10
10
  };
11
- overlayBackground: (theme: Theme) => {
12
- '& .ag-overlay-loading-wrapper': {
13
- background: string;
14
- };
15
- '& .ag-overlay-no-rows-wrapper': {
16
- background: string;
17
- };
18
- };
19
11
  };
@@ -33,15 +33,7 @@ const styles = {
33
33
  "& .ag-pinned-left-header": {
34
34
  borderRight: "none"
35
35
  }
36
- },
37
- overlayBackground: (theme) => ({
38
- "& .ag-overlay-loading-wrapper": {
39
- background: theme.aggrid.overlay.background
40
- },
41
- "& .ag-overlay-no-rows-wrapper": {
42
- background: "none"
43
- }
44
- })
36
+ }
45
37
  };
46
38
  export {
47
39
  CUSTOM_AGGRID_THEME,
@@ -0,0 +1,56 @@
1
+ import { UUID } from 'crypto';
2
+ import { ElementAttributes, ElementType, FieldConstants } from '../../../utils';
3
+ declare enum OperationType {
4
+ CREATE = "CREATE",
5
+ UPDATE = "UPDATE"
6
+ }
7
+ export interface IElementCommonFields {
8
+ [FieldConstants.NAME]: string;
9
+ [FieldConstants.DESCRIPTION]: string;
10
+ }
11
+ export interface IElementCreationDialog extends IElementCommonFields {
12
+ [FieldConstants.FOLDER_NAME]: string;
13
+ [FieldConstants.FOLDER_ID]: UUID;
14
+ }
15
+ export interface IElementUpdateDialog extends IElementCommonFields {
16
+ [FieldConstants.ID]: UUID;
17
+ parentFolderId?: UUID;
18
+ elementFullPath: string;
19
+ }
20
+ export type ElementSaveDialogProps = {
21
+ open: boolean;
22
+ onClose: () => void;
23
+ type: ElementType;
24
+ titleId: string;
25
+ onSave: (data: IElementCreationDialog) => void;
26
+ OnUpdate?: (data: IElementUpdateDialog) => void;
27
+ prefixIdForGeneratedName?: string;
28
+ initialOperation?: OperationType;
29
+ selectorTitleId?: string;
30
+ createLabelId?: string;
31
+ updateLabelId?: string;
32
+ createOnlyMode?: boolean;
33
+ } & ({
34
+ /** createOnlyMode uses only CREATE operation */
35
+ createOnlyMode: true;
36
+ selectorTitleId?: string;
37
+ createLabelId?: string;
38
+ updateLabelId?: string;
39
+ } | {
40
+ /** Standard mode requires label IDs for both operations and update callback */
41
+ createOnlyMode?: false;
42
+ selectorTitleId: string;
43
+ createLabelId: string;
44
+ updateLabelId: string;
45
+ OnUpdate: (data: IElementUpdateDialog) => void;
46
+ }) & ({
47
+ /** starting directory can be the same as a given study */
48
+ studyUuid: UUID;
49
+ initDirectory?: never;
50
+ } | {
51
+ studyUuid?: never;
52
+ /** or directly a given directory */
53
+ initDirectory?: ElementAttributes;
54
+ });
55
+ export declare function ElementSaveDialog({ open, onSave, OnUpdate, onClose, type, titleId, prefixIdForGeneratedName, studyUuid, initDirectory, initialOperation, selectorTitleId, createLabelId, updateLabelId, createOnlyMode, }: Readonly<ElementSaveDialogProps>): import("react/jsx-runtime").JSX.Element;
56
+ export {};
@@ -5,13 +5,6 @@ import { Grid, Button, Typography, Box, CircularProgress } from "@mui/material";
5
5
  import { useForm } from "react-hook-form";
6
6
  import { yupResolver } from "@hookform/resolvers/yup";
7
7
  import "../../../utils/yupConfig.js";
8
- import { FieldConstants } from "../../../utils/constants/fieldConstants.js";
9
- import { MAX_CHAR_DESCRIPTION } from "../../../utils/constants/uiConstants.js";
10
- import "../../../utils/conversionUtils.js";
11
- import "@mui/icons-material";
12
- import { ElementType } from "../../../utils/types/elementType.js";
13
- import "../../../utils/types/equipmentType.js";
14
- import { CustomMuiDialog } from "../customMuiDialog/CustomMuiDialog.js";
15
8
  import "@mui/icons-material/Folder";
16
9
  import "../../inputs/reactHookForm/provider/CustomFormProvider.js";
17
10
  import * as yup from "yup";
@@ -22,6 +15,7 @@ import { fetchDirectoryElementPath } from "../../../services/directory.js";
22
15
  import "../../inputs/reactHookForm/agGridTable/BottomRightButtons.js";
23
16
  import "ag-grid-community/styles/ag-grid.css";
24
17
  import "ag-grid-community/styles/ag-theme-alpine.css";
18
+ import { FieldConstants } from "../../../utils/constants/fieldConstants.js";
25
19
  import "../../customAGGrid/customAggrid.js";
26
20
  import "ag-grid-community";
27
21
  import "@mui/material/Dialog";
@@ -33,6 +27,8 @@ import "@mui/material/Button";
33
27
  import "@mui/material/Grid";
34
28
  import "react-csv-downloader";
35
29
  import "@mui/material/Alert";
30
+ import "@mui/icons-material";
31
+ import { RadioInput } from "../../inputs/reactHookForm/booleans/RadioInput.js";
36
32
  import "../../inputs/reactHookForm/numbers/RangeInput.js";
37
33
  import "localized-countries";
38
34
  import "localized-countries/data/fr";
@@ -48,44 +44,71 @@ import "../../inputs/reactQueryBuilder/PropertyValueEditor.js";
48
44
  import "@mui/material/IconButton";
49
45
  import "@mui/icons-material/Delete";
50
46
  import "react-querybuilder";
47
+ import "../../../utils/conversionUtils.js";
51
48
  import "@mui/material/Box";
49
+ import { ElementType } from "../../../utils/types/elementType.js";
50
+ import { CustomMuiDialog } from "../customMuiDialog/CustomMuiDialog.js";
51
+ import { MAX_CHAR_DESCRIPTION } from "../../../utils/constants/uiConstants.js";
52
+ import "../../../utils/types/equipmentType.js";
53
+ var OperationType = /* @__PURE__ */ ((OperationType2) => {
54
+ OperationType2["CREATE"] = "CREATE";
55
+ OperationType2["UPDATE"] = "UPDATE";
56
+ return OperationType2;
57
+ })(OperationType || {});
52
58
  const schema = yup.object().shape({
53
59
  [FieldConstants.NAME]: yup.string().trim().required(),
54
- [FieldConstants.DESCRIPTION]: yup.string().optional().max(MAX_CHAR_DESCRIPTION, "descriptionLimitError")
60
+ [FieldConstants.DESCRIPTION]: yup.string().optional().max(MAX_CHAR_DESCRIPTION, "descriptionLimitError"),
61
+ [FieldConstants.OPERATION_TYPE]: yup.string().oneOf(Object.values(OperationType)).required()
55
62
  }).required();
56
63
  const emptyFormData = {
57
64
  [FieldConstants.NAME]: "",
58
- [FieldConstants.DESCRIPTION]: ""
65
+ [FieldConstants.DESCRIPTION]: "",
66
+ [FieldConstants.OPERATION_TYPE]: "CREATE"
67
+ /* CREATE */
59
68
  };
60
- function ElementCreationDialog({
69
+ function ElementSaveDialog({
61
70
  open,
62
71
  onSave,
72
+ OnUpdate,
63
73
  onClose,
64
74
  type,
65
75
  titleId,
66
76
  prefixIdForGeneratedName,
67
77
  studyUuid,
68
- initDirectory
78
+ initDirectory,
79
+ initialOperation = "CREATE",
80
+ selectorTitleId,
81
+ createLabelId,
82
+ updateLabelId,
83
+ createOnlyMode = false
69
84
  }) {
70
85
  const intl = useIntl();
71
86
  const { snackError } = useSnackMessage();
72
87
  const [directorySelectorOpen, setDirectorySelectorOpen] = useState(false);
73
88
  const [destinationFolder, setDestinationFolder] = useState();
89
+ const [selectedItem, setSelectedItem] = useState();
74
90
  const formMethods = useForm({
75
- defaultValues: emptyFormData,
91
+ defaultValues: {
92
+ ...emptyFormData,
93
+ [FieldConstants.OPERATION_TYPE]: createOnlyMode ? "CREATE" : initialOperation
94
+ },
76
95
  resolver: yupResolver(schema)
77
96
  });
78
97
  const {
79
98
  reset,
99
+ setValue,
100
+ watch,
80
101
  formState: { errors }
81
102
  } = formMethods;
82
- const disableSave = Object.keys(errors).length > 0;
103
+ const operationType = createOnlyMode ? "CREATE" : watch(FieldConstants.OPERATION_TYPE);
104
+ const isCreateMode = operationType === "CREATE";
105
+ const disableSave = Object.keys(errors).length > 0 || isCreateMode && !destinationFolder || !isCreateMode && !selectedItem;
83
106
  const onCancel = useCallback(() => {
84
- reset(emptyFormData);
107
+ reset({ ...emptyFormData, [FieldConstants.OPERATION_TYPE]: initialOperation });
85
108
  onClose();
86
- }, [onClose, reset]);
109
+ }, [onClose, reset, initialOperation]);
87
110
  useEffect(() => {
88
- if (prefixIdForGeneratedName) {
111
+ if (isCreateMode && prefixIdForGeneratedName) {
89
112
  const getCurrentDateTime = () => (/* @__PURE__ */ new Date()).toISOString();
90
113
  const formattedMessage = intl.formatMessage({
91
114
  id: prefixIdForGeneratedName
@@ -99,9 +122,9 @@ function ElementCreationDialog({
99
122
  { keepDefaultValues: true }
100
123
  );
101
124
  }
102
- }, [prefixIdForGeneratedName, intl, reset]);
125
+ }, [prefixIdForGeneratedName, intl, reset, isCreateMode]);
103
126
  useEffect(() => {
104
- if (open && studyUuid) {
127
+ if (open && isCreateMode && studyUuid) {
105
128
  fetchDirectoryElementPath(studyUuid).then((res) => {
106
129
  if (!res || res.length < 2) {
107
130
  snackError({
@@ -118,31 +141,47 @@ function ElementCreationDialog({
118
141
  });
119
142
  });
120
143
  }
121
- }, [studyUuid, open, snackError]);
144
+ }, [studyUuid, open, snackError, isCreateMode]);
122
145
  useEffect(() => {
123
- if (open && initDirectory) {
146
+ if (open && isCreateMode && initDirectory) {
124
147
  setDestinationFolder({
125
148
  id: initDirectory.elementUuid,
126
149
  name: initDirectory.elementName
127
150
  });
128
151
  }
129
- }, [initDirectory, open]);
152
+ }, [initDirectory, open, isCreateMode]);
130
153
  const handleChangeFolder = useCallback(() => {
131
154
  setDirectorySelectorOpen(true);
132
155
  }, []);
133
- const setSelectedFolder = useCallback(
134
- (folder) => {
135
- if ((folder == null ? void 0 : folder.length) > 0 && folder[0].id !== (destinationFolder == null ? void 0 : destinationFolder.id)) {
136
- const { id, name } = folder[0];
137
- setDestinationFolder({ id, name });
156
+ const handleSelection = useCallback(
157
+ (items) => {
158
+ if (isCreateMode) {
159
+ if ((items == null ? void 0 : items.length) > 0 && items[0].id !== (destinationFolder == null ? void 0 : destinationFolder.id)) {
160
+ const { id, name } = items[0];
161
+ setDestinationFolder({ id, name });
162
+ }
163
+ } else if ((items == null ? void 0 : items.length) > 0 && items[0].id !== (selectedItem == null ? void 0 : selectedItem.id)) {
164
+ const { id, name, description, parents } = items[0];
165
+ if (!parents) {
166
+ snackError({
167
+ messageTxt: "errorNoParent",
168
+ headerId: "error"
169
+ });
170
+ return;
171
+ }
172
+ const fullPath = [...parents.map((parent) => parent.name), name].join("/");
173
+ const parentFolderId = parents[parents.length - 1].id;
174
+ setSelectedItem({ id, name, description, parentFolderId, fullPath });
175
+ setValue(FieldConstants.DESCRIPTION, description ?? "", { shouldDirty: true });
176
+ setValue(FieldConstants.NAME, name, { shouldDirty: true });
138
177
  }
139
178
  setDirectorySelectorOpen(false);
140
179
  },
141
- [destinationFolder == null ? void 0 : destinationFolder.id]
180
+ [isCreateMode, destinationFolder == null ? void 0 : destinationFolder.id, selectedItem == null ? void 0 : selectedItem.id, setValue, snackError]
142
181
  );
143
182
  const onSubmit = useCallback(
144
183
  (values) => {
145
- if (destinationFolder) {
184
+ if (isCreateMode && destinationFolder && onSave) {
146
185
  const creationData = {
147
186
  [FieldConstants.NAME]: values.name,
148
187
  [FieldConstants.DESCRIPTION]: values.description ?? "",
@@ -150,14 +189,31 @@ function ElementCreationDialog({
150
189
  [FieldConstants.FOLDER_ID]: destinationFolder.id
151
190
  };
152
191
  onSave(creationData);
192
+ } else if (!isCreateMode && selectedItem && OnUpdate) {
193
+ const updateData = {
194
+ [FieldConstants.ID]: selectedItem.id,
195
+ [FieldConstants.NAME]: values.name,
196
+ [FieldConstants.DESCRIPTION]: values.description ?? "",
197
+ elementFullPath: selectedItem.fullPath,
198
+ parentFolderId: selectedItem.parentFolderId
199
+ };
200
+ OnUpdate(updateData);
153
201
  }
154
202
  },
155
- [onSave, destinationFolder]
203
+ [isCreateMode, onSave, OnUpdate, destinationFolder, selectedItem]
156
204
  );
157
- const folderChooser = /* @__PURE__ */ jsxs(Grid, { container: true, item: true, children: [
158
- /* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(Button, { onClick: handleChangeFolder, variant: "contained", size: "small", children: /* @__PURE__ */ jsx(FormattedMessage, { id: "showSelectDirectoryDialog" }) }) }),
159
- /* @__PURE__ */ jsx(Typography, { m: 1, component: "span", children: /* @__PURE__ */ jsx(Box, { fontWeight: "fontWeightBold", children: destinationFolder ? destinationFolder.name : /* @__PURE__ */ jsx(CircularProgress, {}) }) })
160
- ] });
205
+ const renderChooser = () => {
206
+ if (isCreateMode) {
207
+ return /* @__PURE__ */ jsxs(Grid, { container: true, item: true, children: [
208
+ /* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(Button, { onClick: handleChangeFolder, variant: "contained", size: "small", children: /* @__PURE__ */ jsx(FormattedMessage, { id: "showSelectDirectoryDialog" }) }) }),
209
+ /* @__PURE__ */ jsx(Typography, { m: 1, component: "span", children: /* @__PURE__ */ jsx(Box, { fontWeight: "fontWeightBold", children: destinationFolder ? destinationFolder.name : /* @__PURE__ */ jsx(CircularProgress, {}) }) })
210
+ ] });
211
+ }
212
+ return /* @__PURE__ */ jsxs(Grid, { container: true, item: true, children: [
213
+ /* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(Button, { onClick: handleChangeFolder, variant: "contained", size: "small", children: /* @__PURE__ */ jsx(FormattedMessage, { id: "showSelectDirectoryItemDialog" }) }) }),
214
+ /* @__PURE__ */ jsx(Typography, { m: 1, component: "span", children: /* @__PURE__ */ jsx(Box, { fontWeight: "fontWeightBold", children: selectedItem ? selectedItem.fullPath : null }) })
215
+ ] });
216
+ };
161
217
  return /* @__PURE__ */ jsxs(
162
218
  CustomMuiDialog,
163
219
  {
@@ -170,39 +226,58 @@ function ElementCreationDialog({
170
226
  formMethods,
171
227
  children: [
172
228
  /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 2, marginTop: "auto", direction: "column", children: [
229
+ !createOnlyMode && /* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(
230
+ RadioInput,
231
+ {
232
+ name: FieldConstants.OPERATION_TYPE,
233
+ options: [
234
+ { id: "CREATE", label: intl.formatMessage({ id: createLabelId }) },
235
+ { id: "UPDATE", label: intl.formatMessage({ id: updateLabelId }) }
236
+ ],
237
+ formProps: {
238
+ sx: {
239
+ "& .MuiFormControlLabel-root": {
240
+ marginRight: 15
241
+ }
242
+ }
243
+ }
244
+ }
245
+ ) }),
173
246
  /* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(
174
247
  UniqueNameInput,
175
248
  {
176
249
  name: FieldConstants.NAME,
177
250
  label: "name",
178
251
  elementType: type,
179
- activeDirectory: destinationFolder == null ? void 0 : destinationFolder.id,
252
+ currentName: !isCreateMode ? selectedItem == null ? void 0 : selectedItem.name : void 0,
253
+ activeDirectory: isCreateMode ? destinationFolder == null ? void 0 : destinationFolder.id : selectedItem == null ? void 0 : selectedItem.parentFolderId,
180
254
  autoFocus: true
181
255
  }
182
256
  ) }),
183
257
  /* @__PURE__ */ jsx(Grid, { item: true, children: /* @__PURE__ */ jsx(DescriptionField, {}) }),
184
- folderChooser
258
+ renderChooser()
185
259
  ] }),
186
260
  /* @__PURE__ */ jsx(
187
261
  DirectoryItemSelector,
188
262
  {
189
263
  open: directorySelectorOpen,
190
- onClose: setSelectedFolder,
191
- types: [ElementType.DIRECTORY],
192
- onlyLeaves: false,
264
+ onClose: handleSelection,
265
+ types: isCreateMode ? [ElementType.DIRECTORY] : [type],
266
+ onlyLeaves: isCreateMode ? false : void 0,
193
267
  multiSelect: false,
194
268
  validationButtonText: intl.formatMessage({
195
269
  id: "validate"
196
270
  }),
197
271
  title: intl.formatMessage({
198
- id: "showSelectDirectoryDialog"
272
+ id: isCreateMode ? "showSelectDirectoryDialog" : selectorTitleId
199
273
  })
200
- }
274
+ },
275
+ isCreateMode ? destinationFolder == null ? void 0 : destinationFolder.id : selectedItem == null ? void 0 : selectedItem.id
201
276
  )
202
277
  ]
203
278
  }
204
279
  );
205
280
  }
206
281
  export {
207
- ElementCreationDialog
282
+ ElementSaveDialog
208
283
  };
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Copyright (c) 2024, RTE (http://www.rte-france.com)
2
+ * Copyright (c) 2025, RTE (http://www.rte-france.com)
3
3
  * This Source Code Form is subject to the terms of the Mozilla Public
4
4
  * License, v. 2.0. If a copy of the MPL was not distributed with this
5
5
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
6
  */
7
- export * from './ElementCreationDialog';
7
+ export * from './ElementSaveDialog';
@@ -0,0 +1,4 @@
1
+ import { ElementSaveDialog } from "./ElementSaveDialog.js";
2
+ export {
3
+ ElementSaveDialog
4
+ };
@@ -6,6 +6,6 @@
6
6
  */
7
7
  export * from './customMuiDialog/CustomMuiDialog';
8
8
  export * from './descriptionModificationDialog';
9
- export * from './elementCreationDialog';
9
+ export * from './elementSaveDialog';
10
10
  export * from './modifyElementSelection';
11
11
  export * from './popupConfirmationDialog';
@@ -1,12 +1,12 @@
1
1
  import { CustomMuiDialog, unscrollableDialogStyles } from "./customMuiDialog/CustomMuiDialog.js";
2
2
  import { DescriptionModificationDialog } from "./descriptionModificationDialog/DescriptionModificationDialog.js";
3
- import { ElementCreationDialog } from "./elementCreationDialog/ElementCreationDialog.js";
3
+ import { ElementSaveDialog } from "./elementSaveDialog/ElementSaveDialog.js";
4
4
  import { ModifyElementSelection } from "./modifyElementSelection/ModifyElementSelection.js";
5
5
  import { PopupConfirmationDialog } from "./popupConfirmationDialog/PopupConfirmationDialog.js";
6
6
  export {
7
7
  CustomMuiDialog,
8
8
  DescriptionModificationDialog,
9
- ElementCreationDialog,
9
+ ElementSaveDialog,
10
10
  ModifyElementSelection,
11
11
  PopupConfirmationDialog,
12
12
  unscrollableDialogStyles
@@ -124,6 +124,7 @@ function DirectoryItemSelector({
124
124
  return {
125
125
  id: e.elementUuid,
126
126
  name: e.elementName,
127
+ description: e.description,
127
128
  specificMetadata: e.specificMetadata,
128
129
  icon: getFileIcon(e.type, styles.icon),
129
130
  children: e.type === ElementType.DIRECTORY ? convertChildren(e.children) : void 0,
@@ -137,6 +138,7 @@ function DirectoryItemSelector({
137
138
  return {
138
139
  id: e.elementUuid,
139
140
  name: e.elementName,
141
+ description: e.description,
140
142
  icon: getFileIcon(e.type, styles.icon),
141
143
  children: e.type === ElementType.DIRECTORY ? convertChildren(nodeMap.current[e.elementUuid].children) : void 0,
142
144
  childrenCount: e.type === ElementType.DIRECTORY ? e.subdirectoriesCount : void 0
@@ -9,7 +9,7 @@ import { ExpertFilterForm } from "./expert/ExpertFilterForm.js";
9
9
  import { FilterType } from "./constants/FilterConstants.js";
10
10
  import { unscrollableDialogStyles } from "../dialogs/customMuiDialog/CustomMuiDialog.js";
11
11
  import "../dialogs/descriptionModificationDialog/DescriptionModificationDialog.js";
12
- import "../dialogs/elementCreationDialog/ElementCreationDialog.js";
12
+ import "../dialogs/elementSaveDialog/ElementSaveDialog.js";
13
13
  import "react-intl";
14
14
  import "@mui/icons-material";
15
15
  import "../treeViewFinder/TreeViewFinder.js";
@@ -14,7 +14,7 @@ import { FilterType } from "../constants/FilterConstants.js";
14
14
  import { CustomReactQueryBuilder } from "../../inputs/reactQueryBuilder/CustomReactQueryBuilder.js";
15
15
  import { unscrollableDialogStyles } from "../../dialogs/customMuiDialog/CustomMuiDialog.js";
16
16
  import "../../dialogs/descriptionModificationDialog/DescriptionModificationDialog.js";
17
- import "../../dialogs/elementCreationDialog/ElementCreationDialog.js";
17
+ import "../../dialogs/elementSaveDialog/ElementSaveDialog.js";
18
18
  import "react-intl";
19
19
  import "@mui/icons-material";
20
20
  import "../../treeViewFinder/TreeViewFinder.js";
@@ -20,7 +20,7 @@ import { ModifyElementSelection } from "../../dialogs/modifyElementSelection/Mod
20
20
  import { exportFilter } from "../../../services/study.js";
21
21
  import { unscrollableDialogStyles } from "../../dialogs/customMuiDialog/CustomMuiDialog.js";
22
22
  import "../../dialogs/descriptionModificationDialog/DescriptionModificationDialog.js";
23
- import "../../dialogs/elementCreationDialog/ElementCreationDialog.js";
23
+ import "../../dialogs/elementSaveDialog/ElementSaveDialog.js";
24
24
  import "@mui/material/Dialog";
25
25
  import "@mui/material/DialogTitle";
26
26
  import "@mui/material/DialogContent";
@@ -15,7 +15,7 @@ import { CUSTOM_AGGRID_THEME, styles } from "./customAGGrid/customAggrid.style.j
15
15
  import { CustomAGGrid } from "./customAGGrid/customAggrid.js";
16
16
  import { CustomMuiDialog, unscrollableDialogStyles } from "./dialogs/customMuiDialog/CustomMuiDialog.js";
17
17
  import { DescriptionModificationDialog } from "./dialogs/descriptionModificationDialog/DescriptionModificationDialog.js";
18
- import { ElementCreationDialog } from "./dialogs/elementCreationDialog/ElementCreationDialog.js";
18
+ import { ElementSaveDialog } from "./dialogs/elementSaveDialog/ElementSaveDialog.js";
19
19
  import { ModifyElementSelection } from "./dialogs/modifyElementSelection/ModifyElementSelection.js";
20
20
  import { PopupConfirmationDialog } from "./dialogs/popupConfirmationDialog/PopupConfirmationDialog.js";
21
21
  import { DirectoryItemSelector } from "./directoryItemSelector/DirectoryItemSelector.js";
@@ -144,7 +144,7 @@ export {
144
144
  EXPERT_FILTER_EQUIPMENTS,
145
145
  EXPERT_FILTER_FIELDS,
146
146
  EXPERT_FILTER_QUERY,
147
- ElementCreationDialog,
147
+ ElementSaveDialog,
148
148
  ElementSearchDialog,
149
149
  ElementSearchInput,
150
150
  ElementValueEditor,
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { useState, useEffect } from "react";
3
3
  import { FormattedMessage } from "react-intl";
4
4
  import { Box, Button } from "@mui/material";
5
5
  import AddIcon from "@mui/icons-material/ControlPoint";
@@ -22,6 +22,11 @@ function DescriptionField({ expandingTextSx }) {
22
22
  setIsDescriptionFieldVisible(false);
23
23
  setValue(FieldConstants.DESCRIPTION, "", { shouldDirty: true });
24
24
  };
25
+ useEffect(() => {
26
+ if (description) {
27
+ setIsDescriptionFieldVisible(true);
28
+ }
29
+ }, [description]);
25
30
  return /* @__PURE__ */ jsx(Box, { children: !isDescriptionFieldVisible ? /* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(AddIcon, {}), onClick: handleOpenDescription, children: /* @__PURE__ */ jsx(FormattedMessage, { id: "AddDescription" }) }) : /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "flex-start" }, children: [
26
31
  /* @__PURE__ */ jsx(
27
32
  ExpandingTextField,
@@ -9,10 +9,11 @@ export interface UniqueNameInputProps {
9
9
  onManualChangeCallback?: () => void;
10
10
  formProps?: Omit<TextFieldProps, 'value' | 'onChange' | 'name' | 'label' | 'inputRef' | 'inputProps' | 'InputProps'>;
11
11
  activeDirectory?: UUID;
12
+ currentName?: string;
12
13
  sx?: SxProps<Theme>;
13
14
  fullWidth?: boolean;
14
15
  }
15
16
  /**
16
17
  * Input component that constantly check if the field's value is available or not
17
18
  */
18
- export declare function UniqueNameInput({ name, label, elementType, autoFocus, onManualChangeCallback, formProps, activeDirectory, sx, fullWidth, }: Readonly<UniqueNameInputProps>): import("react/jsx-runtime").JSX.Element;
19
+ export declare function UniqueNameInput({ name, label, elementType, autoFocus, onManualChangeCallback, formProps, currentName, activeDirectory, sx, fullWidth, }: Readonly<UniqueNameInputProps>): import("react/jsx-runtime").JSX.Element;
@@ -24,6 +24,7 @@ function UniqueNameInput({
24
24
  autoFocus,
25
25
  onManualChangeCallback,
26
26
  formProps,
27
+ currentName = "",
27
28
  activeDirectory,
28
29
  sx,
29
30
  fullWidth = true
@@ -50,7 +51,7 @@ function UniqueNameInput({
50
51
  const directory = selectedDirectory || activeDirectory;
51
52
  const handleCheckName = useCallback(
52
53
  (nameValue) => {
53
- if (nameValue) {
54
+ if (nameValue !== currentName && directory) {
54
55
  elementAlreadyExists(directory, nameValue, elementType).then((alreadyExist) => {
55
56
  if (alreadyExist) {
56
57
  setError(name, {
@@ -68,9 +69,11 @@ function UniqueNameInput({
68
69
  clearErrors("root.isValidating");
69
70
  trigger("root.isValidating");
70
71
  });
72
+ } else {
73
+ trigger("root.isValidating");
71
74
  }
72
75
  },
73
- [setError, clearErrors, name, elementType, directory, trigger]
76
+ [currentName, directory, elementType, setError, name, clearErrors, trigger]
74
77
  );
75
78
  const debouncedHandleCheckName = useDebounce(handleCheckName, 700);
76
79
  useEffect(() => {
@@ -1,13 +1,16 @@
1
1
  import { ReactElement } from 'react';
2
2
  import { ButtonProps, ModalProps } from '@mui/material';
3
3
  import { TreeViewClasses } from '@mui/x-tree-view';
4
+ import { UUID } from 'crypto';
4
5
  export declare const generateTreeViewFinderClass: (className: string) => string;
5
6
  export interface TreeViewFinderNodeProps {
6
- id: string;
7
+ id: UUID;
7
8
  name: string;
9
+ description?: string;
8
10
  icon?: ReactElement;
9
11
  childrenCount?: number;
10
12
  children?: TreeViewFinderNodeProps[];
13
+ parents?: TreeViewFinderNodeProps[];
11
14
  }
12
15
  export interface TreeViewFinderProps {
13
16
  defaultExpanded?: string[];
@@ -28,4 +31,4 @@ export interface TreeViewFinderProps {
28
31
  onTreeBrowse?: (nodeId: string) => void;
29
32
  sortMethod?: (a: TreeViewFinderNodeProps, b: TreeViewFinderNodeProps) => number;
30
33
  }
31
- export declare const TreeViewFinder: import('@emotion/styled').StyledComponent<TreeViewFinderProps & import('@mui/system').MUIStyledCommonProps<import('@mui/material').Theme>, {}, {}>;
34
+ export declare const TreeViewFinder: import('@emotion/styled').StyledComponent<Readonly<TreeViewFinderProps> & import('@mui/system').MUIStyledCommonProps<import('@mui/material').Theme>, {}, {}>;
@@ -79,6 +79,24 @@ function TreeViewFinderComponant(props) {
79
79
  });
80
80
  return newMapPrintedNodes;
81
81
  }, []);
82
+ const findParents = (nodeId, nodes, parentPath = []) => {
83
+ let result = null;
84
+ nodes.some((node) => {
85
+ if (node.id === nodeId) {
86
+ result = parentPath;
87
+ return true;
88
+ }
89
+ if (node.children) {
90
+ const childResult = findParents(nodeId, node.children, [...parentPath, node]);
91
+ if (childResult) {
92
+ result = childResult;
93
+ return true;
94
+ }
95
+ }
96
+ return false;
97
+ });
98
+ return result;
99
+ };
82
100
  useEffect(() => {
83
101
  const newMapPrintedNodes = computeMapPrintedNodes(data);
84
102
  setMapPrintedNodes(newMapPrintedNodes);
@@ -87,9 +105,17 @@ function TreeViewFinderComponant(props) {
87
105
  if (!selected) {
88
106
  return [];
89
107
  }
90
- return selected == null ? void 0 : selected.map((nodeId) => {
91
- return mapPrintedNodes[nodeId];
92
- });
108
+ return selected.map((nodeId) => {
109
+ const selectedNode = mapPrintedNodes[nodeId];
110
+ if (!selectedNode) {
111
+ return null;
112
+ }
113
+ const parents = findParents(nodeId, data ?? []);
114
+ return {
115
+ ...selectedNode,
116
+ parents: parents ?? []
117
+ };
118
+ }).filter((node) => node !== null);
93
119
  };
94
120
  const handleNodeToggle = (_e, nodeIds) => {
95
121
  nodeIds.every((nodeId) => {
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import { CUSTOM_AGGRID_THEME, styles } from "./components/customAGGrid/customAgg
16
16
  import { CustomAGGrid } from "./components/customAGGrid/customAggrid.js";
17
17
  import { CustomMuiDialog, unscrollableDialogStyles } from "./components/dialogs/customMuiDialog/CustomMuiDialog.js";
18
18
  import { DescriptionModificationDialog } from "./components/dialogs/descriptionModificationDialog/DescriptionModificationDialog.js";
19
- import { ElementCreationDialog } from "./components/dialogs/elementCreationDialog/ElementCreationDialog.js";
19
+ import { ElementSaveDialog } from "./components/dialogs/elementSaveDialog/ElementSaveDialog.js";
20
20
  import { ModifyElementSelection } from "./components/dialogs/modifyElementSelection/ModifyElementSelection.js";
21
21
  import { PopupConfirmationDialog } from "./components/dialogs/popupConfirmationDialog/PopupConfirmationDialog.js";
22
22
  import { DirectoryItemSelector } from "./components/directoryItemSelector/DirectoryItemSelector.js";
@@ -234,7 +234,7 @@ export {
234
234
  EXPERT_FILTER_EQUIPMENTS,
235
235
  EXPERT_FILTER_FIELDS,
236
236
  EXPERT_FILTER_QUERY,
237
- ElementCreationDialog,
237
+ ElementSaveDialog,
238
238
  ElementSearchDialog,
239
239
  ElementSearchInput,
240
240
  ElementType,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gridsuite/commons-ui",
3
- "version": "0.89.4",
3
+ "version": "0.91.1",
4
4
  "description": "common react components for gridsuite applications",
5
5
  "author": "gridsuite team",
6
6
  "homepage": "https://github.com/gridsuite",
@@ -1,28 +0,0 @@
1
- import { UUID } from 'crypto';
2
- import { ElementAttributes, ElementType, FieldConstants } from '../../../utils';
3
- interface FormData {
4
- [FieldConstants.NAME]: string;
5
- [FieldConstants.DESCRIPTION]: string;
6
- }
7
- export interface IElementCreationDialog extends FormData {
8
- [FieldConstants.FOLDER_NAME]: string;
9
- [FieldConstants.FOLDER_ID]: UUID;
10
- }
11
- export type ElementCreationDialogProps = {
12
- open: boolean;
13
- onSave: (data: IElementCreationDialog) => void;
14
- onClose: () => void;
15
- type: ElementType;
16
- titleId: string;
17
- prefixIdForGeneratedName?: string;
18
- } & ({
19
- /** starting directory can be the same as a given study */
20
- studyUuid: UUID;
21
- initDirectory?: never;
22
- } | {
23
- studyUuid?: never;
24
- /** or directly a given directory */
25
- initDirectory: ElementAttributes;
26
- });
27
- export declare function ElementCreationDialog({ open, onSave, onClose, type, titleId, prefixIdForGeneratedName, studyUuid, initDirectory, }: Readonly<ElementCreationDialogProps>): import("react/jsx-runtime").JSX.Element;
28
- export {};
@@ -1,4 +0,0 @@
1
- import { ElementCreationDialog } from "./ElementCreationDialog.js";
2
- export {
3
- ElementCreationDialog
4
- };