@gridsuite/commons-ui 0.89.2 → 0.91.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/contingencyList/criteriaBased/CriteriaBasedForm.js +1 -1
- package/dist/components/dialogs/elementSaveDialog/ElementSaveDialog.d.ts +56 -0
- package/dist/components/dialogs/{elementCreationDialog/ElementCreationDialog.js → elementSaveDialog/ElementSaveDialog.js} +116 -41
- package/dist/components/dialogs/{elementCreationDialog → elementSaveDialog}/index.d.ts +2 -2
- package/dist/components/dialogs/elementSaveDialog/index.js +4 -0
- package/dist/components/dialogs/index.d.ts +1 -1
- package/dist/components/dialogs/index.js +2 -2
- package/dist/components/directoryItemSelector/DirectoryItemSelector.js +2 -0
- package/dist/components/filter/FilterForm.js +1 -1
- package/dist/components/filter/expert/ExpertFilterForm.js +1 -1
- package/dist/components/filter/explicitNaming/ExplicitNamingFilterForm.js +1 -1
- package/dist/components/index.js +2 -2
- package/dist/components/inputs/reactHookForm/selectInputs/SelectInput.js +1 -1
- package/dist/components/inputs/reactHookForm/text/DescriptionField.js +6 -1
- package/dist/components/inputs/reactHookForm/text/UniqueNameInput.d.ts +2 -1
- package/dist/components/inputs/reactHookForm/text/UniqueNameInput.js +5 -2
- package/dist/components/treeViewFinder/TreeViewFinder.d.ts +5 -2
- package/dist/components/treeViewFinder/TreeViewFinder.js +29 -3
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/components/dialogs/elementCreationDialog/ElementCreationDialog.d.ts +0 -28
- 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/
|
|
11
|
+
import "../../dialogs/elementSaveDialog/ElementSaveDialog.js";
|
|
12
12
|
import "react-intl";
|
|
13
13
|
import "@mui/icons-material";
|
|
14
14
|
import "../../treeViewFinder/TreeViewFinder.js";
|
|
@@ -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
|
|
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:
|
|
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
|
|
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
|
|
134
|
-
(
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
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
|
-
|
|
258
|
+
renderChooser()
|
|
185
259
|
] }),
|
|
186
260
|
/* @__PURE__ */ jsx(
|
|
187
261
|
DirectoryItemSelector,
|
|
188
262
|
{
|
|
189
263
|
open: directorySelectorOpen,
|
|
190
|
-
onClose:
|
|
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
|
-
|
|
282
|
+
ElementSaveDialog
|
|
208
283
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
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 './
|
|
7
|
+
export * from './ElementSaveDialog';
|
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export * from './customMuiDialog/CustomMuiDialog';
|
|
8
8
|
export * from './descriptionModificationDialog';
|
|
9
|
-
export * from './
|
|
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 {
|
|
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
|
-
|
|
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/
|
|
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/
|
|
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/
|
|
23
|
+
import "../../dialogs/elementSaveDialog/ElementSaveDialog.js";
|
|
24
24
|
import "@mui/material/Dialog";
|
|
25
25
|
import "@mui/material/DialogTitle";
|
|
26
26
|
import "@mui/material/DialogContent";
|
package/dist/components/index.js
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
-
[
|
|
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:
|
|
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
|
|
91
|
-
|
|
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 {
|
|
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
|
-
|
|
237
|
+
ElementSaveDialog,
|
|
238
238
|
ElementSearchDialog,
|
|
239
239
|
ElementSearchInput,
|
|
240
240
|
ElementType,
|
package/package.json
CHANGED
|
@@ -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 {};
|