@topconsultnpm/sdkui-react 6.20.0-dev3.8 → 6.20.0-dev4.2

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 (40) hide show
  1. package/lib/components/base/TMPopUp.js +4 -0
  2. package/lib/components/base/TMTreeView.js +12 -8
  3. package/lib/components/choosers/TMDataListItemChooser.js +1 -1
  4. package/lib/components/choosers/TMDataListItemFields.js +1 -1
  5. package/lib/components/choosers/TMDataListItemPicker.d.ts +1 -0
  6. package/lib/components/choosers/TMDataListItemPicker.js +5 -1
  7. package/lib/components/choosers/TMUserChooser.js +1 -1
  8. package/lib/components/editors/TMMetadataValues.js +200 -40
  9. package/lib/components/editors/TMTextArea.d.ts +1 -0
  10. package/lib/components/editors/TMTextArea.js +6 -6
  11. package/lib/components/features/documents/TMDcmtForm.js +13 -4
  12. package/lib/components/features/documents/TMFileUploader.js +12 -2
  13. package/lib/components/features/documents/TMMasterDetailDcmts.js +25 -63
  14. package/lib/components/features/documents/TMRelationViewer.js +109 -40
  15. package/lib/components/features/search/TMSearchQueryPanel.js +3 -3
  16. package/lib/components/features/search/TMSearchResult.js +2 -10
  17. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +1 -1
  18. package/lib/components/features/search/TMSearchResultsMenuItems.js +1 -8
  19. package/lib/components/features/search/TMSignatureInfoContent.js +10 -6
  20. package/lib/components/features/tasks/TMTaskFormUtils.js +1 -1
  21. package/lib/components/features/workflow/TMWorkflowPopup.js +9 -19
  22. package/lib/components/features/workflow/diagram/DiagramItemForm.d.ts +2 -0
  23. package/lib/components/features/workflow/diagram/DiagramItemForm.js +32 -25
  24. package/lib/components/features/workflow/diagram/RecipientList.d.ts +3 -1
  25. package/lib/components/features/workflow/diagram/RecipientList.js +13 -9
  26. package/lib/components/features/workflow/diagram/WFDiagram.js +29 -2
  27. package/lib/components/features/workflow/diagram/workflowHelpers.js +31 -19
  28. package/lib/components/viewers/TMMidViewer.js +2 -1
  29. package/lib/components/viewers/TMTidViewer.js +2 -1
  30. package/lib/helper/SDKUI_Globals.d.ts +4 -0
  31. package/lib/helper/SDKUI_Globals.js +9 -1
  32. package/lib/helper/SDKUI_Localizator.d.ts +12 -4
  33. package/lib/helper/SDKUI_Localizator.js +104 -24
  34. package/lib/helper/TMUtils.d.ts +6 -40
  35. package/lib/helper/TMUtils.js +69 -166
  36. package/lib/hooks/useDataUserIdItem.js +2 -2
  37. package/lib/hooks/useRelatedDocuments.js +30 -31
  38. package/package.json +55 -55
  39. package/lib/components/features/search/TMSignSettingsForm.d.ts +0 -9
  40. package/lib/components/features/search/TMSignSettingsForm.js +0 -621
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useState } from "react";
3
- import { SDK_Globals, UserListCacheService, WFEvents, WorkflowCacheService } from '@topconsultnpm/sdk-ts';
3
+ import { ResultTypes, SDK_Globals, UserListCacheService, ValidationItem, WFEvents, WorkflowCacheService } from '@topconsultnpm/sdk-ts';
4
4
  import styled from "styled-components";
5
5
  import { SDKUI_Localizator, IconApply, IconCloseOutline, IconUser, IconInfo, IconSignaturePencil, isSign4TopEnabled, IconCheck, IconCloseCircle, IconStop, taskModalSizes } from "../../../helper";
6
6
  import { TMColors } from "../../../utils/theme";
@@ -10,6 +10,7 @@ import TMModal from "../../base/TMModal";
10
10
  import { TMExceptionBoxManager } from "../../base/TMPopUp";
11
11
  import TMSpinner from "../../base/TMSpinner";
12
12
  import TMUserChooser from "../../choosers/TMUserChooser";
13
+ import TMTextArea from "../../editors/TMTextArea";
13
14
  import ShowAlert from "../../base/TMAlert";
14
15
  import { FormModes } from "../../../ts";
15
16
  import TMTaskForm from "../tasks/TMTaskForm";
@@ -19,17 +20,6 @@ const StyledWorkFlowOperationButtonsContainer = styled.div `
19
20
  gap: 10px;
20
21
  flex-direction: column;
21
22
  `;
22
- const StyledTextArea = styled.textarea `
23
- width: 100%;
24
- height: 100%;
25
- border: 1px solid ${(props) => (props.$isValid ? '#b4b4b4' : TMColors.error)};
26
- border-radius: 10px;
27
- padding: 10px;
28
- &:focus {
29
- outline: none;
30
- border-bottom: 4px solid ${(props) => (props.$isValid ? TMColors.primaryColor : TMColors.error)};
31
- }
32
- `;
33
23
  const CharacterCounter = styled.div `
34
24
  text-align: right;
35
25
  font-size: 0.8rem;
@@ -102,7 +92,7 @@ export const WorkFlowApproveRejectPopUp = ({ TID = 0, DID = 0, deviceType = Devi
102
92
  const workflowAction = isReject === 0 ? SDKUI_Localizator.Approve : SDKUI_Localizator.Reject;
103
93
  const itemCount = selectedItems.length > 0 ? `(${selectedItems.length} workitem)` : '';
104
94
  const title = `${workflowAction} ${itemCount}`;
105
- return (_jsx(TMModal, { title: title, onClose: onClose, width: '600px', height: '270px', isModal: true, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsxs("p", { style: { color: (isReject === 1 && disable) ? TMColors.error : 'black' }, children: [SDKUI_Localizator.CommentText, " ", isReject === 1 && disable && _jsx("span", { children: ` (${SDKUI_Localizator.RequiredField})` }), " "] }), _jsx(StyledTextArea, { maxLength: 200, "$isValid": isReject === 0 ? true : !disable, value: commentValue, onChange: (e) => setCommentValue(e.target.value) }), _jsx(CharacterCounter, { children: `${200 - commentValue.length} ${SDKUI_Localizator.CharactersRemaining}` })] }), _jsx(StyledModalFooter, { children: isReject === 0
95
+ return (_jsx(TMModal, { title: title, onClose: onClose, width: '600px', height: '270px', isModal: true, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx(TMTextArea, { label: SDKUI_Localizator.CommentText, value: commentValue, onValueChanged: (e) => setCommentValue(e.target.value), validationItems: isReject === 1 && disable ? [new ValidationItem(ResultTypes.ERROR, 'comment', SDKUI_Localizator.RequiredField)] : [], maxLength: 200, fillHeight: true }), commentValue.length > 0 && _jsx(CharacterCounter, { children: `${200 - commentValue.length} ${SDKUI_Localizator.CharactersRemaining}` })] }), _jsx(StyledModalFooter, { children: isReject === 0
106
96
  ? _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconApply, {}), caption: SDKUI_Localizator.Approve, disabled: false, onClick: () => completeOrRejectAsync(isReject), advancedColor: TMColors.success })
107
97
  : _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Reject, disabled: disable, onClick: () => { !disable && completeOrRejectAsync(isReject); }, advancedColor: TMColors.error }) })] }) }));
108
98
  };
@@ -110,7 +100,7 @@ export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
110
100
  const [commentValue, setCommentValue] = useState('');
111
101
  const [selectedUserID, setSelectedUserID] = useState([]);
112
102
  const [participants, setParticipants] = useState([]);
113
- const disable = commentValue.length === 0 || !selectedUserID;
103
+ const disable = commentValue.length === 0 || selectedUserID.length === 0;
114
104
  // Determina se siamo nel contesto CtrlWorkflow (quando abbiamo workItemDetail)
115
105
  const isCtrlWorkflowContext = !!workItemDetail;
116
106
  const reAssignWorkFlowAsync = async () => {
@@ -175,9 +165,9 @@ export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
175
165
  // Determina il conteggio degli item da mostrare nel titolo
176
166
  const itemCount = workItemDetail ? 1 : selectedItems.length;
177
167
  const titleSuffix = itemCount > 0 ? ` (${itemCount} workitem)` : '';
178
- return (_jsx(TMModal, { onClose: onClose, width: '600px', height: '270px', isModal: true, title: SDKUI_Localizator.Reassign + titleSuffix, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx(TMUserChooser, { dataSource: participants, values: selectedUserID, onValueChanged: (IDs) => {
168
+ return (_jsx(TMModal, { onClose: onClose, width: '600px', height: '350px', isModal: true, title: SDKUI_Localizator.Reassign + titleSuffix, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx(TMUserChooser, { label: SDKUI_Localizator.AssignTo, dataSource: participants, validationItems: selectedUserID.length === 0 ? [new ValidationItem(ResultTypes.ERROR, 'selectedUser', SDKUI_Localizator.RequiredField)] : [], values: selectedUserID, onValueChanged: (IDs) => {
179
169
  setSelectedUserID(IDs ?? []);
180
- } }), _jsxs("p", { style: { color: commentValue.length === 0 ? TMColors.error : 'black' }, children: [SDKUI_Localizator.CommentText, " ", commentValue.length === 0 && _jsx("span", { children: ` (${SDKUI_Localizator.RequiredField})` }), " "] }), _jsx(StyledTextArea, { maxLength: 200, "$isValid": commentValue.length !== 0, value: commentValue, onChange: (e) => setCommentValue(e.target.value) }), _jsx(CharacterCounter, { children: `${200 - commentValue.length} ${SDKUI_Localizator.CharactersRemaining}` })] }), _jsx(StyledModalFooter, { children: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconUser, { fontSize: 16 }), caption: SDKUI_Localizator.Reassign, disabled: disable, onClick: () => !disable && reAssignWorkFlowAsync(), advancedColor: TMColors.tertiary }) })] }) }));
170
+ } }), _jsx(TMTextArea, { label: SDKUI_Localizator.CommentText, value: commentValue, onValueChanged: (e) => setCommentValue(e.target.value), validationItems: commentValue.length === 0 ? [new ValidationItem(ResultTypes.ERROR, 'comment', SDKUI_Localizator.RequiredField)] : [], maxLength: 200, fillHeight: true, elementStyle: { marginTop: '10px', flex: 1 } }), commentValue.length > 0 && _jsx(CharacterCounter, { children: `${200 - commentValue.length} ${SDKUI_Localizator.CharactersRemaining}` })] }), _jsx(StyledModalFooter, { children: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconUser, { fontSize: 16 }), caption: SDKUI_Localizator.Reassign, disabled: disable, onClick: () => !disable && reAssignWorkFlowAsync(), advancedColor: TMColors.tertiary }) })] }) }));
181
171
  };
182
172
  /**
183
173
  * Modal per forzare l'approvazione di un work item
@@ -208,7 +198,7 @@ export const WorkflowForceApproveModal = ({ detail, onClose, onCompleted }) => {
208
198
  };
209
199
  const userName = detail.toUser?.name ?? detail.to;
210
200
  const title = `Forza completamento - ${userName}`;
211
- return (_jsx(TMModal, { title: title, onClose: onClose, width: '600px', height: '270px', isModal: true, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx("div", { style: { fontWeight: 600, marginBottom: '8px' }, children: "Motivazione (obbligatorio):" }), _jsx(StyledTextArea, { "$isValid": !disable, value: commentValue, onChange: (e) => setCommentValue(e.target.value), placeholder: "Inserisci il motivo della forzatura...", maxLength: 200 }), _jsxs(CharacterCounter, { children: [commentValue.length, "/200"] })] }), _jsx(StyledModalFooter, { children: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconCheck, {}), caption: "Forza approvazione", width: '180px', disabled: disable, onClick: () => !disable && forceApproveAsync(), advancedColor: TMColors.success }) })] }) }));
201
+ return (_jsx(TMModal, { title: title, onClose: onClose, width: '600px', height: '270px', isModal: true, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx(TMTextArea, { label: "Motivazione", value: commentValue, onValueChanged: (e) => setCommentValue(e.target.value), validationItems: disable ? [new ValidationItem(ResultTypes.ERROR, 'comment', SDKUI_Localizator.RequiredField)] : [], placeHolder: "Inserisci il motivo della forzatura...", maxLength: 200, fillHeight: true }), commentValue.length > 0 && _jsxs(CharacterCounter, { children: [commentValue.length, "/200"] })] }), _jsx(StyledModalFooter, { children: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconCheck, {}), caption: "Forza approvazione", width: '180px', disabled: disable, onClick: () => !disable && forceApproveAsync(), advancedColor: TMColors.success }) })] }) }));
212
202
  };
213
203
  /**
214
204
  * Modal per forzare il rifiuto di un work item
@@ -239,7 +229,7 @@ export const WorkflowForceRejectModal = ({ detail, onClose, onCompleted }) => {
239
229
  };
240
230
  const userName = detail.toUser?.name ?? detail.to;
241
231
  const title = `Forza rifiuto - ${userName}`;
242
- return (_jsx(TMModal, { title: title, onClose: onClose, width: '600px', height: '270px', isModal: true, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx("div", { style: { fontWeight: 600, marginBottom: '8px' }, children: "Motivazione (obbligatorio):" }), _jsx(StyledTextArea, { "$isValid": !disable, value: commentValue, onChange: (e) => setCommentValue(e.target.value), placeholder: "Inserisci il motivo del rifiuto...", maxLength: 200 }), _jsxs(CharacterCounter, { children: [commentValue.length, "/200"] })] }), _jsx(StyledModalFooter, { children: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconCloseCircle, {}), caption: "Forza rifiuto", width: '150px', disabled: disable, onClick: () => !disable && forceRejectAsync(), advancedColor: TMColors.error }) })] }) }));
232
+ return (_jsx(TMModal, { title: title, onClose: onClose, width: '600px', height: '270px', isModal: true, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx(TMTextArea, { label: "Motivazione", value: commentValue, onValueChanged: (e) => setCommentValue(e.target.value), validationItems: disable ? [new ValidationItem(ResultTypes.ERROR, 'comment', SDKUI_Localizator.RequiredField)] : [], placeHolder: "Inserisci il motivo del rifiuto...", maxLength: 200, fillHeight: true }), commentValue.length > 0 && _jsxs(CharacterCounter, { children: [commentValue.length, "/200"] })] }), _jsx(StyledModalFooter, { children: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconCloseCircle, {}), caption: "Forza rifiuto", width: '150px', disabled: disable, onClick: () => !disable && forceRejectAsync(), advancedColor: TMColors.error }) })] }) }));
243
233
  };
244
234
  /**
245
235
  * Modal per terminare le istanze workflow selezionate
@@ -278,7 +268,7 @@ export const WorkflowEndInstanceModal = ({ selectedInstances, onClose, onComplet
278
268
  const title = selectedInstances.length === 1
279
269
  ? `${SDKUI_Localizator.WorkflowEndInstance} (DID: ${selectedInstances[0].did})`
280
270
  : `${SDKUI_Localizator.WorkflowEndInstance} (${selectedInstances.length} istanze)`;
281
- return (_jsx(TMModal, { title: title, onClose: onClose, width: '600px', height: '270px', isModal: true, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx("div", { style: { fontWeight: 600, marginBottom: '8px' }, children: "Motivazione (obbligatorio):" }), _jsx(StyledTextArea, { "$isValid": !disable, value: commentValue, onChange: (e) => setCommentValue(e.target.value), placeholder: "Inserisci il motivo della terminazione...", maxLength: 200 }), _jsxs(CharacterCounter, { children: [commentValue.length, "/200"] })] }), _jsx(StyledModalFooter, { children: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconStop, {}), caption: SDKUI_Localizator.WorkflowEndInstance, width: '150px', disabled: disable, onClick: () => !disable && endInstancesAsync(), advancedColor: TMColors.error }) })] }) }));
271
+ return (_jsx(TMModal, { title: title, onClose: onClose, width: '600px', height: '270px', isModal: true, children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx(TMTextArea, { label: "Motivazione", value: commentValue, onValueChanged: (e) => setCommentValue(e.target.value), validationItems: disable ? [new ValidationItem(ResultTypes.ERROR, 'comment', SDKUI_Localizator.RequiredField)] : [], placeHolder: "Inserisci il motivo della terminazione...", maxLength: 200, fillHeight: true }), commentValue.length > 0 && _jsxs(CharacterCounter, { children: [commentValue.length, "/200"] })] }), _jsx(StyledModalFooter, { children: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconStop, {}), caption: SDKUI_Localizator.WorkflowEndInstance, width: '150px', disabled: disable, onClick: () => !disable && endInstancesAsync(), advancedColor: TMColors.error }) })] }) }));
282
272
  };
283
273
  export const WorkFlowMoreInfoPopUp = (props) => {
284
274
  const { fromDTD, DID = 0, TID = 0, deviceType = DeviceType.DESKTOP, onClose, onCompleted, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, triggerBlogRefresh } = props;
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
2
  import { DiagramItem, WfInfo } from './interfaces';
3
+ import { DataListItemDescriptor } from '@topconsultnpm/sdk-ts';
3
4
  interface DiagramItemFormProps {
4
5
  itemToEdit: DiagramItem;
5
6
  wf: WfInfo | null | undefined;
6
7
  onClose: () => void;
7
8
  onApply: (updatedItem: DiagramItem) => void;
9
+ onStatusItemEdited?: (originalItem: DataListItemDescriptor, editedItem: DataListItemDescriptor) => void;
8
10
  }
9
11
  declare const DiagramItemForm: React.FC<DiagramItemFormProps>;
10
12
  export default DiagramItemForm;
@@ -10,7 +10,7 @@ import TMTextBox from '../../../editors/TMTextBox';
10
10
  import TMButton from '../../../base/TMButton';
11
11
  import styled from 'styled-components';
12
12
  import TMQuerySummary from '../../../query/TMQuerySummary';
13
- import { CultureIDs, DcmtTypeListCacheService, FromItem, MetadataDataDomains, SDK_Globals, SearchEngine, Severities, WFAppTypes, WorkItemSetRules } from '@topconsultnpm/sdk-ts';
13
+ import { CultureIDs, DcmtTypeListCacheService, FromItem, MetadataDataDomains, ResultTypes, SDK_Globals, SearchEngine, Severities, WFAppTypes, WorkItemSetRules } from '@topconsultnpm/sdk-ts';
14
14
  import TMLocalizedTextBox from '../../../editors/TMLocalizedTextBox';
15
15
  import TMDataListItemPicker from '../../../choosers/TMDataListItemPicker';
16
16
  import WorkitemRecipientsEditor, { actorsToTos, RecipientsContainer, tosToActors } from './WorkitemRecipientsEditor';
@@ -30,9 +30,16 @@ import { DiagramItemProps, wfDiagramItemValidator } from './workflowHelpers';
30
30
  const FormContainer = styled.div `
31
31
  display: flex;
32
32
  flex-direction: column;
33
- gap: 5px;
33
+ height: 100%;
34
34
  padding: 10px;
35
35
  `;
36
+ const FieldsContainer = styled.div `
37
+ display: flex;
38
+ flex-direction: column;
39
+ gap: 5px;
40
+ flex: 1;
41
+ overflow-y: auto;
42
+ `;
36
43
  const FlexContainer = styled.div `
37
44
  display: flex;
38
45
  align-items: center;
@@ -76,7 +83,7 @@ const APP_TYPES_DATASOURCE = [
76
83
  { value: WFAppTypes.SP, display: "SP" },
77
84
  { value: WFAppTypes.REST, display: "REST" }
78
85
  ];
79
- const DiagramItemForm = ({ itemToEdit, wf, onClose, onApply }) => {
86
+ const DiagramItemForm = ({ itemToEdit, wf, onClose, onApply, onStatusItemEdited }) => {
80
87
  const [localItem, setLocalItem] = useState(itemToEdit);
81
88
  const [localItemOrig] = useState(structuredClone(itemToEdit));
82
89
  const [validationItems, setValidationItems] = useState([]);
@@ -392,7 +399,7 @@ const DiagramItemForm = ({ itemToEdit, wf, onClose, onApply }) => {
392
399
  };
393
400
  // Function to render Status-specific fields
394
401
  const renderStatusFields = () => {
395
- return (_jsx(TMDataListItemPicker, { dataListID: wf?.MStatusDLID, selectedValue: localItem.StatusValue, onItemSelect: handleStatusChange, allowEdit: true }));
402
+ return (_jsx(TMDataListItemPicker, { dataListID: wf?.MStatusDLID, selectedValue: localItem.StatusValue, onItemSelect: handleStatusChange, onItemEdited: onStatusItemEdited, allowEdit: true }));
396
403
  };
397
404
  const renderAppFields = () => {
398
405
  return (_jsxs(_Fragment, { children: [_jsx(TMDropDown, { label: SDKUI_Localizator.WorkflowAppType, dataSource: APP_TYPES_DATASOURCE, value: localItem.AppType, isModifiedWhen: localItem.AppType !== localItemOrig.AppType, validationItems: validationItems.filter(v => v.PropertyName === DiagramItemProps.AppType), onValueChanged: (e) => { handleAppTypeChange(e.target.value); } }), localItem.AppType === WFAppTypes.EXE
@@ -580,38 +587,38 @@ const DiagramItemForm = ({ itemToEdit, wf, onClose, onApply }) => {
580
587
  setDossierTypes(formattedList);
581
588
  });
582
589
  }, [localItem.Type]);
583
- // Gestione di Tos e Tos2
584
- const { andRecipients: tosRecipients } = useMemo(() => {
585
- return tosToActors(localItem.Tos ?? '');
586
- }, [localItem.Tos]);
587
- const { andRecipients: tos2Recipients } = useMemo(() => {
590
+ // Owner = Tos2, Participants = Tos
591
+ const { andRecipients: ownerRecipients } = useMemo(() => {
588
592
  return tosToActors(localItem.Tos2 ?? '');
589
593
  }, [localItem.Tos2]);
590
- const handleAddTosRecipients = useCallback((newRecipients, orValue) => {
591
- const { andRecipients } = tosToActors(localItem.Tos ?? '');
592
- const updatedRecipients = [...andRecipients, ...newRecipients.map(r => ({ ...r, Or: orValue }))];
593
- const newTos = actorsToTos(updatedRecipients);
594
- handleTosChange(newTos);
595
- }, [localItem.Tos, handleTosChange]);
596
- const handleRemoveTosRecipient = useCallback((recipientToRemove) => {
597
- const { andRecipients } = tosToActors(localItem.Tos ?? '');
598
- const updatedRecipients = andRecipients.filter(r => r.ActorType !== recipientToRemove.ActorType || r.ActorID !== recipientToRemove.ActorID);
599
- const newTos = actorsToTos(updatedRecipients);
600
- handleTosChange(newTos);
601
- }, [localItem.Tos, handleTosChange]);
602
- const handleAddTos2Recipients = useCallback((newRecipients, orValue) => {
594
+ const { andRecipients: participantRecipients } = useMemo(() => {
595
+ return tosToActors(localItem.Tos ?? '');
596
+ }, [localItem.Tos]);
597
+ const handleAddOwnerRecipients = useCallback((newRecipients, orValue) => {
603
598
  const { andRecipients } = tosToActors(localItem.Tos2 ?? '');
604
599
  const updatedRecipients = [...andRecipients, ...newRecipients.map(r => ({ ...r, Or: orValue }))];
605
600
  const newTos = actorsToTos(updatedRecipients);
606
601
  handleTos2Change(newTos);
607
602
  }, [localItem.Tos2, handleTos2Change]);
608
- const handleRemoveTos2Recipient = useCallback((recipientToRemove) => {
603
+ const handleRemoveOwnerRecipient = useCallback((recipientToRemove) => {
609
604
  const { andRecipients } = tosToActors(localItem.Tos2 ?? '');
610
605
  const updatedRecipients = andRecipients.filter(r => r.ActorType !== recipientToRemove.ActorType || r.ActorID !== recipientToRemove.ActorID);
611
606
  const newTos = actorsToTos(updatedRecipients);
612
607
  handleTos2Change(newTos);
613
608
  }, [localItem.Tos2, handleTos2Change]);
614
- return (_jsxs(_Fragment, { children: [_jsx(TMTextExpression, { label: `${SDKUI_Localizator.Name} (${SDKUI_Localizator.Dossier})`, value: localItem.PlatformObjName, valueOrig: localItemOrig.PlatformObjName, tid: wf?.MTID, isModifiedWhen: (localItem.PlatformObjName ?? '') !== (localItemOrig.PlatformObjName ?? ''), onValueChanged: handlePlatformObjNameChange }), _jsx(TMDropDown, { dataSource: dossierTypes, label: `${SDKUI_Localizator.Description} (${SDKUI_Localizator.Dossier})`, value: localItem.Value3asInt, isModifiedWhen: (localItem.Value3asInt ?? 0) !== (localItemOrig.Value3asInt ?? 0), onValueChanged: (e) => { handleValue3asIntChange(e.target.value); } }), _jsx(TMTextExpression, { label: `${SDKUI_Localizator.Description} (${SDKUI_Localizator.Dossier})`, value: localItem.PlatformObjDescr, valueOrig: localItemOrig.PlatformObjDescr, tid: wf?.MTID, isModifiedWhen: (localItem.PlatformObjDescr ?? '') !== (localItemOrig.PlatformObjDescr ?? ''), onValueChanged: handlePlatformObjDescrChange }), _jsx(TMCultureIDPicker, { label: SDKUI_Localizator.Format, selectedValue: localItem.FormatCultureID, isModifiedWhen: localItem.FormatCultureID !== localItemOrig.FormatCultureID, openChooserBySingleClick: true, onSelectCultureID: handleFormatCultureIDChange }), _jsx(TMTextExpression, { label: `${SDKUI_Localizator.CommentText} (${SDKUI_Localizator.BlogCase})`, placeHolder: 'Inserisci il valore', rows: 2, value: localItem.Value1asString, valueOrig: localItemOrig.Value1asString, tid: wf?.MTID, isModifiedWhen: (localItem.Value1asString ?? '') !== (localItemOrig.Value1asString ?? ''), onValueChanged: handleValue1asStringChange }), _jsx(TMCheckBox, { value: localItem.Value1asInt ?? 0, label: SDKUI_Localizator.WorkflowAddDcmtAsAttachment, isModifiedWhen: localItem.Value1asInt !== localItemOrig.Value1asInt, onValueChanged: handleValue1asIntChange }), _jsx(TMCheckBox, { value: localItem.Value2asInt ?? 0, label: SDKUI_Localizator.WorkflowAddDcmtToDossier, isModifiedWhen: localItem.Value2asInt !== localItemOrig.Value2asInt, onValueChanged: handleValue2asIntChange }), _jsx(TMCheckBox, { value: localItem.Trunc ?? 0, label: SDKUI_Localizator.TruncateString, isModifiedWhen: localItem.Trunc !== localItemOrig.Trunc, onValueChanged: handleTruncChange }), _jsxs(RecipientsContainer, { children: [_jsx(RecipientList, { recipients: tosRecipients, title: SDKUI_Localizator.OwnerName, tid: wf?.MTID, onAdd: (newRecipients) => handleAddTosRecipients(newRecipients, 0), onRemove: handleRemoveTosRecipient }), _jsx(RecipientList, { recipients: tos2Recipients, title: SDKUI_Localizator.Participants, tid: wf?.MTID, onAdd: (newRecipients) => handleAddTos2Recipients(newRecipients, 0), onRemove: handleRemoveTos2Recipient })] })] }));
609
+ const handleAddParticipantRecipients = useCallback((newRecipients, orValue) => {
610
+ const { andRecipients } = tosToActors(localItem.Tos ?? '');
611
+ const updatedRecipients = [...andRecipients, ...newRecipients.map(r => ({ ...r, Or: orValue }))];
612
+ const newTos = actorsToTos(updatedRecipients);
613
+ handleTosChange(newTos);
614
+ }, [localItem.Tos, handleTosChange]);
615
+ const handleRemoveParticipantRecipient = useCallback((recipientToRemove) => {
616
+ const { andRecipients } = tosToActors(localItem.Tos ?? '');
617
+ const updatedRecipients = andRecipients.filter(r => r.ActorType !== recipientToRemove.ActorType || r.ActorID !== recipientToRemove.ActorID);
618
+ const newTos = actorsToTos(updatedRecipients);
619
+ handleTosChange(newTos);
620
+ }, [localItem.Tos, handleTosChange]);
621
+ return (_jsxs(_Fragment, { children: [_jsx(TMTextExpression, { label: `${SDKUI_Localizator.Name} (${SDKUI_Localizator.Dossier})`, value: localItem.PlatformObjName, valueOrig: localItemOrig.PlatformObjName, tid: wf?.MTID, isModifiedWhen: (localItem.PlatformObjName ?? '') !== (localItemOrig.PlatformObjName ?? ''), onValueChanged: handlePlatformObjNameChange }), _jsx(TMDropDown, { dataSource: dossierTypes, label: SDKUI_Localizator.DossierType, value: localItem.Value3asInt, isModifiedWhen: (localItem.Value3asInt ?? 0) !== (localItemOrig.Value3asInt ?? 0), onValueChanged: (e) => { handleValue3asIntChange(e.target.value); } }), _jsx(TMTextExpression, { label: `${SDKUI_Localizator.Description} (${SDKUI_Localizator.Dossier})`, value: localItem.PlatformObjDescr, valueOrig: localItemOrig.PlatformObjDescr, tid: wf?.MTID, isModifiedWhen: (localItem.PlatformObjDescr ?? '') !== (localItemOrig.PlatformObjDescr ?? ''), onValueChanged: handlePlatformObjDescrChange }), _jsx(TMCultureIDPicker, { label: SDKUI_Localizator.Format, selectedValue: localItem.FormatCultureID, isModifiedWhen: localItem.FormatCultureID !== localItemOrig.FormatCultureID, openChooserBySingleClick: true, onSelectCultureID: handleFormatCultureIDChange }), _jsx(TMTextExpression, { label: `${SDKUI_Localizator.CommentText} (${SDKUI_Localizator.BlogCase})`, placeHolder: 'Inserisci il valore', rows: 2, value: localItem.Value1asString, valueOrig: localItemOrig.Value1asString, tid: wf?.MTID, isModifiedWhen: (localItem.Value1asString ?? '') !== (localItemOrig.Value1asString ?? ''), onValueChanged: handleValue1asStringChange }), _jsx(TMCheckBox, { value: localItem.Value1asInt ?? 0, label: SDKUI_Localizator.WorkflowAddDcmtAsAttachment, isModifiedWhen: localItem.Value1asInt !== localItemOrig.Value1asInt, onValueChanged: handleValue1asIntChange }), _jsx(TMCheckBox, { value: localItem.Value2asInt ?? 0, label: SDKUI_Localizator.WorkflowAddDcmtToDossier, isModifiedWhen: localItem.Value2asInt !== localItemOrig.Value2asInt, onValueChanged: handleValue2asIntChange }), _jsx(TMCheckBox, { value: localItem.Trunc ?? 0, label: SDKUI_Localizator.TruncateString, isModifiedWhen: localItem.Trunc !== localItemOrig.Trunc, onValueChanged: handleTruncChange }), _jsxs(RecipientsContainer, { children: [_jsx(RecipientList, { recipients: ownerRecipients, title: SDKUI_Localizator.OwnerName, tid: wf?.MTID, maxRecipients: 1, validationItems: validationItems.filter(v => v.PropertyName === DiagramItemProps.Tos2), onAdd: (newRecipients) => handleAddOwnerRecipients(newRecipients, 0), onRemove: handleRemoveOwnerRecipient }), _jsx(RecipientList, { recipients: participantRecipients, title: SDKUI_Localizator.Participants, tid: wf?.MTID, onAdd: (newRecipients) => handleAddParticipantRecipients(newRecipients, 0), onRemove: handleRemoveParticipantRecipient })] })] }));
615
622
  };
616
623
  const renderAddPartsFields = () => {
617
624
  const { andRecipients: tosRecipients } = useMemo(() => {
@@ -679,7 +686,7 @@ const DiagramItemForm = ({ itemToEdit, wf, onClose, onApply }) => {
679
686
  default:
680
687
  specificFields = null;
681
688
  }
682
- return (_jsxs(FormContainer, { children: [renderCommonFields(), specificFields, _jsxs(ButtonsContainer, { children: [_jsx(TMButton, { caption: 'Applica', btnStyle: 'advanced', advancedColor: TMColors.tertiary, icon: _jsx(IconApply, {}), showTooltip: false, disabled: !isModified, onClick: handleSave }), _jsx(TMButton, { caption: 'Annulla', btnStyle: 'toolbar', color: 'primary', icon: _jsx(IconUndo, {}), showTooltip: false, disabled: !isModified, onClick: handleCancel })] })] }));
689
+ return (_jsxs(FormContainer, { children: [_jsxs(FieldsContainer, { children: [renderCommonFields(), specificFields] }), _jsxs(ButtonsContainer, { children: [_jsx(TMButton, { caption: 'Applica', btnStyle: 'advanced', advancedColor: TMColors.tertiary, icon: _jsx(IconApply, {}), showTooltip: false, disabled: !isModified || validationItems.some(v => v.ResultType === ResultTypes.ERROR), onClick: handleSave }), _jsx(TMButton, { caption: 'Annulla', btnStyle: 'toolbar', color: 'primary', icon: _jsx(IconUndo, {}), showTooltip: false, disabled: !isModified, onClick: handleCancel })] })] }));
683
690
  };
684
691
  return (_jsx(TMModal, { title: LocalizeDiagramItemType(localItem.Type), onClose: onClose, isModal: true, width: calculatedWidth, height: calculatedHeight, children: renderForm() }));
685
692
  };
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { QueryDescriptor } from '@topconsultnpm/sdk-ts';
2
+ import { QueryDescriptor, ValidationItem } from '@topconsultnpm/sdk-ts';
3
3
  export declare enum WorkItemActorTypes {
4
4
  None = 0,
5
5
  UID = 1,
@@ -19,6 +19,8 @@ interface RecipientListProps {
19
19
  title: string;
20
20
  tid?: number;
21
21
  qd?: QueryDescriptor;
22
+ maxRecipients?: number;
23
+ validationItems?: ValidationItem[];
22
24
  onQDChange?: (newQd: QueryDescriptor | undefined) => void;
23
25
  onAdd: (recipient: WorkItemActor[]) => void;
24
26
  onRemove: (recipient: WorkItemActor) => void;
@@ -7,6 +7,7 @@ import { TMUserChooserForm } from '../../../choosers/TMUserChooser';
7
7
  import { TMGroupChooserForm, TMGroupIdViewer } from '../../../choosers/TMGroupChooser';
8
8
  import { TMMidViewer } from '../../../viewers/TMMidViewer';
9
9
  import { SDK_Globals, SDK_Localizator } from '@topconsultnpm/sdk-ts';
10
+ import TMVilViewer from '../../../base/TMVilViewer';
10
11
  import { useOutsideClick } from '../../../../hooks/useOutsideClick';
11
12
  import { FormModes } from '../../../../ts';
12
13
  import { TMMessageBoxManager, ButtonNames } from '../../../base/TMPopUp';
@@ -70,7 +71,7 @@ const FloatingMenu = styled.div `
70
71
  const FloatingMenuButton = (props) => {
71
72
  return _jsx(TMButton, { width: "100%", ...props });
72
73
  };
73
- const RecipientList = ({ recipients, title, tid, qd, onAdd, onRemove, onQDChange }) => {
74
+ const RecipientList = ({ recipients, title, tid, qd, maxRecipients, validationItems, onAdd, onRemove, onQDChange }) => {
74
75
  const [uiState, setUiState] = useState({
75
76
  isMenuOpen: false,
76
77
  showUserChooser: false,
@@ -102,7 +103,7 @@ const RecipientList = ({ recipients, title, tid, qd, onAdd, onRemove, onQDChange
102
103
  onAdd(recipientsToAdd);
103
104
  }
104
105
  setUiState(prevState => ({ ...prevState, showUserChooser: false }));
105
- }, []);
106
+ }, [onAdd]);
106
107
  const handleGroupChosen = useCallback((IDs) => {
107
108
  if (IDs && IDs.length > 0) {
108
109
  const recipientsToAdd = IDs.map(id => ({
@@ -113,7 +114,7 @@ const RecipientList = ({ recipients, title, tid, qd, onAdd, onRemove, onQDChange
113
114
  onAdd(recipientsToAdd);
114
115
  }
115
116
  setUiState(prevState => ({ ...prevState, showGroupChooser: false }));
116
- }, []);
117
+ }, [onAdd]);
117
118
  const handleMetadataChosen = useCallback((IDs) => {
118
119
  if (IDs && IDs.length > 0) {
119
120
  const recipientsToAdd = IDs.map(item => ({
@@ -124,8 +125,11 @@ const RecipientList = ({ recipients, title, tid, qd, onAdd, onRemove, onQDChange
124
125
  onAdd(recipientsToAdd);
125
126
  }
126
127
  setUiState(prevState => ({ ...prevState, showMetadataChooser: false }));
127
- }, []);
128
+ }, [onAdd]);
129
+ const isMaxReached = maxRecipients !== undefined && recipients.length >= maxRecipients;
128
130
  const handleAddClick = () => {
131
+ if (isMaxReached)
132
+ return;
129
133
  setUiState(prevState => ({ ...prevState, isMenuOpen: !prevState.isMenuOpen }));
130
134
  };
131
135
  const handleRecipientClick = useCallback((index) => {
@@ -195,11 +199,11 @@ const RecipientList = ({ recipients, title, tid, qd, onAdd, onRemove, onQDChange
195
199
  document.removeEventListener('keydown', handleKeyPress);
196
200
  };
197
201
  }, [handleKeyPress]);
198
- return (_jsxs(RecipientsColumn, { children: [_jsxs(HeaderContainer, { children: [_jsx("p", { style: { fontWeight: 600 }, children: title }), _jsx(TMButton, { btnStyle: 'icon', caption: SDKUI_Localizator.AddRecipient, icon: _jsx(IconAdd, {}), onClick: handleAddClick }), uiState.isMenuOpen && renderFloatingMenu()] }), _jsx("div", { style: { height: '150px', overflowY: 'auto', gap: '5px', display: 'flex', flexDirection: 'column' }, children: recipients.map((recipient, index) => (_jsxs(RecipientItem, { "$isSelected": uiState.selectedRecipientIndex === index, onClick: () => handleRecipientClick(index), tabIndex: 0, children: [_jsx(IconDelete, { color: '#c00', cursor: 'pointer', onClick: (e) => {
199
- e.stopPropagation();
200
- onRemove(recipient);
201
- setUiState(prevState => ({ ...prevState, selectedRecipientIndex: null })); // Resetta la selezione
202
- } }), renderActorViewer(recipient)] }, index))) }), uiState.showUserChooser && _jsx(TMUserChooserForm, { allowMultipleSelection: true, allowSorting: true, onClose: () => setUiState(prevState => ({ ...prevState, showUserChooser: false })), onChoose: (IDs) => handleUserChosen(IDs) }), uiState.showGroupChooser && _jsx(TMGroupChooserForm, { allowMultipleSelection: true, allowSorting: true, onClose: () => setUiState(prevState => ({ ...prevState, showGroupChooser: false })), onChoose: (IDs) => handleGroupChosen(IDs) }), uiState.showMetadataChooser && tid && _jsx(TMMetadataChooserForm, { allowMultipleSelection: true, allowSorting: true, tids: [tid], onClose: () => setUiState(prevState => ({ ...prevState, showMetadataChooser: false })), onChoose: (IDs) => handleMetadataChosen(IDs) }), uiState.showQdEditor &&
202
+ return (_jsxs(RecipientsColumn, { children: [_jsxs(HeaderContainer, { children: [_jsx("p", { style: { fontWeight: 600 }, children: title }), _jsx(TMButton, { btnStyle: 'icon', caption: SDKUI_Localizator.AddRecipient, icon: _jsx(IconAdd, {}), onClick: handleAddClick, disabled: isMaxReached }), uiState.isMenuOpen && !isMaxReached && renderFloatingMenu()] }), _jsx(TMVilViewer, { vil: validationItems }), _jsx("div", { style: { height: '150px', overflowY: 'auto', gap: '5px', display: 'flex', flexDirection: 'column' }, children: recipients.map((recipient, index) => (_jsxs(RecipientItem, { "$isSelected": uiState.selectedRecipientIndex === index, onClick: () => handleRecipientClick(index), tabIndex: 0, children: [_jsx("span", { style: { display: 'flex', alignItems: 'center', flexShrink: 0 }, children: _jsx(IconDelete, { color: '#c00', cursor: 'pointer', onClick: (e) => {
203
+ e.stopPropagation();
204
+ onRemove(recipient);
205
+ setUiState(prevState => ({ ...prevState, selectedRecipientIndex: null }));
206
+ } }) }), _jsx("span", { style: { flex: 1, minWidth: 0, display: 'flex', alignItems: 'center' }, children: renderActorViewer(recipient) })] }, index))) }), uiState.showUserChooser && _jsx(TMUserChooserForm, { allowMultipleSelection: true, allowSorting: true, onClose: () => setUiState(prevState => ({ ...prevState, showUserChooser: false })), onChoose: (IDs) => handleUserChosen(IDs) }), uiState.showGroupChooser && _jsx(TMGroupChooserForm, { allowMultipleSelection: true, allowSorting: true, onClose: () => setUiState(prevState => ({ ...prevState, showGroupChooser: false })), onChoose: (IDs) => handleGroupChosen(IDs) }), uiState.showMetadataChooser && tid && _jsx(TMMetadataChooserForm, { allowMultipleSelection: true, allowSorting: true, tids: [tid], onClose: () => setUiState(prevState => ({ ...prevState, showMetadataChooser: false })), onChoose: (IDs) => handleMetadataChosen(IDs) }), uiState.showQdEditor &&
203
207
  _jsx(TMModal, { title: SDKUI_Localizator.QueryDefine, onClose: () => setUiState(prevState => ({ ...prevState, showQdEditor: false })), children: _jsx(TMQueryEditor, { inputData: qd, formMode: FormModes.Update, showDistinct: true, onApplied: handleQdChosen, onClose: () => setUiState(prevState => ({ ...prevState, showQdEditor: false })) }) })] }));
204
208
  };
205
209
  export default RecipientList;
@@ -1343,9 +1343,24 @@ const WFDiagram = ({ xmlDiagramString, currentSetID, allowEdit = true, onDiagram
1343
1343
  const newStatus = connection.OutputStatus === WorkItemStatus.Completed
1344
1344
  ? WorkItemStatus.Rejected
1345
1345
  : WorkItemStatus.Completed;
1346
+ const oppositeStatus = newStatus === WorkItemStatus.Completed
1347
+ ? WorkItemStatus.Rejected
1348
+ : WorkItemStatus.Completed;
1349
+ // Se esiste un'altra connection dallo stesso source con il newStatus,
1350
+ // la si inverte in modo che non esistano mai 2 uscite con lo stesso OutputStatus.
1351
+ const sourceId = connection.Source.ParentDiagramItem.ID;
1352
+ const conflictingConn = wfDiagram.Connections.find(conn => conn.ID !== connectionId &&
1353
+ conn.Source.ParentDiagramItem.ID === sourceId &&
1354
+ conn.OutputStatus === newStatus);
1346
1355
  const updatedDiagram = {
1347
1356
  ...wfDiagram,
1348
- Connections: wfDiagram.Connections.map(conn => conn.ID === connectionId ? { ...conn, OutputStatus: newStatus } : conn)
1357
+ Connections: wfDiagram.Connections.map(conn => {
1358
+ if (conn.ID === connectionId)
1359
+ return { ...conn, OutputStatus: newStatus };
1360
+ if (conflictingConn && conn.ID === conflictingConn.ID)
1361
+ return { ...conn, OutputStatus: oppositeStatus };
1362
+ return conn;
1363
+ })
1349
1364
  };
1350
1365
  updateDiagram(updatedDiagram);
1351
1366
  setWfDiagram(updatedDiagram);
@@ -1628,6 +1643,18 @@ const WFDiagram = ({ xmlDiagramString, currentSetID, allowEdit = true, onDiagram
1628
1643
  const newDiagram = { ...wfDiagram, DiagramItems: updatedDiagramItems };
1629
1644
  updateDiagram(newDiagram);
1630
1645
  }, [wfDiagram, updateDiagram]);
1646
+ const handleStatusItemEdited = useCallback((originalItem, editedItem) => {
1647
+ if (!wfDiagram)
1648
+ return;
1649
+ const updatedDiagramItems = wfDiagram.DiagramItems.map(item => {
1650
+ if (item.Type === DiagramItemTypes.Status && item.StatusValue === originalItem.value) {
1651
+ return { ...item, ItemName: editedItem.name || '', StatusValue: editedItem.value };
1652
+ }
1653
+ return item;
1654
+ });
1655
+ const newDiagram = { ...wfDiagram, DiagramItems: updatedDiagramItems };
1656
+ updateDiagram(newDiagram);
1657
+ }, [wfDiagram, updateDiagram]);
1631
1658
  const handleUpdateConnection = useCallback((updatedConnection) => {
1632
1659
  setWfDiagram(prevDiagram => {
1633
1660
  if (!prevDiagram)
@@ -1909,7 +1936,7 @@ const WFDiagram = ({ xmlDiagramString, currentSetID, allowEdit = true, onDiagram
1909
1936
  // Determina se questa è la connessione che stiamo trascinando
1910
1937
  const isThisConnectionBeingDragged = isDraggingExistingConnectionEndpoint && draggingConnectionId === connection.ID;
1911
1938
  return (_jsx(ConnectionComponent, { connection: connection, isSelected: selectedConnections.has(connection.ID), sourcePoint: sourcePoint, sinkPoint: sinkPoint, isTemporary: isThisConnectionBeingDragged, onClick: handleConnectionClick, onDoubleClick: handleDoubleClickConnection, onConnectionEndpointMouseDown: handleConnectionEndpointMouseDown, onContextMenu: handleConnectionContextMenu }, connection.ID));
1912
- }), isDrawingConnection && tempConnectionPathData && (_jsx(TempConnectionPath, { d: tempConnectionPathData })), isDraggingExistingConnectionEndpoint && tempConnectionPathData && (_jsx(TempConnectionPath, { d: tempConnectionPathData })), isDrawingSelectionRect && currentSelectionRect && (_jsx(SelectionRect, { x: currentSelectionRect.x, y: currentSelectionRect.y, width: currentSelectionRect.width, height: currentSelectionRect.height }))] }) })) : (_jsx(DiagramMessage, { children: `${SDKUI_Localizator.WorkflowDiagramMissingOrInvalid} ...` })) }), isModalOpen && itemToEdit && (_jsx(DiagramItemForm, { itemToEdit: itemToEdit, wf: wfDiagram?.Info, onClose: handleCloseModal, onApply: handleUpdateDiagramItem })), isConnectionModalOpen && connectionToEdit && (_jsx(ConnectionForm, { connectionToEdit: connectionToEdit, onClose: () => setIsConnectionModalOpen(false), onApply: handleUpdateConnection })), _jsx(TMContextMenu, { items: connectionContextMenuItems, externalControl: {
1939
+ }), isDrawingConnection && tempConnectionPathData && (_jsx(TempConnectionPath, { d: tempConnectionPathData })), isDraggingExistingConnectionEndpoint && tempConnectionPathData && (_jsx(TempConnectionPath, { d: tempConnectionPathData })), isDrawingSelectionRect && currentSelectionRect && (_jsx(SelectionRect, { x: currentSelectionRect.x, y: currentSelectionRect.y, width: currentSelectionRect.width, height: currentSelectionRect.height }))] }) })) : (_jsx(DiagramMessage, { children: `${SDKUI_Localizator.WorkflowDiagramMissingOrInvalid} ...` })) }), isModalOpen && itemToEdit && (_jsx(DiagramItemForm, { itemToEdit: itemToEdit, wf: wfDiagram?.Info, onClose: handleCloseModal, onApply: handleUpdateDiagramItem, onStatusItemEdited: handleStatusItemEdited })), isConnectionModalOpen && connectionToEdit && (_jsx(ConnectionForm, { connectionToEdit: connectionToEdit, onClose: () => setIsConnectionModalOpen(false), onApply: handleUpdateConnection })), _jsx(TMContextMenu, { items: connectionContextMenuItems, externalControl: {
1913
1940
  visible: contextMenuConnectionId !== null,
1914
1941
  position: connectionContextMenuPosition,
1915
1942
  onClose: closeConnectionContextMenu
@@ -1,6 +1,7 @@
1
- import { PlatformObjectValidator, QueryValidatorOptions, ResultTypes, TMPropertyNames, ValidationItem, WorkItemStatus } from '@topconsultnpm/sdk-ts';
1
+ import { PlatformObjectValidator, QueryValidatorOptions, ResultTypes, ValidationItem, WorkItemStatus } from '@topconsultnpm/sdk-ts';
2
2
  import { DiagramItemTypes, ArrowSymbol } from './interfaces'; // Assicurati che il percorso sia corretto
3
- import { generateUUID, SDKUI_Localizator } from '../../../../helper';
3
+ import { generateUUID, LocalizeDiagramItemType, SDKUI_Localizator } from '../../../../helper';
4
+ import { tosToActors } from './WorkitemRecipientsEditor';
4
5
  /**
5
6
  * Calculates the angle in degrees of an arrow based on two points.
6
7
  * @param prevPoint The previous point on the trajectory.
@@ -318,72 +319,73 @@ export const workflowValidator = async (wf) => {
318
319
  const vil = await wfDiagramItemValidator(item);
319
320
  vil.forEach(v => v.PropertyScopes = ['diagramItem']);
320
321
  validationItems.push(...vil);
322
+ const itemType = LocalizeDiagramItemType(item.Type);
321
323
  switch (item.Type) {
322
324
  case DiagramItemTypes.Start:
323
325
  if (wf.Connections.filter(c => c.Source.ParentDiagramItem.ID === item.ID).length === 0) {
324
- validationItems.push(new ValidationItem(ResultTypes.ERROR, `item-${item.ID}`, SDKUI_Localizator.WorkflowDiagramStartMustHaveOutgoing, ['diagramItem']));
326
+ validationItems.push(new ValidationItem(ResultTypes.ERROR, itemType, SDKUI_Localizator.WorkflowDiagramStartMustHaveOutgoing, ['diagramItem']));
325
327
  }
326
328
  if (wf.Connections.filter(c => c.Sink.ParentDiagramItem.ID === item.ID).length > 0) {
327
- validationItems.push(new ValidationItem(ResultTypes.ERROR, `item-${item.ID}`, SDKUI_Localizator.WorkflowDiagramStartCannotHaveIncoming, ['diagramItem']));
329
+ validationItems.push(new ValidationItem(ResultTypes.ERROR, itemType, SDKUI_Localizator.WorkflowDiagramStartCannotHaveIncoming, ['diagramItem']));
328
330
  }
329
331
  break;
330
332
  case DiagramItemTypes.End:
331
333
  case DiagramItemTypes.Exit:
332
334
  if (wf.Connections.filter(c => c.Sink.ParentDiagramItem.ID === item.ID).length === 0) {
333
- validationItems.push(new ValidationItem(ResultTypes.ERROR, `item-${item.ID}`, `L'elemento '${DiagramItemTypes[item.Type]}' deve avere almeno una connessione in ingresso.`, ['diagramItem']));
335
+ validationItems.push(new ValidationItem(ResultTypes.ERROR, itemType, SDKUI_Localizator.WorkflowDiagramElementMustHaveIncoming.replaceParams(itemType), ['diagramItem']));
334
336
  }
335
337
  if (wf.Connections.filter(c => c.Source.ParentDiagramItem.ID === item.ID).length > 0) {
336
- validationItems.push(new ValidationItem(ResultTypes.ERROR, `item-${item.ID}`, `L'elemento '${DiagramItemTypes[item.Type]}' non può avere connessioni in uscita.`, ['diagramItem']));
338
+ validationItems.push(new ValidationItem(ResultTypes.ERROR, itemType, SDKUI_Localizator.WorkflowDiagramElementCannotHaveOutgoing.replaceParams(itemType), ['diagramItem']));
337
339
  }
338
340
  break;
339
341
  case DiagramItemTypes.Condition:
340
342
  if (wf.Connections.filter(c => c.Source.ParentDiagramItem.ID === item.ID).length !== 2) {
341
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, SDKUI_Localizator.WorkflowDiagramConditionTwoOutgoing, ['diagramItem']));
343
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramConditionTwoOutgoing.replaceParams(item.ItemName), ['diagramItem']));
342
344
  }
343
345
  if (wf.Connections.filter(c => c.Sink.ParentDiagramItem.ID === item.ID).length === 0) {
344
- validationItems.push(new ValidationItem(ResultTypes.ERROR, `item-${item.ID}`, SDKUI_Localizator.WorkflowDiagramConditionMustHaveIncoming, ['diagramItem']));
346
+ validationItems.push(new ValidationItem(ResultTypes.ERROR, itemType, SDKUI_Localizator.WorkflowDiagramConditionMustHaveIncoming.replaceParams(item.ItemName), ['diagramItem']));
345
347
  }
346
348
  break;
347
349
  case DiagramItemTypes.Approval:
348
350
  case DiagramItemTypes.ExecTask:
349
351
  case DiagramItemTypes.DataEntry:
350
352
  if (wf.Connections.filter(c => c.Source.ParentDiagramItem.ID === item.ID).length !== 2) {
351
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, SDKUI_Localizator.WorkflowDiagramElementShouldHaveTwoOutgoing.replace('{0}', item.ItemName), ['diagramItem']));
353
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveTwoOutgoing.replaceParams(item.ItemName), ['diagramItem']));
352
354
  }
353
355
  if (wf.Connections.filter(c => c.Sink.ParentDiagramItem.ID === item.ID).length === 0) {
354
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, SDKUI_Localizator.WorkflowDiagramElementShouldHaveIncoming.replace('{0}', item.ItemName), ['diagramItem']));
356
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveIncoming.replaceParams(item.ItemName), ['diagramItem']));
355
357
  }
356
358
  break;
357
359
  case DiagramItemTypes.Notification:
358
360
  if (wf.Connections.filter(c => c.Source.ParentDiagramItem.ID === item.ID).length === 0) {
359
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, `L'elemento '${item.ItemName}' dovrebbe avere almeno una connessione in uscita.`, ['diagramItem']));
361
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveOutgoing.replaceParams(item.ItemName), ['diagramItem']));
360
362
  }
361
363
  if (wf.Connections.filter(c => c.Sink.ParentDiagramItem.ID === item.ID).length === 0) {
362
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, `L'elemento '${item.ItemName}' deve avere almeno una connessione in ingresso.`, ['diagramItem']));
364
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveIncoming.replaceParams(item.ItemName), ['diagramItem']));
363
365
  }
364
366
  break;
365
367
  case DiagramItemTypes.UpdateDcmt:
366
368
  if (wf.Connections.filter(c => c.Source.ParentDiagramItem.ID === item.ID).length !== 1) {
367
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, `L'elemento '${item.ItemName}' dovrebbe avere esattamente una connessione in uscita.`, ['diagramItem']));
369
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveOneOutgoing.replaceParams(item.ItemName), ['diagramItem']));
368
370
  }
369
371
  if (wf.Connections.filter(c => c.Sink.ParentDiagramItem.ID === item.ID).length === 0) {
370
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, `L'elemento '${item.ItemName}' deve avere almeno una connessione in ingresso.`, ['diagramItem']));
372
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveIncoming.replaceParams(item.ItemName), ['diagramItem']));
371
373
  }
372
374
  break;
373
375
  case DiagramItemTypes.Status:
374
376
  if (wf.Connections.filter(c => c.Source.ParentDiagramItem.ID === item.ID).length !== 1) {
375
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, `L'elemento '${item.ItemName}' dovrebbe avere esattamente una connessione in uscita.`, ['diagramItem']));
377
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveOneOutgoing.replaceParams(item.ItemName), ['diagramItem']));
376
378
  }
377
379
  if (wf.Connections.filter(c => c.Sink.ParentDiagramItem.ID === item.ID).length === 0) {
378
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, `L'elemento '${item.ItemName}' deve avere almeno una connessione in ingresso.`, ['diagramItem']));
380
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveIncoming.replaceParams(item.ItemName), ['diagramItem']));
379
381
  }
380
382
  break;
381
383
  case DiagramItemTypes.RunApp:
382
384
  if (wf.Connections.filter(c => c.Source.ParentDiagramItem.ID === item.ID).length === 0) {
383
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, `L'elemento '${item.ItemName}' dovrebbe avere almeno una connessione in uscita.`, ['diagramItem']));
385
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveOutgoing.replaceParams(item.ItemName), ['diagramItem']));
384
386
  }
385
387
  if (wf.Connections.filter(c => c.Sink.ParentDiagramItem.ID === item.ID).length === 0) {
386
- validationItems.push(new ValidationItem(ResultTypes.WARNING, `item-${item.ID}`, `L'elemento '${item.ItemName}' deve avere almeno una connessione in ingresso.`, ['diagramItem']));
388
+ validationItems.push(new ValidationItem(ResultTypes.WARNING, itemType, SDKUI_Localizator.WorkflowDiagramElementShouldHaveIncoming.replaceParams(item.ItemName), ['diagramItem']));
387
389
  }
388
390
  break;
389
391
  }
@@ -480,7 +482,17 @@ export const wfDiagramItemValidator = async (d) => {
480
482
  qvo.DoOrderByValidation = false;
481
483
  await PlatformObjectValidator.QueryValidatorAsync(d.QD, vil, qvo);
482
484
  if (d.QD?.where === undefined || d.QD.where.length <= 0) {
483
- vil.push(new ValidationItem(ResultTypes.ERROR, TMPropertyNames.where, "La query della condizione non contiene criteri di selezione", [DiagramItemProps.QD]));
485
+ vil.push(new ValidationItem(ResultTypes.ERROR, LocalizeDiagramItemType(d.Type), `La query della condizione '${d.ItemName}' non contiene criteri di selezione`, [DiagramItemProps.QD]));
486
+ }
487
+ break;
488
+ case DiagramItemTypes.CaseFlow_Create:
489
+ PlatformObjectValidator.RequiredStringValidator(d.ItemName, DiagramItemProps.ItemName, vil, SDKUI_Localizator.Name);
490
+ PlatformObjectValidator.RequiredStringValidator(d.Tos2, DiagramItemProps.Tos2, vil, SDKUI_Localizator.OwnerName);
491
+ if (d.Tos2) {
492
+ const { andRecipients } = tosToActors(d.Tos2);
493
+ if (andRecipients.length > 1) {
494
+ vil.push(new ValidationItem(ResultTypes.ERROR, DiagramItemProps.Tos2, SDKUI_Localizator.WorkflowOnlyOneOwnerAllowed));
495
+ }
484
496
  }
485
497
  break;
486
498
  }
@@ -38,11 +38,12 @@ export const TMMidViewer = ({ isMetadataSelected = false, color, tmSession, tid_
38
38
  color: md?.isRequired == 1 ? 'red' : color,
39
39
  }, children: [showIcon && _jsx(TMMetadataIcon, { isMetadataSelected: isMetadataSelected, tid: tid_mid?.tid, md: md, color: color }), _jsx("p", { title: displayName(), style: {
40
40
  textAlign: 'left',
41
+ margin: 0,
41
42
  marginLeft: showIcon ? '5px' : '',
42
43
  whiteSpace: 'nowrap',
43
44
  overflow: 'hidden',
44
45
  textOverflow: 'ellipsis'
45
- }, children: displayName() }), showId && _jsx("p", { style: { padding: '0px 3px' }, children: `(MID: ${tid_mid?.mid})` })] }));
46
+ }, children: displayName() }), showId && _jsx("p", { style: { padding: '0px 3px', margin: 0 }, children: `(MID: ${tid_mid?.mid})` })] }));
46
47
  };
47
48
  export const TMMetadataIcon = ({ tid, md, color, layoutMode = LayoutModes.Update, isMetadataSelected = false, elementStyle }) => {
48
49
  let selectedMetadataStyle = { borderBottom: isMetadataSelected ? `thick solid ${TMColors.text_normal}` : 'none', height: 'max-content' };
@@ -5,6 +5,7 @@ import { AccessLevels, AccessLevelsEx, ArchiveConstraints, DcmtTypeListCacheServ
5
5
  import TMSpinner from '../base/TMSpinner';
6
6
  import { StyledDivHorizontal, StyledTooltipContainer, StyledTooltipItem, StyledTooltipSeparatorItem } from '../base/Styled';
7
7
  import TMTooltip from '../base/TMTooltip';
8
+ import { TMColors } from '../../utils/theme';
8
9
  export var ImageIDList;
9
10
  (function (ImageIDList) {
10
11
  ImageIDList["arrow_001"] = "arrow_001";
@@ -294,7 +295,7 @@ const TMTidViewer = ({ tmSession, tid, did, showIcon = false, color, showId = fa
294
295
  }, children: [showIcon && dtd && _jsx(TMDcmtTypeIcon, { dtd: dtd }), _jsx("p", { title: displayName(), style: {
295
296
  textAlign: 'left',
296
297
  marginLeft: showIcon ? '5px' : '',
297
- color: color ?? (dtd?.isView ? 'red' : ''),
298
+ color: color ?? (dtd?.isView ? 'red' : TMColors.primary),
298
299
  whiteSpace: 'nowrap',
299
300
  overflow: 'hidden',
300
301
  textOverflow: 'ellipsis',
@@ -91,10 +91,14 @@ export declare class DevSettings {
91
91
  }
92
92
  export declare class AdvancedSettings {
93
93
  private _expertMode;
94
+ private _scannerLicense;
94
95
  get expertMode(): number;
95
96
  set expertMode(value: number);
97
+ get scannerLicense(): string;
98
+ set scannerLicense(value: string);
96
99
  toJSON(): {
97
100
  expertMode: number;
101
+ scannerLicense: string;
98
102
  };
99
103
  }
100
104
  export declare class CtrlWfSettings {
@@ -130,6 +130,7 @@ export class DevSettings {
130
130
  export class AdvancedSettings {
131
131
  constructor() {
132
132
  this._expertMode = 0;
133
+ this._scannerLicense = '';
133
134
  }
134
135
  get expertMode() {
135
136
  return this._expertMode;
@@ -142,10 +143,17 @@ export class AdvancedSettings {
142
143
  window.dispatchEvent(event);
143
144
  }
144
145
  }
146
+ get scannerLicense() {
147
+ return this._scannerLicense;
148
+ }
149
+ set scannerLicense(value) {
150
+ this._scannerLicense = value;
151
+ }
145
152
  // Override toJSON to control serialization (called by JSON.stringify)
146
153
  toJSON() {
147
154
  return {
148
- expertMode: this._expertMode, // Serialize only the public property
155
+ expertMode: this._expertMode,
156
+ scannerLicense: this._scannerLicense,
149
157
  };
150
158
  }
151
159
  }