@topconsultnpm/sdkui-react 6.20.0-dev1.12 → 6.20.0-dev1.120

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 (202) hide show
  1. package/lib/assets/Toppy-help-center.png +0 -0
  2. package/lib/assets/headergradient.svg +87 -0
  3. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +322 -30
  4. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +8 -1
  5. package/lib/components/NewComponents/ContextMenu/hooks.js +80 -8
  6. package/lib/components/NewComponents/ContextMenu/index.d.ts +3 -0
  7. package/lib/components/NewComponents/ContextMenu/index.js +2 -0
  8. package/lib/components/NewComponents/ContextMenu/styles.d.ts +9 -1
  9. package/lib/components/NewComponents/ContextMenu/styles.js +159 -37
  10. package/lib/components/NewComponents/ContextMenu/types.d.ts +22 -3
  11. package/lib/components/NewComponents/ContextMenu/useLongPress.d.ts +21 -0
  12. package/lib/components/NewComponents/ContextMenu/useLongPress.js +112 -0
  13. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +803 -109
  14. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +25 -5
  15. package/lib/components/NewComponents/FloatingMenuBar/styles.js +215 -59
  16. package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +12 -2
  17. package/lib/components/base/TMAccordionNew.js +35 -14
  18. package/lib/components/base/TMButton.js +6 -0
  19. package/lib/components/base/TMClosableList.js +4 -0
  20. package/lib/components/base/TMCustomButton.js +61 -17
  21. package/lib/components/base/TMDataGrid.d.ts +7 -4
  22. package/lib/components/base/TMDataGrid.js +153 -11
  23. package/lib/components/base/TMDropDownMenu.js +21 -18
  24. package/lib/components/base/TMFileManager.d.ts +4 -3
  25. package/lib/components/base/TMFileManager.js +32 -24
  26. package/lib/components/base/TMFileManagerDataGridView.d.ts +3 -2
  27. package/lib/components/base/TMFileManagerDataGridView.js +1 -11
  28. package/lib/components/base/TMFileManagerThumbnailItems.d.ts +7 -1
  29. package/lib/components/base/TMFileManagerThumbnailItems.js +5 -2
  30. package/lib/components/base/TMFileManagerThumbnailsView.d.ts +17 -4
  31. package/lib/components/base/TMFileManagerThumbnailsView.js +18 -6
  32. package/lib/components/base/TMFileManagerUtils.d.ts +0 -12
  33. package/lib/components/base/TMListView.js +33 -15
  34. package/lib/components/base/TMPanel.d.ts +1 -1
  35. package/lib/components/base/TMPanel.js +3 -1
  36. package/lib/components/base/TMPopUp.js +6 -0
  37. package/lib/components/base/TMToolbarCard.js +2 -0
  38. package/lib/components/base/TMTreeView.d.ts +2 -1
  39. package/lib/components/base/TMTreeView.js +33 -26
  40. package/lib/components/choosers/TMDataListItemChooser.d.ts +2 -0
  41. package/lib/components/choosers/TMDataListItemChooser.js +8 -2
  42. package/lib/components/choosers/TMDcmtTypeChooser.d.ts +1 -0
  43. package/lib/components/choosers/TMDcmtTypeChooser.js +11 -3
  44. package/lib/components/choosers/TMDistinctValues.js +2 -2
  45. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +2 -0
  46. package/lib/components/choosers/TMDynDataListItemChooser.js +8 -2
  47. package/lib/components/choosers/TMInvoiceRetrieveFormats.js +1 -1
  48. package/lib/components/choosers/TMMetadataChooser.d.ts +2 -0
  49. package/lib/components/choosers/TMMetadataChooser.js +19 -4
  50. package/lib/components/choosers/TMOrderRetrieveFormats.js +1 -1
  51. package/lib/components/choosers/TMUserChooser.d.ts +2 -5
  52. package/lib/components/choosers/TMUserChooser.js +33 -47
  53. package/lib/components/editors/TMCheckBox.js +2 -0
  54. package/lib/components/editors/TMDateBox.js +18 -9
  55. package/lib/components/editors/TMEditorStyled.js +7 -0
  56. package/lib/components/editors/TMLocalizedTextBox.d.ts +3 -1
  57. package/lib/components/editors/TMLocalizedTextBox.js +16 -14
  58. package/lib/components/editors/TMMetadataEditor.d.ts +1 -0
  59. package/lib/components/editors/TMMetadataEditor.js +4 -4
  60. package/lib/components/editors/TMMetadataTextBox.d.ts +9 -0
  61. package/lib/components/editors/TMMetadataTextBox.js +92 -0
  62. package/lib/components/editors/TMMetadataValues.d.ts +1 -0
  63. package/lib/components/editors/TMMetadataValues.js +25 -7
  64. package/lib/components/editors/TMRadioButton.js +2 -0
  65. package/lib/components/editors/TMTextArea.js +18 -30
  66. package/lib/components/editors/TMTextBox.d.ts +1 -1
  67. package/lib/components/editors/TMTextBox.js +29 -4
  68. package/lib/components/editors/TMTextExpression.js +6 -91
  69. package/lib/components/features/archive/TMArchive.js +2 -2
  70. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.d.ts +15 -0
  71. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +462 -0
  72. package/lib/components/features/assistant/TMToppySpeechBubble.d.ts +11 -0
  73. package/lib/components/features/assistant/TMToppySpeechBubble.js +126 -0
  74. package/lib/components/features/documents/TMDcmtBlog.js +1 -1
  75. package/lib/components/features/documents/TMDcmtForm.d.ts +14 -2
  76. package/lib/components/features/documents/TMDcmtForm.js +459 -208
  77. package/lib/components/features/documents/TMDcmtPreview.js +42 -155
  78. package/lib/components/features/documents/TMDcmtTasks.js +9 -9
  79. package/lib/components/features/documents/TMMasterDetailDcmts.js +38 -53
  80. package/lib/components/features/documents/TMRelationViewer.d.ts +1 -1
  81. package/lib/components/features/documents/TMRelationViewer.js +2 -2
  82. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +8 -0
  83. package/lib/components/features/search/{TMSearchResultCheckoutInfoForm.js → TMDcmtCheckoutInfoForm.js} +2 -2
  84. package/lib/components/features/search/TMSavedQuerySelector.js +72 -67
  85. package/lib/components/features/search/TMSearch.d.ts +3 -0
  86. package/lib/components/features/search/TMSearch.js +50 -11
  87. package/lib/components/features/search/TMSearchQueryEditor.d.ts +1 -0
  88. package/lib/components/features/search/TMSearchQueryEditor.js +10 -10
  89. package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -0
  90. package/lib/components/features/search/TMSearchQueryPanel.js +40 -25
  91. package/lib/components/features/search/TMSearchResult.d.ts +3 -0
  92. package/lib/components/features/search/TMSearchResult.js +210 -250
  93. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +3 -3
  94. package/lib/components/features/search/TMSearchResultsMenuItems.js +227 -171
  95. package/lib/components/features/search/TMSignSettingsForm.js +1 -1
  96. package/lib/components/features/search/TMSignatureInfoContent.d.ts +6 -0
  97. package/lib/components/features/search/TMSignatureInfoContent.js +140 -0
  98. package/lib/components/features/search/TMViewHistoryDcmt.js +2 -2
  99. package/lib/components/features/tasks/TMTaskForm.js +75 -25
  100. package/lib/components/features/tasks/TMTasksAgenda.d.ts +3 -1
  101. package/lib/components/features/tasks/TMTasksAgenda.js +48 -9
  102. package/lib/components/features/tasks/TMTasksCalendar.d.ts +2 -0
  103. package/lib/components/features/tasks/TMTasksCalendar.js +19 -7
  104. package/lib/components/features/tasks/TMTasksUtils.d.ts +2 -2
  105. package/lib/components/features/tasks/TMTasksUtils.js +57 -37
  106. package/lib/components/features/tasks/TMTasksView.js +28 -19
  107. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +33 -2
  108. package/lib/components/features/workflow/TMWorkflowPopup.js +139 -34
  109. package/lib/components/features/workflow/diagram/DiagramItemComponent.d.ts +2 -0
  110. package/lib/components/features/workflow/diagram/DiagramItemComponent.js +14 -7
  111. package/lib/components/features/workflow/diagram/DiagramItemForm.js +1 -1
  112. package/lib/components/features/workflow/diagram/RecipientList.js +3 -2
  113. package/lib/components/features/workflow/diagram/WFDiagram.d.ts +4 -0
  114. package/lib/components/features/workflow/diagram/WFDiagram.js +164 -13
  115. package/lib/components/forms/Login/LoginValidatorService.d.ts +2 -0
  116. package/lib/components/forms/Login/LoginValidatorService.js +7 -2
  117. package/lib/components/forms/Login/TMLoginForm.js +35 -7
  118. package/lib/components/forms/TMChooserForm.js +1 -1
  119. package/lib/components/grids/TMBlogsPost.js +56 -31
  120. package/lib/components/grids/TMRecentsManager.js +20 -10
  121. package/lib/components/grids/TMValidationItemsList.js +6 -0
  122. package/lib/components/index.d.ts +6 -3
  123. package/lib/components/index.js +6 -3
  124. package/lib/components/layout/panelManager/TMPanelManagerContext.js +13 -5
  125. package/lib/components/query/TMQueryEditor.d.ts +3 -1
  126. package/lib/components/query/TMQueryEditor.js +102 -100
  127. package/lib/components/settings/SettingsAppearance.d.ts +2 -1
  128. package/lib/components/settings/SettingsAppearance.js +99 -30
  129. package/lib/components/sidebar/TMHeader.js +11 -7
  130. package/lib/components/sidebar/TMSidebar.d.ts +0 -1
  131. package/lib/components/sidebar/TMSidebar.js +16 -44
  132. package/lib/components/sidebar/TMSidebarItem.js +36 -17
  133. package/lib/components/viewers/TMDataListItemViewer.d.ts +2 -1
  134. package/lib/components/viewers/TMDataListItemViewer.js +35 -71
  135. package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +8 -0
  136. package/lib/components/viewers/TMDataUserIdItemViewer.js +39 -0
  137. package/lib/css/tm-sdkui.css +1 -1
  138. package/lib/helper/SDKUI_Globals.d.ts +22 -0
  139. package/lib/helper/SDKUI_Globals.js +10 -1
  140. package/lib/helper/SDKUI_Localizator.d.ts +20 -1
  141. package/lib/helper/SDKUI_Localizator.js +197 -1
  142. package/lib/helper/TMCommandsContextMenu.d.ts +4 -2
  143. package/lib/helper/TMCommandsContextMenu.js +15 -4
  144. package/lib/helper/TMIcons.d.ts +4 -0
  145. package/lib/helper/TMIcons.js +13 -3
  146. package/lib/helper/TMPdfViewer.d.ts +8 -0
  147. package/lib/helper/TMPdfViewer.js +373 -0
  148. package/lib/helper/TMToppyMessage.js +4 -0
  149. package/lib/helper/checkinCheckoutManager.d.ts +31 -1
  150. package/lib/helper/checkinCheckoutManager.js +112 -30
  151. package/lib/helper/devextremeCustomMessages.d.ts +30 -0
  152. package/lib/helper/devextremeCustomMessages.js +30 -0
  153. package/lib/helper/helpers.d.ts +30 -2
  154. package/lib/helper/helpers.js +131 -3
  155. package/lib/helper/index.d.ts +2 -0
  156. package/lib/helper/index.js +2 -0
  157. package/lib/helper/queryHelper.d.ts +1 -1
  158. package/lib/helper/queryHelper.js +33 -3
  159. package/lib/helper/workItemsHelper.d.ts +6 -0
  160. package/lib/helper/workItemsHelper.js +230 -0
  161. package/lib/hooks/useCheckInOutOperations.d.ts +28 -0
  162. package/lib/hooks/useCheckInOutOperations.js +223 -0
  163. package/lib/hooks/useDataListItem.d.ts +12 -0
  164. package/lib/hooks/useDataListItem.js +132 -0
  165. package/lib/hooks/useDataUserIdItem.d.ts +10 -0
  166. package/lib/hooks/useDataUserIdItem.js +96 -0
  167. package/lib/hooks/useFloatingBarPinnedItems.d.ts +11 -0
  168. package/lib/hooks/useFloatingBarPinnedItems.js +54 -0
  169. package/lib/hooks/useMetadataExpression.d.ts +19 -0
  170. package/lib/hooks/useMetadataExpression.js +99 -0
  171. package/lib/hooks/useSettingsFeedback.d.ts +11 -0
  172. package/lib/hooks/useSettingsFeedback.js +38 -0
  173. package/lib/hooks/useWorkflowApprove.d.ts +4 -0
  174. package/lib/hooks/useWorkflowApprove.js +14 -1
  175. package/lib/index.d.ts +1 -0
  176. package/lib/index.js +3 -2
  177. package/lib/services/platform_services.d.ts +3 -3
  178. package/lib/ts/types.d.ts +61 -1
  179. package/lib/utils/theme.d.ts +1 -1
  180. package/lib/utils/theme.js +1 -1
  181. package/package.json +7 -4
  182. package/lib/components/NewComponents/Notification/Notification.d.ts +0 -4
  183. package/lib/components/NewComponents/Notification/Notification.js +0 -60
  184. package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +0 -8
  185. package/lib/components/NewComponents/Notification/NotificationContainer.js +0 -33
  186. package/lib/components/NewComponents/Notification/index.d.ts +0 -2
  187. package/lib/components/NewComponents/Notification/index.js +0 -2
  188. package/lib/components/NewComponents/Notification/styles.d.ts +0 -21
  189. package/lib/components/NewComponents/Notification/styles.js +0 -180
  190. package/lib/components/NewComponents/Notification/types.d.ts +0 -18
  191. package/lib/components/NewComponents/Notification/types.js +0 -1
  192. package/lib/components/base/TMContextMenu.d.ts +0 -25
  193. package/lib/components/base/TMContextMenu.js +0 -109
  194. package/lib/components/base/TMContextMenuOLD.d.ts +0 -26
  195. package/lib/components/base/TMContextMenuOLD.js +0 -56
  196. package/lib/components/base/TMFloatingToolbar.d.ts +0 -9
  197. package/lib/components/base/TMFloatingToolbar.js +0 -101
  198. package/lib/components/features/assistant/ToppyDraggableHelpCenter.d.ts +0 -30
  199. package/lib/components/features/assistant/ToppyDraggableHelpCenter.js +0 -482
  200. package/lib/components/features/assistant/ToppySpeechBubble.d.ts +0 -9
  201. package/lib/components/features/assistant/ToppySpeechBubble.js +0 -117
  202. package/lib/components/features/search/TMSearchResultCheckoutInfoForm.d.ts +0 -8
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  import { Task_States, PdGs, Priorities, ValidationItem, SDK_Localizator, ResultTypes, SDK_Globals } from '@topconsultnpm/sdk-ts';
2
3
  import { TMColors } from '../../../utils/theme';
3
4
  import { SDKUI_Localizator } from '../../../helper';
@@ -296,7 +297,20 @@ newTasks // Array of new tasks to merge
296
297
  return Array.from(taskMap.values());
297
298
  };
298
299
  export const getOriginLabel = (pdg, ID1Name) => {
299
- return pdg ? (ID1Name ?? '') : SDKUI_Localizator.NoSource;
300
+ let label = ID1Name ?? SDKUI_Localizator.NoSource;
301
+ try {
302
+ if (typeof label === 'string' && label.length > 0) {
303
+ // Rimuove: (TID: 123), (DID: 456), TID: 123, DID: 456
304
+ label = label.replace(/\s*\(\s*\b(?:TID|DID):\s*\d+\s*\)|\s*\b(?:TID|DID):\s*\d+/gi, '');
305
+ // Rimuove eventuali spazi multipli rimasti
306
+ label = label.replace(/\s{2,}/g, ' ').trim();
307
+ }
308
+ }
309
+ catch {
310
+ label = ID1Name ?? SDKUI_Localizator.NoSource;
311
+ }
312
+ // Se pdg esiste ritorna la label (anche se vuota), altrimenti ritorna sempre NoSource
313
+ return pdg ? label : SDKUI_Localizator.NoSource;
300
314
  };
301
315
  export const taskValidatorAsync = async (taskDescriptor) => {
302
316
  let vil = [];
@@ -399,59 +413,65 @@ export const areDifferentIDs = (fromID, userID) => {
399
413
  export const createTasksMenuItems = (taskDescriptor, showId, setShowId, showSearch, setShowSearch, openTaskForm, openEditTaskForm, openDuplicateTaskForm, onDeleteCallback, markAsStatus, getAllTasks, fromWG, showContextualWG, setShowContextualWG, fromDossier, showContextualDossier, setShowContextualDossier, fromDocument, showContextualDocument, setShowContextualDocument, showGoToToday, handleGoToToday, fromDatagrid = true) => {
400
414
  const isTaskDescriptorDefined = taskDescriptor !== undefined;
401
415
  const isTaskFromAnotherUser = isTaskDescriptorDefined && areDifferentIDs(taskDescriptor.fromID, SDK_Globals.tmSession?.SessionDescr?.userID);
416
+ const getRowIdsAsArray = (rowIds) => {
417
+ if (fromDatagrid) {
418
+ return Array.isArray(rowIds) ? rowIds : [rowIds];
419
+ }
420
+ return taskDescriptor?.id ? [taskDescriptor.id] : [];
421
+ };
402
422
  const menuItems = [
403
423
  {
404
424
  id: 'createContextualTask',
405
- text: SDKUI_Localizator.CreateContextualTask,
406
- icon: 'plus',
425
+ name: SDKUI_Localizator.CreateContextualTask,
426
+ icon: _jsx("span", { className: "dx-icon-plus" }),
407
427
  onClick: () => { openTaskForm(FormModes.Create, undefined, true); },
408
428
  disabled: false
409
429
  },
410
430
  {
411
- text: SDKUI_Localizator.Create,
412
- icon: 'plus',
431
+ name: SDKUI_Localizator.Create,
432
+ icon: _jsx("span", { className: "dx-icon-plus" }),
413
433
  onClick: () => { openTaskForm(FormModes.Create, undefined, false); },
414
434
  disabled: false
415
435
  },
416
436
  {
417
- text: SDKUI_Localizator.Update,
418
- icon: 'edit',
419
- onClick: openEditTaskForm,
437
+ name: SDKUI_Localizator.Update,
438
+ icon: _jsx("span", { className: "dx-icon-edit" }),
439
+ onClick: (rowId) => openEditTaskForm(fromDatagrid ? rowId : taskDescriptor?.id),
420
440
  operationType: 'singleRow',
421
441
  disabled: fromDatagrid ? false : !isTaskDescriptorDefined
422
442
  },
423
443
  {
424
- text: SDKUI_Localizator.Duplicate,
425
- icon: 'copy',
426
- onClick: openDuplicateTaskForm,
444
+ name: SDKUI_Localizator.Duplicate,
445
+ icon: _jsx("span", { className: "dx-icon-copy" }),
446
+ onClick: (rowId) => openDuplicateTaskForm(fromDatagrid ? rowId : taskDescriptor?.id),
427
447
  operationType: 'singleRow',
428
448
  disabled: fromDatagrid ? isTaskFromAnotherUser : !isTaskDescriptorDefined || isTaskFromAnotherUser
429
449
  },
430
450
  {
431
- text: SDKUI_Localizator.Delete,
432
- icon: 'trash',
433
- onClick: onDeleteCallback,
451
+ name: SDKUI_Localizator.Delete,
452
+ icon: _jsx("span", { className: "dx-icon-trash" }),
453
+ onClick: (rowIds) => onDeleteCallback(getRowIdsAsArray(rowIds)),
434
454
  operationType: 'multiRow',
435
455
  disabled: fromDatagrid ? isTaskFromAnotherUser : !isTaskDescriptorDefined || isTaskFromAnotherUser
436
456
  },
437
457
  {
438
- icon: 'optionsgear',
439
- text: SDKUI_Localizator.MarkAs,
458
+ icon: _jsx("span", { className: "dx-icon-optionsgear" }),
459
+ name: SDKUI_Localizator.MarkAs,
440
460
  id: "markAs",
441
461
  operationType: 'multiRow',
442
462
  disabled: fromDatagrid ? false : !isTaskDescriptorDefined,
443
- items: [
444
- { icon: 'product', text: SDKUI_Localizator.NewFemale, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.NotStarted) },
445
- { icon: 'refresh', text: SDKUI_Localizator.InProgress, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.InProgress) },
446
- { icon: 'check', text: SDKUI_Localizator.Completed, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.Completed) },
447
- { icon: 'taskstop', text: SDKUI_Localizator.Pending, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.Waiting) },
448
- { icon: 'clock', text: SDKUI_Localizator.Postponed, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.Deferred) }
463
+ submenu: [
464
+ { icon: _jsx("span", { className: "dx-icon-product" }), name: SDKUI_Localizator.NewFemale, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.NotStarted) },
465
+ { icon: _jsx("span", { className: "dx-icon-refresh" }), name: SDKUI_Localizator.InProgress, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.InProgress) },
466
+ { icon: _jsx("span", { className: "dx-icon-check" }), name: SDKUI_Localizator.Completed, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.Completed) },
467
+ { icon: _jsx("span", { className: "dx-icon-taskstop" }), name: SDKUI_Localizator.Pending, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.Waiting) },
468
+ { icon: _jsx("span", { className: "dx-icon-clock" }), name: SDKUI_Localizator.Postponed, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.Deferred) }
449
469
  ]
450
470
  },
451
471
  {
452
472
  id: 'wgContextFilter',
453
- text: showContextualWG ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
454
- icon: 'filter',
473
+ name: showContextualWG ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
474
+ icon: _jsx("span", { className: "dx-icon-filter" }),
455
475
  onClick: () => { setShowContextualWG(prev => !prev); },
456
476
  disabled: false,
457
477
  beginGroup: true,
@@ -459,8 +479,8 @@ export const createTasksMenuItems = (taskDescriptor, showId, setShowId, showSear
459
479
  },
460
480
  {
461
481
  id: 'dossierContextFilter',
462
- text: showContextualDossier ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
463
- icon: 'filter',
482
+ name: showContextualDossier ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
483
+ icon: _jsx("span", { className: "dx-icon-filter" }),
464
484
  onClick: () => { setShowContextualDossier(prev => !prev); },
465
485
  disabled: false,
466
486
  beginGroup: !fromWG && !fromDocument,
@@ -468,38 +488,38 @@ export const createTasksMenuItems = (taskDescriptor, showId, setShowId, showSear
468
488
  },
469
489
  {
470
490
  id: 'documentContextFilter',
471
- text: showContextualDocument ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
472
- icon: 'filter',
491
+ name: showContextualDocument ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
492
+ icon: _jsx("span", { className: "dx-icon-filter" }),
473
493
  onClick: () => { setShowContextualDocument(prev => !prev); },
474
494
  disabled: false,
475
495
  beginGroup: !fromDossier && !fromWG,
476
496
  visible: fromDocument
477
497
  },
478
498
  {
479
- icon: "event",
499
+ icon: _jsx("span", { className: "dx-icon-event" }),
480
500
  onClick: () => { if (handleGoToToday) {
481
501
  handleGoToToday();
482
502
  } },
483
- text: SDKUI_Localizator.GoToToday,
503
+ name: SDKUI_Localizator.GoToToday,
484
504
  disabled: false,
485
505
  beginGroup: true,
486
506
  },
487
507
  {
488
508
  beginGroup: true,
489
- icon: showSearch ? "eyeclose" : "eyeopen",
509
+ icon: showSearch ? _jsx("span", { className: "dx-icon-eyeclose" }) : _jsx("span", { className: "dx-icon-eyeopen" }),
490
510
  onClick: () => setShowSearch(prevShowSearch => !prevShowSearch),
491
- text: showSearch ? SDKUI_Localizator.HideSearch : SDKUI_Localizator.ShowSearch,
511
+ name: showSearch ? SDKUI_Localizator.HideSearch : SDKUI_Localizator.ShowSearch,
492
512
  disabled: false
493
513
  },
494
514
  {
495
- icon: showId ? "eyeclose" : "eyeopen",
515
+ icon: showId ? _jsx("span", { className: "dx-icon-eyeclose" }) : _jsx("span", { className: "dx-icon-eyeopen" }),
496
516
  onClick: () => setShowId(prevShowId => !prevShowId),
497
- text: showId ? SDKUI_Localizator.ID_Hide : SDKUI_Localizator.ID_Show,
517
+ name: showId ? SDKUI_Localizator.ID_Hide : SDKUI_Localizator.ID_Show,
498
518
  disabled: false
499
519
  },
500
520
  {
501
- text: SDKUI_Localizator.Refresh,
502
- icon: 'refresh',
521
+ name: SDKUI_Localizator.Refresh,
522
+ icon: _jsx("span", { className: "dx-icon-refresh" }),
503
523
  onClick: () => getAllTasks(),
504
524
  disabled: false,
505
525
  },
@@ -529,7 +549,7 @@ export const createTasksMenuItems = (taskDescriptor, showId, setShowId, showSear
529
549
  item.visible === undefined);
530
550
  }
531
551
  if (showGoToToday === false) {
532
- filteredMenuItems = filteredMenuItems.filter(item => item.text !== SDKUI_Localizator.GoToToday);
552
+ filteredMenuItems = filteredMenuItems.filter(item => item.name !== SDKUI_Localizator.GoToToday);
533
553
  }
534
554
  return filteredMenuItems;
535
555
  };
@@ -5,7 +5,6 @@ import { TabPanel, Item } from 'devextreme-react/tab-panel';
5
5
  import { Priorities, ResultTypes, SDK_Globals, Task_States } from "@topconsultnpm/sdk-ts";
6
6
  import { calculateNumberOfDays, renderTaskIcons } from "./TMTasksUtilsView";
7
7
  import { getPriorityLocalizatorValue } from "../tasks/TMTasksUtils";
8
- import ContextMenu from 'devextreme-react/context-menu';
9
8
  import { calcResponsiveSizes, getExceptionMessage, SDKUI_Localizator, StyledTabItem, TMCountBadge } from "../../../helper";
10
9
  import { useDeviceType } from "../../base/TMDeviceProvider";
11
10
  import { FormModes } from "../../../ts";
@@ -85,8 +84,9 @@ const TMTasksView = (props) => {
85
84
  onDeleteCallback([focusedRowKey]); }, (rowIds, status) => { if (focusedRowKey)
86
85
  markAsStatus([focusedRowKey], status); }, getAllTasks, taskContext?.workingGroup?.id !== undefined, showContextualWG, setShowContextualWG, taskContext?.dossier?.id !== undefined, showContextualDossier, setShowContextualDossier, taskContext?.document?.tid !== undefined && taskContext?.document?.did !== undefined, showContextualDocument, setShowContextualDocument, true, () => { setCurrentCalendarDate(new Date()); setCurrentAgendaDate(new Date()); }, false),
87
86
  ];
88
- }, [visualizedTasks, focusedRowKey, showId, showSearch, showContextualWG, showContextualDossier, taskContext]);
87
+ }, [focusedRowKey, showId, showSearch, showContextualWG, showContextualDossier, taskContext]);
89
88
  const [menuItems, setMenuItems] = useState(agendaCalendarItems());
89
+ const [datagridMenu, setDatagridMenu] = useState([]);
90
90
  const newTaskCount = getNewTaskCount(allTasks);
91
91
  useEffect(() => {
92
92
  setMenuItems(agendaCalendarItems());
@@ -266,6 +266,23 @@ const TMTasksView = (props) => {
266
266
  }
267
267
  });
268
268
  }, [visualizedTasks]);
269
+ const listMenuItems = useCallback(() => {
270
+ const taskDescriptor = visualizedTasks.find(task => task.id === focusedRowKey);
271
+ return createTasksMenuItems(taskDescriptor, showId, setShowId, showSearch, setShowSearch, openTaskFormCallback, (rowId) => { if (rowId) {
272
+ const task = visualizedTasks.find(t => t.id === rowId);
273
+ if (task)
274
+ openTaskFormCallback(FormModes.Update, task);
275
+ } }, (rowId) => { if (rowId) {
276
+ const task = visualizedTasks.find(t => t.id === rowId);
277
+ if (task)
278
+ openTaskFormCallback(FormModes.Duplicate, task);
279
+ } }, onDeleteCallback, markAsStatus, getAllTasks, taskContext?.workingGroup?.id !== undefined, showContextualWG, setShowContextualWG, taskContext?.dossier?.id !== undefined, showContextualDossier, setShowContextualDossier, taskContext?.document?.tid !== undefined && taskContext?.document?.did !== undefined, showContextualDocument, setShowContextualDocument, false, // showGoToToday
280
+ undefined, true // fromDatagrid
281
+ );
282
+ }, [visualizedTasks, focusedRowKey, showId, showSearch, showContextualWG, showContextualDossier, showContextualDocument, taskContext, openTaskFormCallback, onDeleteCallback, markAsStatus, getAllTasks]);
283
+ useEffect(() => {
284
+ setDatagridMenu(listMenuItems());
285
+ }, [listMenuItems]);
269
286
  const onSavedCallback = async (task) => {
270
287
  // If task is undefined or has no ID, exit early
271
288
  if (task === undefined || task.id === undefined)
@@ -295,22 +312,14 @@ const TMTasksView = (props) => {
295
312
  }
296
313
  setShowTaskForm(false);
297
314
  };
298
- const handleNavigateToDossiersWrapper = useCallback(async (dossierId) => {
315
+ const handleNavigateToDossiersWrapper = useCallback(async (value) => {
299
316
  setShowTaskForm(false);
300
- await handleNavigateToDossiers(dossierId);
301
- }, []);
302
- const handleNavigateToWGsWrapper = useCallback(async (workGroupId) => {
317
+ await handleNavigateToDossiers(value);
318
+ }, [handleNavigateToDossiers]);
319
+ const handleNavigateToWGsWrapper = useCallback(async (value) => {
303
320
  setShowTaskForm(false);
304
- await handleNavigateToWGs(workGroupId);
305
- }, []);
306
- const onContextMenuPreparing = (e) => {
307
- if (e === undefined)
308
- return;
309
- if (e.target === 'content') {
310
- e.items = e.items || [];
311
- e.items = createTasksMenuItems(e.row?.data, showId, setShowId, showSearch, setShowSearch, openTaskFormCallback, () => { openTaskFormCallback(FormModes.Update, e.row?.data); }, () => { openTaskFormCallback(FormModes.Duplicate, e.row?.data); }, onDeleteCallback, markAsStatus, getAllTasks, taskContext?.workingGroup?.id !== undefined, showContextualWG, setShowContextualWG, taskContext?.dossier?.id !== undefined, showContextualDossier, setShowContextualDossier, taskContext?.document?.tid !== undefined && taskContext?.document?.did !== undefined, showContextualDocument, setShowContextualDocument, false);
312
- }
313
- };
321
+ await handleNavigateToWGs(value);
322
+ }, [handleNavigateToWGs]);
314
323
  const RenderCustomHeader = ({ data }) => { return _jsx("p", { style: { color: TEXT_NOT_SELECTED_COLOR }, children: data.column.caption }); };
315
324
  const cellDefaultRender = useCallback((cellData) => {
316
325
  const data = cellData.data;
@@ -519,13 +528,13 @@ const TMTasksView = (props) => {
519
528
  ];
520
529
  }, [showId]);
521
530
  const getFromOrToDatagridElement = (fromOrToDataSource, fromCell = false, toCell = false) => {
522
- return _jsx(TMDataGrid, { dataSource: fromOrToDataSource, dataColumns: getDataColumns(fromCell, toCell), selection: { mode: 'multiple', showCheckBoxesMode: "always" }, focusedRowKey: focusedRowKey, selectedRowKeys: [...selectedRowKeys], onFocusedRowChanged: onFocusedRowChanged, onSelectionChanged: onSelectionChanged, onRowDblClick: onRowDblClick, onContextMenuPreparing: onContextMenuPreparing, showSearchPanel: showSearch, noDataText: SDKUI_Localizator.TasksEmpty, counterConfig: { show: true }, onHasFiltersChange: (active) => setHasFilters(active) });
531
+ return _jsx(TMDataGrid, { dataSource: fromOrToDataSource, dataColumns: getDataColumns(fromCell, toCell), selection: { mode: 'multiple', showCheckBoxesMode: "always" }, focusedRowKey: focusedRowKey, selectedRowKeys: [...selectedRowKeys], onFocusedRowChanged: onFocusedRowChanged, onSelectionChanged: onSelectionChanged, onRowDblClick: onRowDblClick, customContextMenuItems: datagridMenu, showSearchPanel: showSearch, noDataText: SDKUI_Localizator.TasksEmpty, counterConfig: { show: true }, onHasFiltersChange: (active) => setHasFilters(active) });
523
532
  };
524
533
  const getFromOrToAgendaElement = (fromOrToDataSource, fromCell = false, toCell = false) => {
525
- return _jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: "auto" }, children: [_jsx(ContextMenu, { dataSource: menuItems, target: `#tasks-agenda-wrapper-${id}` }), _jsx("div", { style: { width: "100%", height: "100%" }, children: _jsx(TMTasksAgenda, { id: id, showId: showId, showSearch: showSearch, visualizedTasks: fromOrToDataSource, fromCell: fromCell, toCell: toCell, currentAgendaDate: currentAgendaDate, setCurrentAgendaDate: setCurrentAgendaDate, openTaskForm: openTaskFormCallback, handleFocusedRowChange: handleFocusedRowChange }) })] });
534
+ return _jsx("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: "auto" }, children: _jsx("div", { style: { width: "100%", height: "100%" }, children: _jsx(TMTasksAgenda, { id: id, showId: showId, showSearch: showSearch, visualizedTasks: fromOrToDataSource, fromCell: fromCell, toCell: toCell, currentAgendaDate: currentAgendaDate, setCurrentAgendaDate: setCurrentAgendaDate, openTaskForm: openTaskFormCallback, handleFocusedRowChange: handleFocusedRowChange, menuItems: menuItems }) }) });
526
535
  };
527
536
  const getFromOrToCalendarElement = (fromOrToDataSource, fromCell = false, toCell = false) => {
528
- return _jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: "auto" }, children: [_jsx(ContextMenu, { dataSource: menuItems, target: `#tasks-calendar-wrapper-${id}` }), _jsx("div", { style: { width: "100%", height: "100%" }, children: _jsx(TMTasksCalendar, { id: id, visualizedTasks: fromOrToDataSource, showId: showId, fromCell: fromCell, toCell: toCell, showSearch: showSearch, currentCalendarDate: currentCalendarDate, setCurrentCalendarDate: setCurrentCalendarDate, openTaskForm: openTaskFormCallback, onDeleteCallback: onDeleteCallback, setCalendarStartDate: setCalendarStartDate, setCalendarEndDate: setCalendarEndDate, focusedRowKey: focusedRowKey, handleFocusedRowChange: handleFocusedRowChange }) })] });
537
+ return _jsx("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: "auto" }, children: _jsx("div", { style: { width: "100%", height: "100%" }, children: _jsx(TMTasksCalendar, { id: id, visualizedTasks: fromOrToDataSource, showId: showId, fromCell: fromCell, toCell: toCell, showSearch: showSearch, currentCalendarDate: currentCalendarDate, setCurrentCalendarDate: setCurrentCalendarDate, openTaskForm: openTaskFormCallback, onDeleteCallback: onDeleteCallback, setCalendarStartDate: setCalendarStartDate, setCalendarEndDate: setCalendarEndDate, focusedRowKey: focusedRowKey, handleFocusedRowChange: handleFocusedRowChange, menuItems: menuItems }) }) });
529
538
  };
530
539
  return _jsxs("div", { style: { width: '100%', height: '100%' }, onContextMenu: (e) => e.preventDefault(), children: [_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, children: _jsxs(TabPanel, { width: "100%", height: "100%", animationEnabled: false, swipeEnabled: false, loop: false, showNavButtons: true, repaintChangesOnly: true, stylingMode: "primary", iconPosition: 'start', tabsPosition: 'top', selectedIndex: activeTabIndex, onSelectedIndexChange: onSelectedIndexChange, id: "task-centered-tab-title", children: [_jsx(Item, { title: SDKUI_Localizator.AssignedToMe, icon: "user", tabRender: (params) => {
531
540
  return _jsxs(StyledTabItem, { "$isSelected": activeTabIndex === AssignedTab.AssignedToMe, children: [_jsxs(TMTooltip, { content: SDKUI_Localizator.AssignedToMe, children: [_jsx("i", { className: `dx-icon-${params.icon}` }), "\u00A0", params.title, " ", (assignedToMeCount > 0) ? `(${assignedToMeCount})` : ''] }), newTaskCount > 0 && (_jsx(TMTooltip, { content: SDKUI_Localizator.NewAssignedActivitiesNumber + ": " + newTaskCount, children: _jsx(TMCountBadge, { children: newTaskCount }) }))] });
@@ -1,5 +1,6 @@
1
- import { DcmtTypeDescriptor } from '@topconsultnpm/sdk-ts';
1
+ import { DcmtTypeDescriptor, WFDescriptor } from '@topconsultnpm/sdk-ts';
2
2
  import { DeviceType } from "../../base/TMDeviceProvider";
3
+ import { WorkItemDetail } from "../../../ts";
3
4
  interface IWorkflowOperationButtonsProps {
4
5
  dtd: DcmtTypeDescriptor | undefined;
5
6
  approveDisable?: boolean;
@@ -24,13 +25,43 @@ export declare const WorkFlowApproveRejectPopUp: ({ TID, DID, deviceType, isReje
24
25
  onClose?: () => void;
25
26
  onCompleted?: () => Promise<void>;
26
27
  }) => import("react/jsx-runtime").JSX.Element;
27
- export declare const WorkFlowReAssignPopUp: ({ DID, TID, deviceType, onClose, selectedItems, onCompleted }: {
28
+ export declare const WorkFlowReAssignPopUp: ({ DID, TID, deviceType, onClose, selectedItems, onCompleted, wf, workItemDetail }: {
28
29
  TID?: number;
29
30
  DID?: number;
30
31
  deviceType?: DeviceType;
31
32
  onClose?: () => void;
32
33
  selectedItems?: any[];
33
34
  onCompleted?: () => Promise<void>;
35
+ wf?: WFDescriptor;
36
+ workItemDetail?: WorkItemDetail;
37
+ }) => import("react/jsx-runtime").JSX.Element;
38
+ /**
39
+ * Modal per forzare l'approvazione di un work item
40
+ */
41
+ export declare const WorkflowForceApproveModal: ({ detail, onClose, onCompleted }: {
42
+ detail: WorkItemDetail;
43
+ onClose?: () => void;
44
+ onCompleted?: () => Promise<void>;
45
+ }) => import("react/jsx-runtime").JSX.Element;
46
+ /**
47
+ * Modal per forzare il rifiuto di un work item
48
+ */
49
+ export declare const WorkflowForceRejectModal: ({ detail, onClose, onCompleted }: {
50
+ detail: WorkItemDetail;
51
+ onClose?: () => void;
52
+ onCompleted?: () => Promise<void>;
53
+ }) => import("react/jsx-runtime").JSX.Element;
54
+ /**
55
+ * Modal per terminare le istanze workflow selezionate
56
+ */
57
+ export declare const WorkflowEndInstanceModal: ({ selectedInstances, onClose, onCompleted }: {
58
+ selectedInstances: Array<{
59
+ wfid?: number;
60
+ tid?: number;
61
+ did?: number;
62
+ }>;
63
+ onClose?: () => void;
64
+ onCompleted?: () => Promise<void>;
34
65
  }) => import("react/jsx-runtime").JSX.Element;
35
66
  export declare const WorkFlowMoreInfoPopUp: ({ DID, TID, deviceType, onClose, onCompleted }: {
36
67
  TID?: number;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useState } from "react";
3
- import { Priorities, ResultTypes, SDK_Globals, SDK_Localizator, TaskEngine, UserListCacheService, ValidationItem, WorkflowCacheService } from '@topconsultnpm/sdk-ts';
2
+ import { useEffect, useMemo, useState } from "react";
3
+ import { Priorities, ResultTypes, SDK_Globals, SDK_Localizator, TaskEngine, UserListCacheService, ValidationItem, WFEvents, WorkflowCacheService } from '@topconsultnpm/sdk-ts';
4
4
  import styled from "styled-components";
5
- import { SDKUI_Localizator, IconApply, IconCloseOutline, IconUser, IconInfo, DateDisplayTypes, TASK_MORE_INFO_PREFIX_NAME, IconSignaturePencil, isSign4TopEnabled } from "../../../helper";
5
+ import { SDKUI_Localizator, IconApply, IconCloseOutline, IconUser, IconInfo, DateDisplayTypes, TASK_MORE_INFO_PREFIX_NAME, IconSignaturePencil, isSign4TopEnabled, IconCheck, IconCloseCircle, IconStop } from "../../../helper";
6
6
  import { TMColors } from "../../../utils/theme";
7
7
  import TMButton from "../../base/TMButton";
8
8
  import { DeviceType } from "../../base/TMDeviceProvider";
@@ -21,17 +21,15 @@ const StyledWorkFlowOperationButtonsContainer = styled.div `
21
21
  gap: 10px;
22
22
  flex-direction: column;
23
23
  `;
24
- const StyledTextArea = styled.textarea.attrs({
25
- maxLength: 200
26
- }) `
24
+ const StyledTextArea = styled.textarea `
27
25
  width: 100%;
28
26
  height: 100%;
29
- border: 1px solid ${props => props.$isValid ? '#b4b4b4' : TMColors.error};
27
+ border: 1px solid ${(props) => (props.$isValid ? '#b4b4b4' : TMColors.error)};
30
28
  border-radius: 10px;
31
29
  padding: 10px;
32
- &:focus{
30
+ &:focus {
33
31
  outline: none;
34
- border-bottom: 4px solid ${props => props.$isValid ? TMColors.primaryColor : TMColors.error};
32
+ border-bottom: 4px solid ${(props) => (props.$isValid ? TMColors.primaryColor : TMColors.error)};
35
33
  }
36
34
  `;
37
35
  const CharacterCounter = styled.div `
@@ -68,17 +66,12 @@ const StyledHorizontalContainer = styled.div `
68
66
  export const WorkFlowOperationButtons = (props) => {
69
67
  const { dtd = undefined, deviceType = DeviceType.DESKTOP, approveDisable = false, signApproveDisable = false, rejectDisable = false, reassignDisable = false, infoDisable = false, onApprove, onSignApprove, onReject, onReAssign, onMoreInfo } = props;
70
68
  const isMobile = deviceType === DeviceType.MOBILE;
71
- // Stato per distinguere workflow di firma vs approvazione
72
- const [isSignWorkflow, setIsSignWorkflow] = useState(false);
73
- useEffect(() => {
74
- // Controlla se il documento ha dei widget definiti, se il documento ha il widget SIGN4_TOP abilitato, allora è un workflow di firma
69
+ // Calcola direttamente se è un workflow di firma per evitare flickering durante il render
70
+ const isSignWorkflow = useMemo(() => {
75
71
  if (dtd && dtd.widgets && dtd.widgets.length > 0) {
76
- setIsSignWorkflow(isSign4TopEnabled(dtd.widgets));
77
- }
78
- else {
79
- // Se non ci sono widget o non è SIGN4_TOP, imposta il workflow di default (approvazione senza firma)
80
- setIsSignWorkflow(false);
72
+ return isSign4TopEnabled(dtd.widgets);
81
73
  }
74
+ return false;
82
75
  }, [dtd]);
83
76
  return (_jsx(StyledWorkFlowOperationButtonsContainer, { "$isMobile": isMobile, children: isSignWorkflow ? (_jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconSignaturePencil, {}), caption: SDKUI_Localizator.SignatureAndApprove, width: "160px", disabled: signApproveDisable, onClick: () => !signApproveDisable && onSignApprove?.(), onMouseDown: e => e.stopPropagation(), advancedColor: "#1a9a49", color: "success" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Reject, disabled: rejectDisable, onClick: () => !rejectDisable && onReject?.(), onMouseDown: e => e.stopPropagation(), advancedColor: TMColors.error, color: "error" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconInfo, { fontSize: 16 }), caption: SDKUI_Localizator.MoreInformation, width: "180px", disabled: infoDisable, onClick: () => !infoDisable && onMoreInfo?.(), onMouseDown: e => e.stopPropagation(), advancedColor: TMColors.info, color: "info" })] })) : (_jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconApply, {}), caption: SDKUI_Localizator.Approve, disabled: approveDisable, onClick: () => !approveDisable && onApprove?.(), advancedColor: "#1a9a49", color: "success" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Reject, disabled: rejectDisable, onClick: () => !rejectDisable && onReject?.(), advancedColor: TMColors.error, color: "error" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconUser, { fontSize: 16 }), caption: SDKUI_Localizator.Reassign, disabled: reassignDisable, onClick: () => !reassignDisable && onReAssign?.(), advancedColor: TMColors.tertiary, color: "tertiary" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconInfo, { fontSize: 16 }), caption: SDKUI_Localizator.MoreInformation, width: "180px", disabled: infoDisable, onClick: () => !infoDisable && onMoreInfo?.(), advancedColor: TMColors.info, color: "info" })] })) }));
84
77
  };
@@ -97,6 +90,7 @@ export const WorkFlowApproveRejectPopUp = ({ TID = 0, DID = 0, deviceType = Devi
97
90
  for (const { TID, DID } of items) {
98
91
  await workflowEngine.WorkItem_CompleteOrRejectAsync(TID, DID, commentValue, isReject);
99
92
  }
93
+ ShowAlert({ mode: 'success', position: 'TOP_RIGHT', title: isReject === 0 ? SDKUI_Localizator.WorkitemApprove : SDKUI_Localizator.WorkitemReject, message: SDKUI_Localizator.OperationSuccess, duration: 3000 });
100
94
  }
101
95
  catch (e) {
102
96
  TMExceptionBoxManager.show({ exception: e });
@@ -105,33 +99,42 @@ export const WorkFlowApproveRejectPopUp = ({ TID = 0, DID = 0, deviceType = Devi
105
99
  onCompleted?.();
106
100
  onClose?.();
107
101
  TMSpinner.hide();
108
- ShowAlert({ mode: 'success', position: 'TOP_RIGHT', title: isReject === 0 ? SDKUI_Localizator.WorkitemApprove : SDKUI_Localizator.WorkitemReject, message: SDKUI_Localizator.OperationSuccess, duration: 3000 });
109
102
  }
110
103
  };
111
104
  const workflowAction = isReject === 0 ? SDKUI_Localizator.Approve : SDKUI_Localizator.Reject;
112
105
  const itemCount = selectedItems.length > 0 ? `(${selectedItems.length} workitem)` : '';
113
106
  const title = `${workflowAction} ${itemCount}`;
114
- 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, { "$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
107
+ 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
115
108
  ? _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconApply, {}), caption: SDKUI_Localizator.Approve, disabled: false, onClick: () => completeOrRejectAsync(isReject), advancedColor: TMColors.success })
116
109
  : _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Reject, disabled: disable, onClick: () => { !disable && completeOrRejectAsync(isReject); }, advancedColor: TMColors.error }) })] }) }));
117
110
  };
118
- export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceType.DESKTOP, onClose, selectedItems = [], onCompleted }) => {
111
+ export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceType.DESKTOP, onClose, selectedItems = [], onCompleted, wf, workItemDetail }) => {
119
112
  const [commentValue, setCommentValue] = useState('');
120
113
  const [selectedUserID, setSelectedUserID] = useState([]);
121
114
  const [participants, setParticipants] = useState([]);
122
115
  const disable = commentValue.length === 0 || !selectedUserID;
116
+ // Determina se siamo nel contesto CtrlWorkflow (quando abbiamo workItemDetail)
117
+ const isCtrlWorkflowContext = !!workItemDetail;
123
118
  const reAssignWorkFlowAsync = async () => {
124
119
  try {
125
120
  TMSpinner.show();
126
121
  const workflowEngine = SDK_Globals.tmSession?.NewWorkflowEngine();
127
122
  if (!workflowEngine)
128
123
  throw new Error("Workflow engine is not available");
129
- const items = selectedItems.length > 0
130
- ? selectedItems.map(({ TID, DID }) => ({ TID, DID }))
131
- : [{ TID, DID }];
132
- for (const { TID, DID } of items) {
133
- await SDK_Globals.tmSession?.NewWorkflowEngine().WorkItem_ReassignAsync(TID, DID, selectedUserID?.[0], commentValue);
124
+ if (isCtrlWorkflowContext && workItemDetail) {
125
+ // Contesto CtrlWorkflow: usa WFCtrl_ReassignWIAsync
126
+ await workflowEngine.WFCtrl_ReassignWIAsync(workItemDetail.wfid, workItemDetail.did, selectedUserID?.[0], commentValue);
127
+ }
128
+ else {
129
+ // Contesto WorkItem: usa WorkItem_ReassignAsync
130
+ const items = selectedItems.length > 0
131
+ ? selectedItems.map(({ TID, DID }) => ({ TID, DID }))
132
+ : [{ TID, DID }];
133
+ for (const { TID, DID } of items) {
134
+ await workflowEngine.WorkItem_ReassignAsync(TID, DID, selectedUserID?.[0], commentValue);
135
+ }
134
136
  }
137
+ ShowAlert({ mode: 'success', position: 'TOP_RIGHT', title: SDKUI_Localizator.WorkitemReassign, message: SDKUI_Localizator.OperationSuccess, duration: 3000 });
135
138
  }
136
139
  catch (e) {
137
140
  TMExceptionBoxManager.show({ exception: e });
@@ -140,11 +143,10 @@ export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
140
143
  onCompleted?.();
141
144
  onClose?.();
142
145
  TMSpinner.hide();
143
- ShowAlert({ mode: 'success', position: 'TOP_RIGHT', title: SDKUI_Localizator.WorkitemReassign, message: SDKUI_Localizator.OperationSuccess, duration: 3000 });
144
146
  }
145
147
  };
146
148
  // Determina il TID da usare
147
- const tidToUse = selectedItems?.[0]?.TID ?? TID;
149
+ const tidToUse = workItemDetail?.tid ?? selectedItems?.[0]?.TID ?? TID;
148
150
  useEffect(() => {
149
151
  let isMounted = true;
150
152
  const fetchData = async () => {
@@ -153,11 +155,11 @@ export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
153
155
  if (!tidToUse)
154
156
  return;
155
157
  // Recupera info workflow
156
- const wf = await WorkflowCacheService.GetWFInfoAsync(tidToUse);
158
+ const workflowInfo = wf ?? await WorkflowCacheService.GetWFInfoAsync(tidToUse);
157
159
  // Recupera tutti gli utenti
158
160
  const allUsers = await UserListCacheService.GetAllAsync();
159
161
  // Filtra utenti partecipanti
160
- const participantIds = wf?.participants?.map(p => p.userID);
162
+ const participantIds = workflowInfo?.participants?.map(p => p.userID);
161
163
  const participantUsers = allUsers.filter(u => participantIds?.includes(u.id) && u.id !== SDK_Globals.tmSession?.SessionDescr?.userID);
162
164
  if (isMounted)
163
165
  setParticipants(participantUsers);
@@ -171,10 +173,113 @@ export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
171
173
  };
172
174
  fetchData();
173
175
  return () => { isMounted = false; };
174
- }, [tidToUse]);
175
- return (_jsx(TMModal, { onClose: onClose, width: '600px', height: '270px', isModal: true, title: SDKUI_Localizator.Reassign + (selectedItems.length > 0 ? ' (' + selectedItems.length + ' workitem)' : ''), children: _jsxs(StyledModalBodyWrapper, { children: [_jsxs(StyledModalContentContainer, { children: [_jsx(TMUserChooser, { dataSource: participants, values: selectedUserID, onValueChanged: (IDs) => {
176
+ }, [tidToUse, wf, workItemDetail]);
177
+ // Determina il conteggio degli item da mostrare nel titolo
178
+ const itemCount = workItemDetail ? 1 : selectedItems.length;
179
+ const titleSuffix = itemCount > 0 ? ` (${itemCount} workitem)` : '';
180
+ 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) => {
176
181
  setSelectedUserID(IDs ?? []);
177
- } }), _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, { "$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 }) })] }) }));
182
+ } }), _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 }) })] }) }));
183
+ };
184
+ /**
185
+ * Modal per forzare l'approvazione di un work item
186
+ */
187
+ export const WorkflowForceApproveModal = ({ detail, onClose, onCompleted }) => {
188
+ const [commentValue, setCommentValue] = useState('');
189
+ const disable = commentValue.length === 0;
190
+ const forceApproveAsync = async () => {
191
+ try {
192
+ TMSpinner.show({ description: 'Forza approvazione in corso...' });
193
+ await SDK_Globals.tmSession?.NewWorkflowEngine().WFCtrl_ForceWIAsync(detail.wfid, detail.did, WFEvents.AfterBtnApprove01, commentValue);
194
+ ShowAlert({
195
+ mode: 'success',
196
+ position: 'TOP_RIGHT',
197
+ title: 'Forza completamento',
198
+ message: 'Work item approvato con successo',
199
+ duration: 3000
200
+ });
201
+ await onCompleted?.();
202
+ }
203
+ catch (e) {
204
+ TMExceptionBoxManager.show({ exception: e });
205
+ }
206
+ finally {
207
+ onClose?.();
208
+ TMSpinner.hide();
209
+ }
210
+ };
211
+ const userName = detail.toUser?.name ?? detail.to;
212
+ const title = `Forza completamento - ${userName}`;
213
+ 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 }) })] }) }));
214
+ };
215
+ /**
216
+ * Modal per forzare il rifiuto di un work item
217
+ */
218
+ export const WorkflowForceRejectModal = ({ detail, onClose, onCompleted }) => {
219
+ const [commentValue, setCommentValue] = useState('');
220
+ const disable = commentValue.length === 0;
221
+ const forceRejectAsync = async () => {
222
+ try {
223
+ TMSpinner.show({ description: 'Forza rifiuto in corso...' });
224
+ await SDK_Globals.tmSession?.NewWorkflowEngine().WFCtrl_ForceWIAsync(detail.wfid, detail.did, WFEvents.AfterBtnReject01, commentValue);
225
+ ShowAlert({
226
+ mode: 'success',
227
+ position: 'TOP_RIGHT',
228
+ title: 'Forza rifiuto',
229
+ message: 'Work item rifiutato con successo',
230
+ duration: 3000
231
+ });
232
+ await onCompleted?.();
233
+ }
234
+ catch (e) {
235
+ TMExceptionBoxManager.show({ exception: e });
236
+ }
237
+ finally {
238
+ onClose?.();
239
+ TMSpinner.hide();
240
+ }
241
+ };
242
+ const userName = detail.toUser?.name ?? detail.to;
243
+ const title = `Forza rifiuto - ${userName}`;
244
+ 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 }) })] }) }));
245
+ };
246
+ /**
247
+ * Modal per terminare le istanze workflow selezionate
248
+ */
249
+ export const WorkflowEndInstanceModal = ({ selectedInstances, onClose, onCompleted }) => {
250
+ const [commentValue, setCommentValue] = useState('');
251
+ const disable = commentValue.length === 0;
252
+ const endInstancesAsync = async () => {
253
+ try {
254
+ TMSpinner.show({ description: 'Terminazione istanze in corso...' });
255
+ const workflowEngine = SDK_Globals.tmSession?.NewWorkflowEngine();
256
+ if (!workflowEngine)
257
+ throw new Error("Workflow engine non disponibile");
258
+ for (const instance of selectedInstances) {
259
+ if (instance.wfid && instance.did) {
260
+ await workflowEngine.WFCtrl_EndInstanceAsync(instance.wfid, instance.tid ?? 0, instance.did, commentValue);
261
+ }
262
+ }
263
+ ShowAlert({
264
+ mode: 'success',
265
+ position: 'TOP_RIGHT',
266
+ title: 'Terminazione istanze',
267
+ message: `${selectedInstances.length} ${selectedInstances.length === 1 ? 'istanza terminata' : 'istanze terminate'} con successo`,
268
+ duration: 3000
269
+ });
270
+ await onCompleted?.();
271
+ }
272
+ catch (e) {
273
+ TMExceptionBoxManager.show({ exception: e });
274
+ }
275
+ finally {
276
+ onClose?.();
277
+ TMSpinner.hide();
278
+ }
279
+ };
280
+ const itemCount = selectedInstances.length > 0 ? `(${selectedInstances.length} ${selectedInstances.length === 1 ? 'istanza' : 'istanze'})` : '';
281
+ const title = `Termina istanza ${itemCount}`;
282
+ 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: "Termina istanza", width: '150px', disabled: disable, onClick: () => !disable && endInstancesAsync(), advancedColor: TMColors.error }) })] }) }));
178
283
  };
179
284
  export const WorkFlowMoreInfoPopUp = ({ DID = 0, TID = 0, deviceType = DeviceType.DESKTOP, onClose, onCompleted }) => {
180
285
  const [users, setUsers] = useState([]);
@@ -210,6 +315,7 @@ export const WorkFlowMoreInfoPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
210
315
  name: `${TASK_MORE_INFO_PREFIX_NAME}${nameInput}`
211
316
  };
212
317
  await SDK_Globals.tmSession?.NewWorkflowEngine().WorkItem_MoreInfoAsync(TID, DID, taskWithPrefix);
318
+ ShowAlert({ mode: 'success', position: 'TOP_RIGHT', title: SDKUI_Localizator.MoreInformation, message: SDKUI_Localizator.MoreInfoSent, duration: 3000 });
213
319
  }
214
320
  catch (e) {
215
321
  TMExceptionBoxManager.show({ exception: e });
@@ -218,7 +324,6 @@ export const WorkFlowMoreInfoPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
218
324
  onCompleted?.();
219
325
  onClose?.();
220
326
  TMSpinner.hide();
221
- ShowAlert({ mode: 'success', position: 'TOP_RIGHT', title: SDKUI_Localizator.MoreInformation, message: SDKUI_Localizator.MoreInfoSent, duration: 3000 });
222
327
  }
223
328
  };
224
329
  useEffect(() => {