@topconsultnpm/sdkui-react 6.21.0-t2 → 6.21.0-t3

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 (151) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +22 -1
  2. package/lib/components/NewComponents/ContextMenu/styles.d.ts +4 -4
  3. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +6 -6
  4. package/lib/components/base/Styled.d.ts +1 -1
  5. package/lib/components/base/TMAreaManager.js +11 -0
  6. package/lib/components/base/TMCounterBar.d.ts +2 -2
  7. package/lib/components/base/TMCounterContainer.d.ts +2 -1
  8. package/lib/components/base/TMCustomButton.d.ts +1 -1
  9. package/lib/components/base/TMDataGrid.js +12 -2
  10. package/lib/components/base/TMDataGridExportForm.d.ts +2 -1
  11. package/lib/components/base/TMDataGridExportForm.js +19 -8
  12. package/lib/components/base/TMFileManager.d.ts +2 -1
  13. package/lib/components/base/TMFileManagerDataGridView.d.ts +2 -1
  14. package/lib/components/base/TMFileManagerDataGridView.js +4 -4
  15. package/lib/components/base/TMFileManagerThumbnailItems.d.ts +1 -1
  16. package/lib/components/base/TMFileManagerThumbnailItems.js +3 -3
  17. package/lib/components/base/TMFileManagerThumbnailsView.d.ts +1 -1
  18. package/lib/components/base/TMFileManagerUtils.d.ts +7 -0
  19. package/lib/components/base/TMFileManagerUtils.js +14 -1
  20. package/lib/components/base/TMLayout.d.ts +4 -4
  21. package/lib/components/base/TMList.d.ts +2 -1
  22. package/lib/components/base/TMListView.d.ts +1 -1
  23. package/lib/components/base/TMModal.js +2 -2
  24. package/lib/components/base/TMPopUp.d.ts +1 -0
  25. package/lib/components/base/TMPopUp.js +59 -2
  26. package/lib/components/base/TMSpinner.d.ts +5 -2
  27. package/lib/components/base/TMSpinner.js +33 -6
  28. package/lib/components/base/TMTab.d.ts +4 -3
  29. package/lib/components/base/TMTooltip.d.ts +1 -1
  30. package/lib/components/base/TMTreeView.d.ts +1 -1
  31. package/lib/components/base/TMTreeView.js +12 -15
  32. package/lib/components/base/TMUserAvatar.d.ts +2 -1
  33. package/lib/components/base/TMVilViewer.d.ts +2 -1
  34. package/lib/components/base/TMWaitPanel.d.ts +5 -2
  35. package/lib/components/base/TMWaitPanel.js +8 -6
  36. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +1 -1
  37. package/lib/components/choosers/TMDynDataListItemChooser.js +6 -1
  38. package/lib/components/choosers/TMGroupChooser.js +1 -1
  39. package/lib/components/choosers/TMInvoiceRetrieveFormats.d.ts +2 -1
  40. package/lib/components/choosers/TMOrderRetrieveFormats.d.ts +2 -1
  41. package/lib/components/choosers/TMRelationChooser.d.ts +3 -3
  42. package/lib/components/choosers/TMUserChooser.d.ts +2 -2
  43. package/lib/components/editors/TMEditorStyled.d.ts +6 -6
  44. package/lib/components/editors/TMFormulaEditor.d.ts +2 -1
  45. package/lib/components/editors/TMFormulaEditor.js +98 -49
  46. package/lib/components/editors/TMHtmlContentDisplay.d.ts +2 -1
  47. package/lib/components/editors/TMHtmlEditor.d.ts +2 -1
  48. package/lib/components/editors/TMMetadataEditor.js +6 -2
  49. package/lib/components/editors/TMMetadataValues.js +23 -6
  50. package/lib/components/editors/TMTreeDropDown.d.ts +1 -1
  51. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.d.ts +1 -1
  52. package/lib/components/features/blog/TMBlogCommentForm.d.ts +2 -1
  53. package/lib/components/features/blog/TMBlogCommentForm.js +5 -2
  54. package/lib/components/features/documents/TMCopyToFolderForm.js +46 -24
  55. package/lib/components/features/documents/TMDcmtForm.js +19 -9
  56. package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +1 -1
  57. package/lib/components/features/documents/TMDcmtIcon.d.ts +2 -1
  58. package/lib/components/features/documents/TMDcmtIcon.js +1 -1
  59. package/lib/components/features/documents/TMDcmtPreview.d.ts +1 -1
  60. package/lib/components/features/documents/TMDcmtTasks.d.ts +2 -1
  61. package/lib/components/features/documents/TMDragDropOverlay.d.ts +1 -1
  62. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +0 -2
  63. package/lib/components/features/documents/TMMasterDetailDcmts.js +4 -5
  64. package/lib/components/features/documents/TMMergeToPdfForm.d.ts +0 -2
  65. package/lib/components/features/documents/TMMergeToPdfForm.js +26 -10
  66. package/lib/components/features/documents/TMRelationViewer.js +8 -3
  67. package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +0 -13
  68. package/lib/components/features/documents/copyAndMergeDcmtsShared.js +1 -39
  69. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +2 -1
  70. package/lib/components/features/search/TMMetadataOutputForm.d.ts +18 -0
  71. package/lib/components/features/search/TMMetadataOutputForm.js +225 -0
  72. package/lib/components/features/search/TMMetadataSorterForm.d.ts +18 -0
  73. package/lib/components/features/search/TMMetadataSorterForm.js +243 -0
  74. package/lib/components/features/search/TMSavedQuerySelector.d.ts +2 -2
  75. package/lib/components/features/search/TMSearch.d.ts +0 -2
  76. package/lib/components/features/search/TMSearch.js +2 -2
  77. package/lib/components/features/search/TMSearchQueryEditor.js +14 -8
  78. package/lib/components/features/search/TMSearchQueryPanel.js +249 -58
  79. package/lib/components/features/search/TMSearchResult.d.ts +1 -2
  80. package/lib/components/features/search/TMSearchResult.js +40 -20
  81. package/lib/components/features/search/TMSearchResultFloatingActionButton.d.ts +1 -1
  82. package/lib/components/features/search/TMSignatureInfoContent.d.ts +2 -1
  83. package/lib/components/features/search/TMViewHistoryDcmt.d.ts +2 -1
  84. package/lib/components/features/search/TMViewHistoryDcmt.js +1 -1
  85. package/lib/components/features/search/metadataFormHelper.d.ts +16 -0
  86. package/lib/components/features/search/metadataFormHelper.js +77 -0
  87. package/lib/components/features/tasks/TMTaskForm.d.ts +1 -1
  88. package/lib/components/features/tasks/TMTaskFormUtils.d.ts +10 -10
  89. package/lib/components/features/tasks/TMTasksAgenda.d.ts +1 -1
  90. package/lib/components/features/tasks/TMTasksCalendar.d.ts +1 -1
  91. package/lib/components/features/tasks/TMTasksHeader.d.ts +1 -1
  92. package/lib/components/features/tasks/TMTasksPanelContent.d.ts +1 -1
  93. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +5 -5
  94. package/lib/components/features/tasks/TMTasksView.d.ts +1 -1
  95. package/lib/components/features/wg/TMWGsCopyMoveForm.d.ts +3 -2
  96. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +8 -7
  97. package/lib/components/forms/Login/Chooser.d.ts +2 -2
  98. package/lib/components/forms/Login/TMLoginForm.js +15 -3
  99. package/lib/components/forms/TMChooserForm.d.ts +2 -1
  100. package/lib/components/forms/TMSaveForm.d.ts +4 -4
  101. package/lib/components/grids/TMBlogAttachments.d.ts +2 -1
  102. package/lib/components/grids/TMBlogAttachments.js +2 -2
  103. package/lib/components/grids/TMBlogHeader.d.ts +1 -1
  104. package/lib/components/grids/TMBlogsPost.d.ts +1 -1
  105. package/lib/components/grids/TMBlogsPost.js +5 -3
  106. package/lib/components/grids/TMBlogsPostUtils.d.ts +10 -9
  107. package/lib/components/grids/TMBlogsPostUtils.js +3 -1
  108. package/lib/components/grids/TMValidationItemsList.d.ts +2 -1
  109. package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +2 -1
  110. package/lib/components/layout/panelManager/TMPanelManagerContext.d.ts +2 -2
  111. package/lib/components/layout/panelManager/TMPanelManagerToolbar.d.ts +1 -1
  112. package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.d.ts +2 -2
  113. package/lib/components/layout/panelManager/TMPanelWrapper.d.ts +2 -2
  114. package/lib/components/pages/TMPage.d.ts +1 -1
  115. package/lib/components/settings/SettingsAppearance.d.ts +2 -1
  116. package/lib/components/sidebar/TMAboutApp.d.ts +2 -1
  117. package/lib/components/sidebar/TMHeader.d.ts +3 -3
  118. package/lib/components/viewers/TMDataListItemViewer.d.ts +3 -2
  119. package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +3 -2
  120. package/lib/components/viewers/TMMidViewer.d.ts +2 -2
  121. package/lib/components/viewers/TMTidViewer.d.ts +2 -2
  122. package/lib/components/wizard/TMWizard.d.ts +1 -0
  123. package/lib/components/wizard/TMWizard.js +5 -3
  124. package/lib/helper/Enum_Localizator.js +1 -0
  125. package/lib/helper/MergePdfManager.d.ts +45 -0
  126. package/lib/helper/MergePdfManager.js +148 -0
  127. package/lib/helper/SDKUI_Globals.js +2 -1
  128. package/lib/helper/SDKUI_Localizator.d.ts +6 -0
  129. package/lib/helper/SDKUI_Localizator.js +60 -0
  130. package/lib/helper/TMCommandsContextMenu.d.ts +1 -1
  131. package/lib/helper/TMIcons.d.ts +278 -278
  132. package/lib/helper/TMPdfViewer.d.ts +2 -1
  133. package/lib/helper/TMToppyMessage.d.ts +2 -2
  134. package/lib/helper/TMUtils.d.ts +24 -20
  135. package/lib/helper/TMUtils.js +55 -0
  136. package/lib/helper/checkinCheckoutManager.d.ts +4 -3
  137. package/lib/helper/checkinCheckoutManager.js +29 -11
  138. package/lib/helper/helpers.d.ts +3 -2
  139. package/lib/helper/helpers.js +1 -0
  140. package/lib/hooks/useCheckInOutOperations.d.ts +4 -3
  141. package/lib/hooks/useDataUserIdItem.js +1 -1
  142. package/lib/hooks/useDcmtOperations.d.ts +18 -1
  143. package/lib/hooks/useDcmtOperations.js +235 -24
  144. package/lib/hooks/useDocumentOperations.d.ts +0 -2
  145. package/lib/hooks/useDocumentOperations.js +27 -10
  146. package/lib/hooks/useInputDialog.d.ts +2 -1
  147. package/lib/hooks/useRelatedDocuments.js +4 -4
  148. package/lib/services/platform_services.d.ts +7 -6
  149. package/lib/ts/types.d.ts +2 -1
  150. package/lib/ts/types.js +1 -0
  151. package/package.json +14 -7
@@ -246,7 +246,7 @@ const TMBlogCommentForm = (props) => {
246
246
  alignItems: 'center',
247
247
  padding: '0 8px',
248
248
  }, children: currentDraftAttachments.length > 0 ? (currentDraftAttachments.map(draft => {
249
- const tooltipContent = (_jsxs("div", { style: { textAlign: 'left' }, children: [_jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Name, ":"] }), " ", draft.name ?? '-'] }), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Author, ":"] }), " ", draft.updaterName ?? '-'] }), _jsx("hr", {}), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Version, ":"] }), " ", draft.version] }), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Size, ":"] }), " ", formatBytes(draft.size ?? 0)] }), _jsx("hr", {}), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.CreationTime, ":"] }), " ", Globalization.getDateTimeDisplayValue(draft.creationTime)] }), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.LastUpdateTime, ":"] }), " ", Globalization.getDateTimeDisplayValue(draft.lastUpdateTime)] })] }));
249
+ const tooltipContent = (_jsxs("div", { style: { textAlign: 'left' }, children: [_jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Name, ":"] }), " ", draft.name ?? '-'] }), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Author, ":"] }), " ", draft.updaterName ?? '-'] }), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Extension, ":"] }), " ", draft.ext ?? '-'] }), _jsx("hr", {}), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Version, ":"] }), " ", draft.version] }), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.Size, ":"] }), " ", formatBytes(draft.size ?? 0)] }), _jsx("hr", {}), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.CreationTime, ":"] }), " ", Globalization.getDateTimeDisplayValue(draft.creationTime)] }), _jsxs("div", { children: [_jsxs("span", { style: { fontWeight: 'bold' }, children: [SDKUI_Localizator.LastUpdateTime, ":"] }), " ", Globalization.getDateTimeDisplayValue(draft.lastUpdateTime)] })] }));
250
250
  return _jsxs("div", { style: {
251
251
  display: 'inline-flex',
252
252
  alignItems: 'center',
@@ -264,7 +264,7 @@ const TMBlogCommentForm = (props) => {
264
264
  }, onMouseLeave: (e) => {
265
265
  e.currentTarget.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)';
266
266
  e.currentTarget.style.backgroundColor = '#fff';
267
- }, children: [draft.ext ? (_jsx("span", { style: { marginRight: '10px', display: 'flex', alignItems: 'center' }, children: getFileIcon(draft.ext, undefined, tooltipContent) })) : (_jsx(IconAttachment, { style: { marginRight: '5px' } })), _jsx("span", { style: { marginRight: '8px', display: 'flex', alignItems: 'center' }, children: draft.name }), draft.version && (_jsx("span", { style: {
267
+ }, children: [draft.ext ? (_jsxs("span", { style: { marginRight: '10px', display: 'flex', alignItems: 'center', position: 'relative', width: draft.isSigned ? '30px' : undefined }, children: [getFileIcon(draft.ext, undefined, tooltipContent), draft.isSigned == 1 && _jsx("div", { style: { position: 'absolute', bottom: '-4px', right: '-7px' }, children: _jsx(TMTooltip, { content: "Documento firmato", children: _jsx(IconSignature, { fontSize: 28 }) }) })] })) : (_jsx(IconAttachment, { style: { marginRight: '5px' } })), _jsx("span", { style: { marginRight: '8px', display: 'flex', alignItems: 'center' }, children: draft.name }), draft.version && (_jsx("span", { style: {
268
268
  display: 'inline-flex',
269
269
  width: '20px',
270
270
  height: '20px',
@@ -349,3 +349,6 @@ const TMAttachmentsView = (props) => {
349
349
  }, []);
350
350
  return _jsx(TMChooserForm, { title: SDKUI_Localizator.Attachments, allowMultipleSelection: true, allowApplyWithZeroSelection: true, startWithShowOnlySelectedItems: true, hasShowOnlySelectedItems: false, width: calcResponsiveSizes(deviceType, '700px', '700px', '95%'), height: "500px", manageUseLocalizedName: false, columns: dataColumns, showDefaultColumns: false, selectedIDs: selectedIDs, dataSource: dataSource, hasShowId: true, hideRefresh: false, onClose: onClose, onChoose: onChoose });
351
351
  };
352
+ function IconSignature(props) {
353
+ return (_jsx("svg", { height: "1em", viewBox: "0 0 450 450", width: "1em", fill: "currentColor", ...props, children: _jsx("g", { children: _jsx("g", { children: _jsxs("g", { clipRule: "evenodd", fill: "rgb(0,0,0)", fillRule: "evenodd", children: [_jsx("path", { d: "m366.6 67.8 1.1-4c.4-1.5.6-3 .6-4.5 0-8.1-5.5-15.2-13.3-17.3-9.5-2.5-19.3 3.2-21.8 12.8l-20.4 77.9 34.6 9z" }), _jsx("path", { d: "m234.9 198.9h148.6v35.7h-148.6z", transform: "matrix(.253 -.968 .968 .253 21.311 461.088)" }), _jsx("path", { d: "m292.8 316 8.4 2.2 4.5-17.3-34.6-9.1-4.5 17.4 8.3 2.2z" }), _jsx("path", { d: "m275.3 319.7-12.7 14.7 5.4 40.3 24.4-32.5-3.9-19.1zm6.5 23.3c-.8 2.9-3.7 4.6-6.6 3.9s-4.6-3.7-3.9-6.6 3.7-4.6 6.6-3.9 4.6 3.7 3.9 6.6z" }), _jsx("path", { d: "m395.6 71.5-20.3-5.5-2 7.7 16.5 4.4-24.8 95c-.6 2.1.7 4.3 2.8 4.8.3.1.7.1 1 .1 1.8 0 3.4-1.2 3.8-3l25.8-98.8c.6-2-.7-4.2-2.8-4.7z" }), _jsx("path", { d: "" }), _jsx("path", { d: "m243.4 379.8c-1.8-1.2-4.3-.8-5.5 1.1-9.6 14.1-29.9 19.6-45.3 12.2-.5-.2-.9-.5-1.4-.7-3.5-1.8-7.9-4-12.8-2.7-2.7.7-4.7 2.3-6.5 3.6-1.5 1.2-2.8 2.2-3.9 2.2-2 .1-4-3-5-5.9-.2-.5-.4-1-.5-1.5-1.4-4.1-3.1-9.1-7.8-11.8-5.8-3.3-12.9-.9-17.4 3-2.4 2-4.2 4.4-6 6.7-1.2 1.5-2.3 2.9-3.4 4.1-7.5 7.9-20.3 10-30.2 5.6 7.6-6.9 13-15.5 15.4-24.9s1-21.1-7.8-25.8c-4.5-2.4-9.9-2.4-15.2.2-4.4 2.2-8.4 5.9-10.9 10.3-3.9 7-5.1 15.4-3.3 23.8 1.4 6.3 4.3 12 8.4 16.5-8.4 4.9-18.2 7.3-27.8 6.1-2.2-.3-4.2 1.2-4.5 3.4s1.2 4.2 3.4 4.5c2.1.3 4.1.4 6.2.4 10 0 20.1-3.1 29.1-9 6.1 3.7 13.5 5.4 21.1 4.7 8.5-.8 16.3-4.4 21.8-10.2 1.5-1.5 2.7-3.1 3.9-4.7 1.6-2.1 3.1-4 4.9-5.6 2.4-2 6-3.4 8.3-2.1 2.1 1.2 3.1 4.2 4.2 7.5.2.5.4 1.1.6 1.6 2.5 7 7.1 11.1 12.4 11.1h.6c3.6-.2 6.2-2.2 8.3-3.9 1.3-1 2.5-2 3.6-2.2 2-.5 4.5.8 7.2 2.1.5.3 1 .5 1.5.7 5.7 2.7 11.9 4 18.2 4 14.4 0 29-6.9 37.1-18.9 1.3-1.8.9-4.3-1-5.5zm-152.6 11.3c-8.1-8-10.4-21.8-4.8-31.7 2.5-4.5 7.5-8.2 12-8.2 1.2 0 2.3.3 3.4.8 5 2.7 5.5 10.6 3.9 16.8-2.2 8.7-7.5 16.5-14.5 22.3z" })] }) }) }) }));
354
+ }
@@ -32,6 +32,11 @@ const TMCopyToFolderForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationVi
32
32
  // ---- Stato dei settings ----
33
33
  const [settings, setSettings] = useState(() => buildInitialDownloadSettings(SDKUI_Globals.userSettings.documentDownloadSettings, SDKUI_Globals.userSettings.searchSettings.invoiceRetrieveFormat, SDKUI_Globals.userSettings.searchSettings.orderRetrieveFormat));
34
34
  const [selectedItemsRelationViewer, setSelectedItemsRelationViewer] = useState([]);
35
+ // ---- Stato per la creazione ZIP (spinner separato) ----
36
+ const [isCreatingZip, setIsCreatingZip] = useState(false);
37
+ const [zipProgressText, setZipProgressText] = useState('');
38
+ const [zipProgressValue, setZipProgressValue] = useState(0);
39
+ const [zipProgressMax, setZipProgressMax] = useState(0);
35
40
  const [hasSavedLayout, setHasSavedLayout] = useState(() => {
36
41
  const saved = SDKUI_Globals.userSettings.documentDownloadSettings;
37
42
  const defaults = new DocumentDownloadSettings();
@@ -171,7 +176,7 @@ const TMCopyToFolderForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationVi
171
176
  retrieveOptions.invoiceRetrieveFormat = settings.invoiceFormat ?? SDKUI_Globals.userSettings.searchSettings.invoiceRetrieveFormat;
172
177
  retrieveOptions.orderRetrieveFormat = settings.orderFormat ?? SDKUI_Globals.userSettings.searchSettings.orderRetrieveFormat;
173
178
  if (settings.exportMode === 'copy') {
174
- await downloadDcmtsAsync(dcmtInfosToDownload, DownloadTypes.Dcmt, 'download', writeFileToFolder, undefined, true, retrieveOptions, false);
179
+ await downloadDcmtsAsync({ inputDcmts: dcmtInfosToDownload, downloadType: DownloadTypes.Dcmt, downloadMode: 'download', onFileDownloaded: writeFileToFolder, skipConfirmation: true, retrieveOptions, useCache: false });
175
180
  }
176
181
  else if (settings.exportMode === 'zip') {
177
182
  const zipEntries = [];
@@ -194,38 +199,55 @@ const TMCopyToFolderForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationVi
194
199
  });
195
200
  zipEntries.push({ filename: getUniqueZipFileName(targetFileName), data: file });
196
201
  };
197
- await downloadDcmtsAsync(dcmtInfosToDownload, DownloadTypes.Dcmt, 'download', collectFileForZip, undefined, true, retrieveOptions, false);
202
+ await downloadDcmtsAsync({ inputDcmts: dcmtInfosToDownload, downloadType: DownloadTypes.Dcmt, downloadMode: 'download', onFileDownloaded: collectFileForZip, skipConfirmation: true, retrieveOptions, useCache: false });
198
203
  if (zipEntries.length > 0) {
199
204
  const zipFileName = settings.zipFileName.trim().toLowerCase().endsWith('.zip')
200
205
  ? settings.zipFileName.trim()
201
206
  : settings.zipFileName.trim() + '.zip';
202
207
  // Crea il blob ZIP
203
- const zipBlob = await ZipManager.createZip(zipEntries, {
204
- compressionLevel: 6,
205
- password: settings.zipPassword.trim() || undefined,
206
- });
207
- // Se c'è un handle della cartella: salva direttamente nella cartella selezionata
208
- if (folderHandleRef.current) {
209
- try {
210
- // Per lo ZIP usa sempre rename automatico (come fa il browser)
211
- const finalZipFileName = await generateUniqueFileName(folderHandleRef.current, zipFileName);
212
- const fileHandle = await folderHandleRef.current.getFileHandle(finalZipFileName, { create: true });
213
- const writable = await fileHandle.createWritable();
214
- await writable.write(zipBlob);
215
- await writable.close();
216
- ShowAlert({ message: SDKUI_Localizator.ZipCreatedSavedInFolder.replaceParams(finalZipFileName, folderHandleRef.current.name), mode: 'success', duration: 5000, title: SDKUI_Localizator.CompressToZipFile });
208
+ setIsCreatingZip(true);
209
+ setZipProgressMax(zipEntries.length);
210
+ setZipProgressValue(0);
211
+ setZipProgressText(SDKUI_Localizator.CompressToZipFile);
212
+ try {
213
+ const zipBlob = await ZipManager.createZip(zipEntries, {
214
+ compressionLevel: 6,
215
+ password: settings.zipPassword.trim() || undefined,
216
+ onProgress: (current, total, filename) => {
217
+ setZipProgressValue(current);
218
+ setZipProgressText(`${SDKUI_Localizator.CompressToZipFile}: ${filename}`);
219
+ },
220
+ });
221
+ // Se c'è un handle della cartella: salva direttamente nella cartella selezionata
222
+ if (folderHandleRef.current) {
223
+ try {
224
+ // Per lo ZIP usa sempre rename automatico (come fa il browser)
225
+ const finalZipFileName = await generateUniqueFileName(folderHandleRef.current, zipFileName);
226
+ const fileHandle = await folderHandleRef.current.getFileHandle(finalZipFileName, { create: true });
227
+ const writable = await fileHandle.createWritable();
228
+ await writable.write(zipBlob);
229
+ await writable.close();
230
+ ShowAlert({ message: SDKUI_Localizator.ZipCreatedSavedInFolder.replaceParams(finalZipFileName, folderHandleRef.current.name), mode: 'success', duration: 5000, title: SDKUI_Localizator.CompressToZipFile });
231
+ }
232
+ catch (err) {
233
+ console.error('Error saving ZIP to folder, fallback to standard download:', err);
234
+ // Fallback: download standard del browser
235
+ ZipManager.downloadBlob(zipBlob, zipFileName);
236
+ ShowAlert({ message: SDKUI_Localizator.ZipCreatedSavedInFolder.replaceParams(zipFileName, "Download"), mode: 'success', duration: 5000, title: SDKUI_Localizator.CompressToZipFile });
237
+ }
217
238
  }
218
- catch (err) {
219
- console.error('Error saving ZIP to folder, fallback to standard download:', err);
220
- // Fallback: download standard del browser
239
+ else {
240
+ // Se non c'è un handle della cartella: download zip standard del browser
221
241
  ZipManager.downloadBlob(zipBlob, zipFileName);
222
242
  ShowAlert({ message: SDKUI_Localizator.ZipCreatedSavedInFolder.replaceParams(zipFileName, "Download"), mode: 'success', duration: 5000, title: SDKUI_Localizator.CompressToZipFile });
223
243
  }
224
244
  }
225
- else {
226
- // Se non c'è un handle della cartella: download zip standard del browser
227
- ZipManager.downloadBlob(zipBlob, zipFileName);
228
- ShowAlert({ message: SDKUI_Localizator.ZipCreatedSavedInFolder.replaceParams(zipFileName, "Download"), mode: 'success', duration: 5000, title: SDKUI_Localizator.CompressToZipFile });
245
+ catch (err) {
246
+ console.error('Error creating ZIP:', err);
247
+ ShowAlert({ message: SDKUI_Localizator.Error, mode: 'error', duration: 5000, title: SDKUI_Localizator.CompressToZipFile });
248
+ }
249
+ finally {
250
+ setIsCreatingZip(false);
229
251
  }
230
252
  }
231
253
  }
@@ -355,7 +377,7 @@ const TMCopyToFolderForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationVi
355
377
  { value: 'skip', display: SDKUI_Localizator.DoNotCopy },
356
378
  { value: 'rename', display: SDKUI_Localizator.CopyButRename },
357
379
  ], value: isUsingDefaultDownloads ? 'rename' : settings.fileExistsMode, direction: "row", disabled: isUsingDefaultDownloads, onValueChanged: (value) => updateSettings('fileExistsMode', value), fontSize: '0.9rem' }) }), isUsingDefaultDownloads && (_jsx("span", { style: { fontSize: '0.8rem', color: '#888', fontStyle: 'italic', marginTop: '4px', display: 'block' }, children: SDKUI_Localizator.BrowserAutoRenamesDuplicateFilesInDownloadsFolder }))] }) }), fileNamingRow, formatSelectorsRow] })), settings.exportMode === 'zip' && (_jsxs("div", { style: { display: 'flex', flexWrap: 'wrap', columnGap: '10px' }, children: [_jsxs("div", { style: { display: 'flex', flexWrap: 'wrap', columnGap: '10px', width: '100%' }, children: [folderSelector, _jsx("div", { style: { flex: '1 1 280px', minWidth: '280px' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.ZipFileName, value: settings.zipFileName, validationItems: zipValidationItems, autoComplete: "one-time-code", onValueChanged: (e) => updateSettings('zipFileName', e.target.value) }) }), _jsx("div", { style: { flex: '1 1 280px', minWidth: '280px' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.ProtectWithPasswordOptional, value: settings.zipPassword, type: "password", autoComplete: "one-time-code", onValueChanged: (e) => updateSettings('zipPassword', e.target.value) }) })] }), fileNamingRow, formatSelectorsRow] }))] })] }));
358
- return (_jsx(TMModal, { width: calcResponsiveSizes(deviceType, showTMRelationViewer ? '95%' : '950px', '95%', '95%'), height: showTMRelationViewer ? '95%' : 'auto', title: getTitle(), onClose: onClose, showCloseButton: true, children: _jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsxs("div", { onContextMenu: (e) => e.preventDefault(), style: { display: 'flex', flexDirection: 'column', padding: '4px 4px 16px 4px', width: '100%', height: '100%', boxSizing: 'border-box', overflow: 'hidden' }, children: [showTMRelationViewer ? (_jsx("div", { style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: _jsxs(TMSplitterLayout, { direction: 'vertical', showSeparator: true, separatorSize: 8, separatorColor: 'transparent', separatorActiveColor: 'transparent', overflow: 'hidden', min: ["50", "50"], start: ['65%', '35%'], children: [_jsx(TMDownloadRelationViewerSection, { selectedDcmtInfos: selectedDcmtInfos, onSelectionChanged: setSelectedItemsRelationViewer, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), configSection] }, "TMCopyToFolder-relation-config") })) : (configSection), _jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', flexShrink: 0, marginTop: '12px' }, children: _jsxs("button", { disabled: !isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0), onClick: run, style: {
380
+ return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel || isCreatingZip, showWaitPanelPrimary: isCreatingZip ? true : showPrimary, showWaitPanelSecondary: isCreatingZip ? false : showSecondary, waitPanelTitle: isCreatingZip ? SDKUI_Localizator.CompressToZipFile : waitPanelTitle, waitPanelTextPrimary: isCreatingZip ? zipProgressText : waitPanelTextPrimary, waitPanelValuePrimary: isCreatingZip ? zipProgressValue : waitPanelValuePrimary, waitPanelMaxValuePrimary: isCreatingZip ? zipProgressMax : waitPanelMaxValuePrimary, waitPanelTextSecondary: isCreatingZip ? '' : waitPanelTextSecondary, waitPanelValueSecondary: isCreatingZip ? 0 : waitPanelValueSecondary, waitPanelMaxValueSecondary: isCreatingZip ? 0 : waitPanelMaxValueSecondary, isCancelable: !isCreatingZip, abortController: abortController, usePortal: true, children: _jsx(TMModal, { width: calcResponsiveSizes(deviceType, showTMRelationViewer ? '95%' : '950px', '95%', '95%'), height: showTMRelationViewer ? '95%' : 'auto', title: getTitle(), onClose: onClose, showCloseButton: true, children: _jsxs("div", { onContextMenu: (e) => e.preventDefault(), style: { display: 'flex', flexDirection: 'column', padding: '4px 4px 16px 4px', width: '100%', height: '100%', boxSizing: 'border-box', overflow: 'hidden' }, children: [showTMRelationViewer ? (_jsx("div", { style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: _jsxs(TMSplitterLayout, { direction: 'vertical', showSeparator: true, separatorSize: 8, separatorColor: 'transparent', separatorActiveColor: 'transparent', overflow: 'hidden', min: ["50", "50"], start: ['65%', '35%'], children: [_jsx(TMDownloadRelationViewerSection, { selectedDcmtInfos: selectedDcmtInfos, onSelectionChanged: setSelectedItemsRelationViewer, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), configSection] }, "TMCopyToFolder-relation-config") })) : (configSection), _jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', flexShrink: 0, marginTop: '12px' }, children: _jsxs("button", { disabled: !isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0), onClick: run, style: {
359
381
  display: 'flex',
360
382
  alignItems: 'center',
361
383
  justifyContent: 'center',
@@ -922,9 +922,14 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
922
922
  setWaitPanelValueSecondaryLocal(pd.ProgressBarValue);
923
923
  setWaitPanelTextSecondaryLocal(`${SDKUI_Localizator.Archiving}... ${Globalization.getNumberDisplayValue(pd.ProgressBarValue, true)} / ${Globalization.getNumberDisplayValue(maxFileSize, true)}`);
924
924
  if (pd.ProgressBarValue === pd.ProgressBarMaximum) {
925
- setWaitPanelMaxValueSecondaryLocal(0);
926
- setWaitPanelValueSecondaryLocal(0);
927
- setWaitPanelTextSecondaryLocal('');
925
+ // Cambia subito il titolo alla fase 2 quando l'upload termina
926
+ // e mostra la progress bar primaria con valore iniziale 20%
927
+ setWaitPanelTitleLocal(SDKUI_Localizator.ArchivingCompletionInProgress);
928
+ setShowSecondaryLocal(false);
929
+ setShowPrimaryLocal(true);
930
+ setWaitPanelMaxValuePrimaryLocal(3);
931
+ setWaitPanelValuePrimaryLocal(0.6); // 20% di 3
932
+ setWaitPanelTextPrimaryLocal(SDKUI_Localizator.ArchivingCompletionInProgress);
928
933
  firstBlock = true;
929
934
  }
930
935
  });
@@ -933,11 +938,22 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
933
938
  const savedFormData = structuredClone(formDataRef.current);
934
939
  setFormDataOrig(savedFormData);
935
940
  formDataOrigRef.current = savedFormData;
941
+ // Fase 2: Completamento archiviazione (la progress bar primaria è già visibile dal callback)
942
+ // Imposta il titolo anche qui per sicurezza, nel caso il callback non venga eseguito
943
+ setWaitPanelTitleLocal(SDKUI_Localizator.ArchivingCompletionInProgress);
944
+ // Step 1/3: Aggiornamento griglia di ricerca
945
+ setWaitPanelValuePrimaryLocal(1);
936
946
  await onRefreshSearchAsyncDatagrid?.();
947
+ // Step 2/3: Callback di salvataggio
948
+ setWaitPanelValuePrimaryLocal(2);
937
949
  await onSavedAsyncCallback?.(ae.TID, newDID);
950
+ // Step 3/3: Aggiornamento lista metadati
951
+ setWaitPanelValuePrimaryLocal(3);
938
952
  // Usa fromDTDRef.current invece di fromDTD per evitare stale closure,
939
953
  // garantendo di avere il descrittore del tipo documento corrente.
940
954
  await setMetadataList(fromDTDRef.current?.metadata ?? [], undefined, true, newDID);
955
+ // Breve pausa per mostrare il completamento al 100%
956
+ await new Promise(resolve => setTimeout(resolve, 200));
941
957
  handleReset();
942
958
  let newMruTIDS = updateMruTids(SDKUI_Globals.userSettings.archivingSettings.mruTIDs, TID);
943
959
  SDKUI_Globals.userSettings.archivingSettings.mruTIDs = newMruTIDS;
@@ -951,12 +967,6 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
951
967
  TMExceptionBoxManager.show({ exception: err });
952
968
  }
953
969
  finally {
954
- setWaitPanelTextPrimaryLocal('');
955
- setWaitPanelMaxValuePrimaryLocal(0);
956
- setWaitPanelValuePrimaryLocal(0);
957
- setWaitPanelTextSecondaryLocal('');
958
- setWaitPanelMaxValueSecondaryLocal(0);
959
- setWaitPanelValueSecondaryLocal(0);
960
970
  setShowWaitPanelLocal(false);
961
971
  setUseWaitPanelLocalState(false);
962
972
  }
@@ -30,5 +30,5 @@ interface TMDcmtFormActionButtonsProps {
30
30
  setShowMoreInfoTaskPopup: React.Dispatch<React.SetStateAction<boolean>>;
31
31
  setShowMoreInfoTaskTask: React.Dispatch<React.SetStateAction<TaskDescriptor | undefined>>;
32
32
  }
33
- declare const TMDcmtFormActionButtons: (props: TMDcmtFormActionButtonsProps) => import("react/jsx-runtime").JSX.Element;
33
+ declare const TMDcmtFormActionButtons: (props: TMDcmtFormActionButtonsProps) => React.JSX.Element;
34
34
  export default TMDcmtFormActionButtons;
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import { DcmtInfo, DownloadModes, DownloadTypes } from '../../../ts';
2
3
  import { FileDescriptor } from '@topconsultnpm/sdk-ts';
3
4
  interface ITMDcmtIconProps {
@@ -14,5 +15,5 @@ interface ITMDcmtIconProps {
14
15
  openInOffice?: (selectedDcmtsOrFocused: Array<DcmtInfo>) => Promise<void>;
15
16
  onDownloadDcmtsAsync?: (inputDcmts: DcmtInfo[] | undefined, downloadType: DownloadTypes, downloadMode: DownloadModes, onFileDownloaded?: (dcmtFile: File | undefined) => void, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>) => Promise<void>;
16
17
  }
17
- declare const TMDcmtIcon: ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode, tooltipContent, openInOffice, onDownloadDcmtsAsync }: ITMDcmtIconProps) => import("react/jsx-runtime").JSX.Element;
18
+ declare const TMDcmtIcon: ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode, tooltipContent, openInOffice, onDownloadDcmtsAsync }: ITMDcmtIconProps) => React.JSX.Element;
18
19
  export default TMDcmtIcon;
@@ -41,7 +41,7 @@ const TMDcmtIcon = ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isS
41
41
  await onDownloadDcmtsAsync?.(dcmt, DownloadTypes.Dcmt, effectiveDownloadMode);
42
42
  }
43
43
  else {
44
- await downloadDcmtsAsync(dcmt, DownloadTypes.Dcmt, effectiveDownloadMode);
44
+ await downloadDcmtsAsync({ inputDcmts: dcmt, downloadType: DownloadTypes.Dcmt, downloadMode: effectiveDownloadMode });
45
45
  }
46
46
  }
47
47
  }, [tid, did, fileExtension, downloadMode, openInOffice, onDownloadDcmtsAsync, downloadDcmtsAsync]);
@@ -25,7 +25,7 @@ export declare const TMNothingToShow: ({ text, secondText, fileExt, icon }: {
25
25
  secondText?: any;
26
26
  fileExt?: string;
27
27
  icon?: any;
28
- }) => import("react/jsx-runtime").JSX.Element;
28
+ }) => React.JSX.Element;
29
29
  export declare const StyledHeaderIcon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$color"> & {
30
30
  $color: string;
31
31
  }, never> & Partial<Pick<import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$color"> & {
@@ -1,3 +1,4 @@
1
+ import React from "react";
1
2
  import { FormModes, TaskContext } from "../../../ts";
2
3
  import { HomeBlogPost, TaskDescriptor } from "@topconsultnpm/sdk-ts";
3
4
  interface TMDcmtTasksProps {
@@ -12,5 +13,5 @@ interface TMDcmtTasksProps {
12
13
  handleNavigateToDossiers?: (value: HomeBlogPost | number) => Promise<void>;
13
14
  onBack?: () => void;
14
15
  }
15
- declare const TMDcmtTasks: (props: TMDcmtTasksProps) => import("react/jsx-runtime").JSX.Element;
16
+ declare const TMDcmtTasks: (props: TMDcmtTasksProps) => React.JSX.Element;
16
17
  export default TMDcmtTasks;
@@ -2,5 +2,5 @@ interface TMDragDropOverlayProps {
2
2
  handleFile: (file: File) => void;
3
3
  refocusAfterFileInput: () => void;
4
4
  }
5
- declare const TMDragDropOverlay: (props: TMDragDropOverlayProps) => import("react/jsx-runtime").JSX.Element;
5
+ declare const TMDragDropOverlay: (props: TMDragDropOverlayProps) => import("react").JSX.Element;
6
6
  export default TMDragDropOverlay;
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { HomeBlogPost, SearchResultDescriptor, TaskDescriptor } from '@topconsultnpm/sdk-ts';
3
3
  import { RelationTreeItem } from './TMRelationViewer';
4
- import { MergePdfManagerType } from '../../../helper';
5
4
  import { DcmtInfo, TaskContext, MetadataValueDescriptorEx } from '../../../ts';
6
5
  import { DeviceContextProps } from '../../base/TMDeviceProvider';
7
6
  export type IRelatedDcmt = RelationTreeItem;
@@ -29,7 +28,6 @@ interface ITMMasterDetailDcmtsProps extends DeviceContextProps {
29
28
  openS4TViewer?: boolean;
30
29
  onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: (() => Promise<void>)) => void;
31
30
  onOpenPdfEditorRequest?: ((dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: () => Promise<void>) => void);
32
- mergePdfManager?: MergePdfManagerType;
33
31
  datagridUtility?: {
34
32
  onRefreshSearchAsyncDatagrid?: () => Promise<void>;
35
33
  onRefreshDataRowsAsync?: (() => Promise<void>);
@@ -16,7 +16,7 @@ import TMDcmtForm from './TMDcmtForm';
16
16
  import { TMNothingToShow } from './TMDcmtPreview';
17
17
  import { Spinner, TMButton } from '../..';
18
18
  import { useDocumentOperations } from '../../../hooks/useDocumentOperations';
19
- const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, appendMasterDcmts, onTaskCreateRequest, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, datagridUtility, dcmtUtility, mergePdfManager }) => {
19
+ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, appendMasterDcmts, onTaskCreateRequest, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, datagridUtility, dcmtUtility, }) => {
20
20
  const floatingBarContainerRef = useRef(null);
21
21
  const [focusedItem, setFocusedItem] = useState();
22
22
  const [selectedItems, setSelectedItems] = useState([]);
@@ -211,7 +211,6 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
211
211
  openTaskFormHandler,
212
212
  onRefreshAfterAddDcmtToFavs,
213
213
  },
214
- mergePdfManager: mergePdfManager
215
214
  });
216
215
  // Load dtdMaster when inputDcmts changes
217
216
  useEffect(() => {
@@ -305,7 +304,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
305
304
  position: contextMenuPosition,
306
305
  onClose: () => setContextMenuVisible(false)
307
306
  } })] }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound, onItemContextMenu, contextMenuVisible, contextMenuPosition, refreshKey, focusedItemFormData]);
308
- const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { refreshKey: refreshKeyFormOrResult, deviceType: deviceType, focusedItem: focusedItem, onTaskCreateRequest: onTaskCreateRequest, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, handleNavigateToReference: handleNavigateToReference, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onRefreshSearchResults: onRefreshAllPanels, mergePdfManager: mergePdfManager }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers, handleNavigateToReference, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshAfterAddDcmtToFavs, refreshKeyFormOrResult]);
307
+ const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { refreshKey: refreshKeyFormOrResult, deviceType: deviceType, focusedItem: focusedItem, onTaskCreateRequest: onTaskCreateRequest, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, handleNavigateToReference: handleNavigateToReference, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onRefreshSearchResults: onRefreshAllPanels }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers, handleNavigateToReference, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshAfterAddDcmtToFavs, refreshKeyFormOrResult]);
309
308
  const initialPanelDimensions = {
310
309
  'tmTreeView': { width: '50%', height: '100%' },
311
310
  'tmFormOrResult': { width: '50%', height: '100%' },
@@ -424,11 +423,11 @@ const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurr
424
423
  }, [onItemContextMenu, handleFocusedItemChanged]);
425
424
  return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, showExpandAllButton: true, onNoRelationsFound: onNoRelationsFound, onItemContextMenu: onContextMenu, focusedItemFormData: focusedItemFormData }, refreshKey));
426
425
  };
427
- const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCreateRequest, allTasks = [], mergePdfManager, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid, onRefreshSearchResults, handleNavigateToReference }) => {
426
+ const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid, onRefreshSearchResults, handleNavigateToReference }) => {
428
427
  const { setPanelVisibilityById } = useTMPanelManagerContext();
429
428
  return (_jsx(_Fragment, { children: focusedItem?.isDcmt ?
430
429
  _jsx(TMDcmtForm, { groupId: 'tmFormOrResult', TID: focusedItem?.tid, DID: focusedItem.did, allowButtonsRefs: true, isClosable: deviceType !== DeviceType.MOBILE, allowNavigation: false, allowRelations: deviceType !== DeviceType.MOBILE, showDcmtFormSidebar: false, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, onReferenceClick: handleNavigateToReference, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, focusedItem?.tid, focusedItem?.did), openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, datagridUtility: {
431
430
  onRefreshSearchAsyncDatagrid,
432
431
  } }, refreshKey) :
433
- _jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, enablePinIcons: false, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, showBackButton: false, onRefreshSearchAsyncDatagrid: onRefreshSearchResults, mergePdfManager: mergePdfManager, onReferenceClick: handleNavigateToReference }, refreshKey) }));
432
+ _jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, autoFocusFirstRow: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, enablePinIcons: false, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, showBackButton: false, onRefreshSearchAsyncDatagrid: onRefreshSearchResults, onReferenceClick: handleNavigateToReference }, refreshKey) }));
434
433
  };
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { DcmtInfo } from '../../../ts';
3
- import { MergePdfManagerType } from '../../../helper';
4
3
  import { HomeBlogPost, TaskDescriptor } from '@topconsultnpm/sdk-ts';
5
4
  import { TMCopyToFolderMode } from '../../../hooks/useDocumentOperations';
6
5
  interface ITMMergeToPdfFormProps {
@@ -8,7 +7,6 @@ interface ITMMergeToPdfFormProps {
8
7
  selectedDcmtInfos: Array<DcmtInfo>;
9
8
  onClose: () => void;
10
9
  showTMRelationViewer: boolean;
11
- mergePdfManager?: MergePdfManagerType;
12
10
  allTasks?: Array<TaskDescriptor>;
13
11
  getAllTasks?: () => Promise<void>;
14
12
  deleteTaskByIdsCallback?: (deletedTaskIds: Array<number>) => Promise<void>;
@@ -15,17 +15,23 @@ import TMDownloadRelationViewerSection from './TMDownloadRelationViewerSection';
15
15
  import { getDcmtInfosToDownload, getFloatingLabelStyle, isDirectoryPickerSupported, isPdfExt, MIN_PDF_FOR_MERGE, } from './copyAndMergeDcmtsShared';
16
16
  import ShowAlert from '../../base/TMAlert';
17
17
  import TMTooltip from '../../base/TMTooltip';
18
+ import MergePdfManager from '../../../helper/MergePdfManager';
18
19
  /**
19
20
  * Form per l'unione di più documenti PDF in un singolo file.
20
21
  * Condivide TMDownloadRelationViewerSection e gli helper in copyAndMergeDcmtsShared
21
22
  * con TMCopyToFolderForm.
22
23
  */
23
- const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationViewer, mergePdfManager, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
24
+ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationViewer, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
24
25
  const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, } = useDcmtOperations();
25
26
  const deviceType = useDeviceType();
26
- const [pdfFileName, setPdfFileName] = useState('merged.pdf');
27
+ const [pdfFileName, setPdfFileName] = useState(`${SDKUI_Localizator.Result.toLowerCase()}.pdf`);
27
28
  const [destinationFolder, setDestinationFolder] = useState('Download');
28
29
  const [selectedItemsRelationViewer, setSelectedItemsRelationViewer] = useState([]);
30
+ // ---- Stato per il merge PDF (progress bar) ----
31
+ const [isMergingPdf, setIsMergingPdf] = useState(false);
32
+ const [mergeProgressText, setMergeProgressText] = useState('');
33
+ const [mergeProgressValue, setMergeProgressValue] = useState(0);
34
+ const [mergeProgressMax, setMergeProgressMax] = useState(0);
29
35
  // ---- Ref per la selezione cartella (File System Access API) ----
30
36
  const folderHandleRef = useRef(null);
31
37
  const skipSelectFolderRef = useRef(false);
@@ -137,7 +143,7 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
137
143
  const collectFileForMerge = async (file, _dcmtInfo) => {
138
144
  pdfFiles.push(file);
139
145
  };
140
- await downloadDcmtsAsync(pdfDcmtInfosToDownload, DownloadTypes.Dcmt, 'download', collectFileForMerge, undefined, true, rfo, false);
146
+ await downloadDcmtsAsync({ inputDcmts: pdfDcmtInfosToDownload, downloadType: DownloadTypes.Dcmt, downloadMode: 'download', onFileDownloaded: collectFileForMerge, skipConfirmation: true, retrieveOptions: rfo, useCache: false });
141
147
  if (pdfFiles.length === 0) {
142
148
  TMMessageBoxManager.show({ message: SDKUI_Localizator.NoFilesAvailableForMerge, buttons: [ButtonNames.OK] });
143
149
  return null;
@@ -150,18 +156,25 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
150
156
  TMMessageBoxManager.show({ message: SDKUI_Localizator.PleaseCorrectErrorsBeforeProceeding, buttons: [ButtonNames.OK] });
151
157
  return;
152
158
  }
153
- if (!mergePdfManager) {
154
- TMMessageBoxManager.show({ message: SDKUI_Localizator.PdfMergeFeatureNotAvailable, buttons: [ButtonNames.OK] });
155
- return;
156
- }
157
159
  const pdfFiles = await collectPdfFilesToMerge();
158
160
  if (!pdfFiles)
159
161
  return;
160
162
  const finalName = pdfFileName.trim().toLowerCase().endsWith('.pdf') ? pdfFileName.trim() : pdfFileName.trim() + '.pdf';
163
+ // Inizializza progress bar per il merge
164
+ setIsMergingPdf(true);
165
+ setMergeProgressMax(pdfFiles.length);
166
+ setMergeProgressValue(0);
167
+ setMergeProgressText(SDKUI_Localizator.MergeToPdf);
161
168
  try {
169
+ const mergeOptions = {
170
+ onProgress: (current, total, file) => {
171
+ setMergeProgressValue(current);
172
+ setMergeProgressText(`${SDKUI_Localizator.MergeToPdf}: ${file.name}`);
173
+ }
174
+ };
162
175
  // Se c'è una cartella selezionata (non Download di default), salva direttamente nella cartella
163
176
  if (folderHandleRef.current) {
164
- const mergedFile = await mergePdfManager.mergeToFile(pdfFiles, finalName);
177
+ const mergedFile = await MergePdfManager.mergeToFile(pdfFiles, finalName, mergeOptions);
165
178
  const fileHandle = await folderHandleRef.current.getFileHandle(finalName, { create: true });
166
179
  const writable = await fileHandle.createWritable();
167
180
  await writable.write(mergedFile);
@@ -170,7 +183,7 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
170
183
  }
171
184
  else {
172
185
  // Altrimenti usa il download standard del browser
173
- await mergePdfManager.mergeAndDownload(pdfFiles, finalName);
186
+ await MergePdfManager.mergeAndDownload(pdfFiles, finalName, mergeOptions);
174
187
  ShowAlert({ message: SDKUI_Localizator.PdfMergedSavedInFolder.replaceParams('Download'), mode: 'success', duration: 5000, title: SDKUI_Localizator.MergeToPdf });
175
188
  }
176
189
  }
@@ -179,6 +192,9 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
179
192
  TMMessageBoxManager.show({ message: SDKUI_Localizator.PdfMergeError, buttons: [ButtonNames.OK] });
180
193
  return;
181
194
  }
195
+ finally {
196
+ setIsMergingPdf(false);
197
+ }
182
198
  onClose();
183
199
  };
184
200
  // ---- Render della sezione configurazione (solo PDF file name + warning) ----
@@ -265,7 +281,7 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
265
281
  ? SDKUI_Localizator.FileNotPdfWillBeExcluded.replaceParams(extLabel)
266
282
  : SDKUI_Localizator.FilesNotPdfWillBeExcluded.replaceParams(nonPdfSelectedItems.length.toString(), extLabel);
267
283
  })() }))] })] }))] })] }));
268
- return (_jsx(TMModal, { width: calcResponsiveSizes(deviceType, showTMRelationViewer ? '90%' : '500px', showTMRelationViewer ? '90%' : '500px', '95%'), height: showTMRelationViewer ? '95%' : 'auto', title: getTitle(), onClose: onClose, showCloseButton: true, children: _jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsxs("div", { onContextMenu: (e) => e.preventDefault(), style: { display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px', width: '100%', height: '100%', boxSizing: 'border-box', overflow: 'hidden' }, children: [showTMRelationViewer ? (_jsx("div", { style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: _jsxs(TMSplitterLayout, { direction: 'vertical', showSeparator: true, separatorSize: 8, separatorColor: 'transparent', separatorActiveColor: 'transparent', overflow: 'hidden', min: ["50", "50"], start: ["70%", "30%"], children: [_jsx(TMDownloadRelationViewerSection, { selectedDcmtInfos: selectedDcmtInfos, onSelectionChanged: setSelectedItemsRelationViewer, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), configSection] }, "TMMergeToPdf-relation-config") })) : (configSection), _jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', flexShrink: 0, marginTop: '12px' }, children: _jsxs("button", { disabled: !isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0) || !hasEnoughPdfForMerge, onClick: run, style: {
284
+ return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel || isMergingPdf, showWaitPanelPrimary: isMergingPdf ? true : showPrimary, showWaitPanelSecondary: isMergingPdf ? false : showSecondary, waitPanelTitle: isMergingPdf ? SDKUI_Localizator.MergeToPdf : waitPanelTitle, waitPanelTextPrimary: isMergingPdf ? mergeProgressText : waitPanelTextPrimary, waitPanelValuePrimary: isMergingPdf ? mergeProgressValue : waitPanelValuePrimary, waitPanelMaxValuePrimary: isMergingPdf ? mergeProgressMax : waitPanelMaxValuePrimary, waitPanelTextSecondary: isMergingPdf ? '' : waitPanelTextSecondary, waitPanelValueSecondary: isMergingPdf ? 0 : waitPanelValueSecondary, waitPanelMaxValueSecondary: isMergingPdf ? 0 : waitPanelMaxValueSecondary, isCancelable: !isMergingPdf, abortController: abortController, usePortal: true, children: _jsx(TMModal, { width: calcResponsiveSizes(deviceType, showTMRelationViewer ? '90%' : '500px', showTMRelationViewer ? '90%' : '500px', '95%'), height: showTMRelationViewer ? '95%' : 'auto', title: getTitle(), onClose: onClose, showCloseButton: true, children: _jsxs("div", { onContextMenu: (e) => e.preventDefault(), style: { display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px', width: '100%', height: '100%', boxSizing: 'border-box', overflow: 'hidden' }, children: [showTMRelationViewer ? (_jsx("div", { style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: _jsxs(TMSplitterLayout, { direction: 'vertical', showSeparator: true, separatorSize: 8, separatorColor: 'transparent', separatorActiveColor: 'transparent', overflow: 'hidden', min: ["50", "50"], start: ["70%", "30%"], children: [_jsx(TMDownloadRelationViewerSection, { selectedDcmtInfos: selectedDcmtInfos, onSelectionChanged: setSelectedItemsRelationViewer, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), configSection] }, "TMMergeToPdf-relation-config") })) : (configSection), _jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', flexShrink: 0, marginTop: '12px' }, children: _jsxs("button", { disabled: !isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0) || !hasEnoughPdfForMerge, onClick: run, style: {
269
285
  display: 'flex',
270
286
  alignItems: 'center',
271
287
  justifyContent: 'center',
@@ -1236,9 +1236,14 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
1236
1236
  border: `1px solid ${TMColors.border_normal}`,
1237
1237
  borderRadius: '4px',
1238
1238
  cursor: 'pointer',
1239
- lineHeight: 1,
1240
- whiteSpace: 'nowrap'
1241
- }, children: [allExpanded ? _jsx(IconChevronRight, { fontSize: 14 }) : _jsx(IconChevronDown, { fontSize: 14 }), _jsx("span", { children: allExpanded ? SDKUI_Localizator.CollapseAll : SDKUI_Localizator.ExpandAll })] }) })), _jsx("div", { style: { flex: 1, minHeight: 0, overflow: 'auto' }, children: _jsx(TMTreeView, { dataSource: mergedTreeData, itemRender: finalItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: handleDataChanged, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, itemsPerPage: 100, onSelectionChanged: handleSelectedItemsChanged, onItemContextMenu: onItemContextMenu }) }), showExpansionWaitPanel && (_jsx(TMWaitPanel, { title: isForMaster ? 'Caricamento documenti master' : 'Caricamento documenti dettaglio', showPrimary: true, textPrimary: expansionWaitPanelText, valuePrimary: expansionWaitPanelValue, maxValuePrimary: expansionWaitPanelMaxValue, isCancelable: true, abortController: expansionAbortController, onAbortClick: (abortController) => {
1239
+ whiteSpace: 'nowrap',
1240
+ outline: 'none'
1241
+ }, children: [_jsx("span", { style: { display: 'flex', alignItems: 'center' }, children: allExpanded ? _jsx(IconChevronRight, { fontSize: 14 }) : _jsx(IconChevronDown, { fontSize: 14 }) }), _jsx("span", { children: allExpanded ? SDKUI_Localizator.CollapseAll : SDKUI_Localizator.ExpandAll })] }) })), _jsx("div", { style: { flex: 1, minHeight: 0, overflow: 'auto' }, children: _jsx(TMTreeView, { dataSource: mergedTreeData, itemRender: finalItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: handleDataChanged, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, itemsPerPage: 100, onSelectionChanged: handleSelectedItemsChanged, onItemContextMenu: onItemContextMenu, shouldDelayFocusOnEvent: (node, e) => {
1242
+ // Ritarda il focus quando si clicca sull'icona del documento
1243
+ // per permettere al doppio click di funzionare
1244
+ const target = e.target;
1245
+ return !!target.closest('.tm-dcmt-icon');
1246
+ } }) }), showExpansionWaitPanel && (_jsx(TMWaitPanel, { title: isForMaster ? 'Caricamento documenti master' : 'Caricamento documenti dettaglio', showPrimary: true, textPrimary: expansionWaitPanelText, valuePrimary: expansionWaitPanelValue, maxValuePrimary: expansionWaitPanelMaxValue, isCancelable: true, abortController: expansionAbortController, onAbortClick: (abortController) => {
1242
1247
  setTimeout(() => {
1243
1248
  abortController?.abort();
1244
1249
  }, 100);
@@ -19,19 +19,6 @@ export declare const isDirectoryPickerSupported: () => boolean;
19
19
  * il file viene restituito senza firma.
20
20
  */
21
21
  export declare const isPdfExt: (ext: string | null | undefined) => boolean;
22
- /**
23
- * Estrae l'estensione completa da un nome file, gestendo estensioni composite
24
- * a più livelli come .PDF.P7M, .XML.P7M.TS, etc.
25
- *
26
- * Esempi:
27
- * - "documento.pdf" -> ".pdf"
28
- * - "DCMT_123.PDF.P7M" -> ".PDF.P7M"
29
- * - "fattura.xml.p7m" -> ".xml.p7m"
30
- * - "example.XML.P7M.TS" -> ".XML.P7M.TS"
31
- * - "file.tar.gz" -> ".gz" (tar.gz non è gestito come firma)
32
- * - "file" -> ""
33
- */
34
- export declare const getFullFileExtension: (fileName: string, depth?: number) => string;
35
22
  /**
36
23
  * Estrae il nome base del file (senza estensione completa).
37
24
  * Gestisce estensioni composite come .PDF.P7M
@@ -1,5 +1,5 @@
1
1
  import { DcmtTypeListCacheService, LayoutModes, SDK_Globals } from '@topconsultnpm/sdk-ts';
2
- import { searchResultToMetadataValues, DocumentDownloadSettings } from '../../../helper';
2
+ import { searchResultToMetadataValues, DocumentDownloadSettings, getFullFileExtension } from '../../../helper';
3
3
  import { TMColors } from '../../../utils/theme';
4
4
  /** Numero minimo di file PDF necessari per poterli unire in un unico documento. */
5
5
  export const MIN_PDF_FOR_MERGE = 2;
@@ -61,44 +61,6 @@ export const isPdfExt = (ext) => {
61
61
  const normalized = ext.trim().toLowerCase().replace(/^\./, '');
62
62
  return normalized === 'pdf' || normalized === 'pdf.p7m' || normalized === 'pdf.tsd' || normalized === 'pdf.m7m';
63
63
  };
64
- /**
65
- * Estensioni di firma/marca temporale note che possono avvolgere altre estensioni.
66
- * Es: file.pdf.p7m, file.xml.p7m, file.docx.p7m, file.xml.p7m.ts
67
- */
68
- const SIGNATURE_EXTENSIONS = new Set(['p7m', 'p7s', 'm7m', 'tsd', 'tsr', 'ts']);
69
- /** Profondità massima di ricorsione per la ricerca di estensioni composite */
70
- const MAX_EXTENSION_DEPTH = 5;
71
- /**
72
- * Estrae l'estensione completa da un nome file, gestendo estensioni composite
73
- * a più livelli come .PDF.P7M, .XML.P7M.TS, etc.
74
- *
75
- * Esempi:
76
- * - "documento.pdf" -> ".pdf"
77
- * - "DCMT_123.PDF.P7M" -> ".PDF.P7M"
78
- * - "fattura.xml.p7m" -> ".xml.p7m"
79
- * - "example.XML.P7M.TS" -> ".XML.P7M.TS"
80
- * - "file.tar.gz" -> ".gz" (tar.gz non è gestito come firma)
81
- * - "file" -> ""
82
- */
83
- export const getFullFileExtension = (fileName, depth = 0) => {
84
- if (!fileName || depth > MAX_EXTENSION_DEPTH)
85
- return '';
86
- const lastDotIndex = fileName.lastIndexOf('.');
87
- if (lastDotIndex <= 0)
88
- return '';
89
- const lastExtension = fileName.substring(lastDotIndex + 1).toLowerCase();
90
- // Se l'ultima estensione è una firma/marca, cerca ricorsivamente le estensioni precedenti
91
- if (SIGNATURE_EXTENSIONS.has(lastExtension)) {
92
- const nameWithoutLastExt = fileName.substring(0, lastDotIndex);
93
- const innerExtension = getFullFileExtension(nameWithoutLastExt, depth + 1);
94
- if (innerExtension) {
95
- // Concatena l'estensione interna con quella corrente
96
- return innerExtension + fileName.substring(lastDotIndex);
97
- }
98
- }
99
- // Estensione singola (o estensione base dopo le firme)
100
- return fileName.substring(lastDotIndex);
101
- };
102
64
  /**
103
65
  * Estrae il nome base del file (senza estensione completa).
104
66
  * Gestisce estensioni composite come .PDF.P7M
@@ -1,8 +1,9 @@
1
+ import React from "react";
1
2
  import { DcmtInfo } from "../../../ts";
2
3
  interface TMDcmtCheckoutInfoFormProps {
3
4
  dtdName: string;
4
5
  selectedDcmtOrFocused: DcmtInfo;
5
6
  onClose: () => void;
6
7
  }
7
- declare const TMDcmtCheckoutInfoForm: (props: TMDcmtCheckoutInfoFormProps) => import("react/jsx-runtime").JSX.Element;
8
+ declare const TMDcmtCheckoutInfoForm: (props: TMDcmtCheckoutInfoFormProps) => React.JSX.Element;
8
9
  export default TMDcmtCheckoutInfoForm;
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ import { MetadataDescriptor, QueryDescriptor, SelectItem } from "@topconsultnpm/sdk-ts";
3
+ interface TMMetadataOutputFormProps {
4
+ /** QueryDescriptor da cui estrarre i metadati disponibili */
5
+ qd?: QueryDescriptor;
6
+ /** Lista di SelectItem attualmente selezionati */
7
+ selectedSelectItems?: SelectItem[];
8
+ /** Consente di visualizzare i metadati di sistema (es. MID < 150) */
9
+ allowSysMetadata?: boolean;
10
+ /** Funzione predicato per filtrare i metadati (es. solo quelli con permesso canView) */
11
+ filterMetadata?: (value: MetadataDescriptor, index: number, array: MetadataDescriptor[]) => unknown;
12
+ /** Callback chiamata alla chiusura del form */
13
+ onClose: () => void;
14
+ /** Callback chiamata quando l'utente conferma la selezione dei SelectItem */
15
+ onChoose?: (selectItems: SelectItem[] | undefined) => void;
16
+ }
17
+ declare const TMMetadataOutputForm: (props: TMMetadataOutputFormProps) => React.JSX.Element;
18
+ export default TMMetadataOutputForm;