@topconsultnpm/sdkui-react 6.21.0-t1 → 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 (197) 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 +10 -10
  4. package/lib/components/base/Styled.d.ts +1 -1
  5. package/lib/components/base/TMAccordionNew.d.ts +1 -0
  6. package/lib/components/base/TMAccordionNew.js +6 -5
  7. package/lib/components/base/TMAreaManager.js +30 -3
  8. package/lib/components/base/TMCounterBar.d.ts +2 -2
  9. package/lib/components/base/TMCounterContainer.d.ts +2 -1
  10. package/lib/components/base/TMCustomButton.d.ts +1 -1
  11. package/lib/components/base/TMDataGrid.js +14 -4
  12. package/lib/components/base/TMDataGridExportForm.d.ts +2 -1
  13. package/lib/components/base/TMDataGridExportForm.js +19 -8
  14. package/lib/components/base/TMFileManager.d.ts +2 -1
  15. package/lib/components/base/TMFileManagerDataGridView.d.ts +2 -1
  16. package/lib/components/base/TMFileManagerDataGridView.js +4 -4
  17. package/lib/components/base/TMFileManagerThumbnailItems.d.ts +1 -1
  18. package/lib/components/base/TMFileManagerThumbnailItems.js +3 -3
  19. package/lib/components/base/TMFileManagerThumbnailsView.d.ts +1 -1
  20. package/lib/components/base/TMFileManagerUtils.d.ts +7 -0
  21. package/lib/components/base/TMFileManagerUtils.js +14 -1
  22. package/lib/components/base/TMLayout.d.ts +4 -4
  23. package/lib/components/base/TMList.d.ts +2 -1
  24. package/lib/components/base/TMListView.d.ts +1 -1
  25. package/lib/components/base/TMModal.d.ts +1 -0
  26. package/lib/components/base/TMModal.js +4 -4
  27. package/lib/components/base/TMPanel.d.ts +7 -4
  28. package/lib/components/base/TMPanel.js +58 -26
  29. package/lib/components/base/TMPopUp.d.ts +1 -0
  30. package/lib/components/base/TMPopUp.js +59 -2
  31. package/lib/components/base/TMSpinner.d.ts +5 -2
  32. package/lib/components/base/TMSpinner.js +33 -6
  33. package/lib/components/base/TMTab.d.ts +4 -3
  34. package/lib/components/base/TMTooltip.d.ts +1 -1
  35. package/lib/components/base/TMTreeView.d.ts +1 -1
  36. package/lib/components/base/TMTreeView.js +24 -17
  37. package/lib/components/base/TMUserAvatar.d.ts +2 -1
  38. package/lib/components/base/TMVilViewer.d.ts +2 -1
  39. package/lib/components/base/TMWaitPanel.d.ts +5 -2
  40. package/lib/components/base/TMWaitPanel.js +14 -9
  41. package/lib/components/choosers/TMDistinctValues.js +35 -21
  42. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +1 -1
  43. package/lib/components/choosers/TMDynDataListItemChooser.js +6 -1
  44. package/lib/components/choosers/TMGroupChooser.js +1 -1
  45. package/lib/components/choosers/TMInvoiceRetrieveFormats.d.ts +2 -1
  46. package/lib/components/choosers/TMOrderRetrieveFormats.d.ts +2 -1
  47. package/lib/components/choosers/TMRelationChooser.d.ts +3 -3
  48. package/lib/components/choosers/TMUserChooser.d.ts +6 -2
  49. package/lib/components/choosers/TMUserChooser.js +7 -5
  50. package/lib/components/editors/TMDateBox.js +4 -2
  51. package/lib/components/editors/TMEditorStyled.d.ts +6 -6
  52. package/lib/components/editors/TMFormulaEditor.d.ts +4 -1
  53. package/lib/components/editors/TMFormulaEditor.js +125 -22
  54. package/lib/components/editors/TMHtmlContentDisplay.d.ts +2 -1
  55. package/lib/components/editors/TMHtmlEditor.d.ts +2 -1
  56. package/lib/components/editors/TMMetadataEditor.js +6 -2
  57. package/lib/components/editors/TMMetadataValues.js +25 -7
  58. package/lib/components/editors/TMRadioButton.js +7 -5
  59. package/lib/components/editors/TMTextArea.d.ts +2 -0
  60. package/lib/components/editors/TMTextArea.js +6 -3
  61. package/lib/components/editors/TMTextBox.d.ts +2 -0
  62. package/lib/components/editors/TMTextBox.js +3 -3
  63. package/lib/components/editors/TMTreeDropDown.d.ts +1 -1
  64. package/lib/components/features/archive/TMArchive.js +1 -1
  65. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.d.ts +1 -1
  66. package/lib/components/features/blog/TMBlogCommentForm.d.ts +2 -1
  67. package/lib/components/features/blog/TMBlogCommentForm.js +5 -2
  68. package/lib/components/features/documents/TMCopyToFolderForm.d.ts +24 -0
  69. package/lib/components/features/documents/TMCopyToFolderForm.js +401 -0
  70. package/lib/components/features/documents/TMDcmtForm.d.ts +1 -0
  71. package/lib/components/features/documents/TMDcmtForm.js +166 -54
  72. package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +1 -1
  73. package/lib/components/features/documents/TMDcmtFormActionButtons.js +259 -60
  74. package/lib/components/features/documents/TMDcmtIcon.d.ts +2 -1
  75. package/lib/components/features/documents/TMDcmtIcon.js +1 -1
  76. package/lib/components/features/documents/TMDcmtPreview.d.ts +2 -1
  77. package/lib/components/features/documents/TMDcmtPreview.js +2 -2
  78. package/lib/components/features/documents/TMDcmtTasks.d.ts +3 -1
  79. package/lib/components/features/documents/TMDcmtTasks.js +2 -2
  80. package/lib/components/features/documents/TMDownloadRelationViewerSection.d.ts +23 -0
  81. package/lib/components/features/documents/TMDownloadRelationViewerSection.js +173 -0
  82. package/lib/components/features/documents/TMDragDropOverlay.d.ts +1 -1
  83. package/lib/components/features/documents/TMFileUploader.js +1 -1
  84. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
  85. package/lib/components/features/documents/TMMasterDetailDcmts.js +28 -9
  86. package/lib/components/features/documents/TMMergeToPdfForm.d.ts +24 -0
  87. package/lib/components/features/documents/TMMergeToPdfForm.js +309 -0
  88. package/lib/components/features/documents/TMRelationViewer.d.ts +13 -0
  89. package/lib/components/features/documents/TMRelationViewer.js +80 -6
  90. package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +58 -0
  91. package/lib/components/features/documents/copyAndMergeDcmtsShared.js +266 -0
  92. package/lib/components/features/search/SignatureParamsManager.d.ts +70 -0
  93. package/lib/components/features/search/SignatureParamsManager.js +145 -0
  94. package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +2 -1
  95. package/lib/components/features/search/TMMetadataOutputForm.d.ts +18 -0
  96. package/lib/components/features/search/TMMetadataOutputForm.js +225 -0
  97. package/lib/components/features/search/TMMetadataSorterForm.d.ts +18 -0
  98. package/lib/components/features/search/TMMetadataSorterForm.js +243 -0
  99. package/lib/components/features/search/TMSavedQuerySelector.d.ts +3 -3
  100. package/lib/components/features/search/TMSavedQuerySelector.js +3 -2
  101. package/lib/components/features/search/TMSearch.d.ts +4 -1
  102. package/lib/components/features/search/TMSearch.js +16 -10
  103. package/lib/components/features/search/TMSearchQueryEditor.js +14 -8
  104. package/lib/components/features/search/TMSearchQueryPanel.js +250 -59
  105. package/lib/components/features/search/TMSearchResult.d.ts +3 -0
  106. package/lib/components/features/search/TMSearchResult.js +154 -38
  107. package/lib/components/features/search/TMSearchResultFloatingActionButton.d.ts +1 -1
  108. package/lib/components/features/search/TMSignatureInfoContent.d.ts +2 -1
  109. package/lib/components/features/search/TMViewHistoryDcmt.d.ts +2 -1
  110. package/lib/components/features/search/TMViewHistoryDcmt.js +2 -3
  111. package/lib/components/features/search/metadataFormHelper.d.ts +16 -0
  112. package/lib/components/features/search/metadataFormHelper.js +77 -0
  113. package/lib/components/features/tasks/TMTaskForm.d.ts +1 -1
  114. package/lib/components/features/tasks/TMTaskFormUtils.d.ts +10 -10
  115. package/lib/components/features/tasks/TMTasksAgenda.d.ts +1 -1
  116. package/lib/components/features/tasks/TMTasksCalendar.d.ts +1 -1
  117. package/lib/components/features/tasks/TMTasksHeader.d.ts +1 -1
  118. package/lib/components/features/tasks/TMTasksPanelContent.d.ts +1 -1
  119. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +5 -5
  120. package/lib/components/features/tasks/TMTasksView.d.ts +1 -1
  121. package/lib/components/features/wg/TMWGsCopyMoveForm.d.ts +3 -2
  122. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +8 -7
  123. package/lib/components/features/workflow/TMWorkflowPopup.js +3 -0
  124. package/lib/components/features/workflow/diagram/queryDescriptorParser.js +3 -6
  125. package/lib/components/forms/Login/Chooser.d.ts +2 -2
  126. package/lib/components/forms/Login/TMLoginForm.d.ts +9 -0
  127. package/lib/components/forms/Login/TMLoginForm.js +76 -3
  128. package/lib/components/forms/TMChooserForm.d.ts +2 -1
  129. package/lib/components/forms/TMResultDialog.d.ts +1 -1
  130. package/lib/components/forms/TMResultDialog.js +4 -2
  131. package/lib/components/forms/TMSaveForm.d.ts +4 -4
  132. package/lib/components/grids/TMBlogAttachments.d.ts +3 -1
  133. package/lib/components/grids/TMBlogAttachments.js +39 -13
  134. package/lib/components/grids/TMBlogHeader.d.ts +1 -1
  135. package/lib/components/grids/TMBlogsPost.d.ts +1 -1
  136. package/lib/components/grids/TMBlogsPost.js +12 -4
  137. package/lib/components/grids/TMBlogsPostUtils.d.ts +10 -9
  138. package/lib/components/grids/TMBlogsPostUtils.js +14 -18
  139. package/lib/components/grids/TMValidationItemsList.d.ts +2 -1
  140. package/lib/components/index.d.ts +1 -0
  141. package/lib/components/index.js +1 -0
  142. package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +2 -1
  143. package/lib/components/layout/panelManager/TMPanelManagerContext.d.ts +2 -2
  144. package/lib/components/layout/panelManager/TMPanelManagerToolbar.d.ts +1 -1
  145. package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.d.ts +2 -2
  146. package/lib/components/layout/panelManager/TMPanelWrapper.d.ts +2 -2
  147. package/lib/components/pages/TMPage.d.ts +1 -1
  148. package/lib/components/pages/TMPage.js +3 -1
  149. package/lib/components/query/TMQueryEditor.js +2 -2
  150. package/lib/components/settings/SettingsAppearance.d.ts +2 -1
  151. package/lib/components/sidebar/TMAboutApp.d.ts +2 -1
  152. package/lib/components/sidebar/TMHeader.d.ts +3 -3
  153. package/lib/components/viewers/TMDataListItemViewer.d.ts +3 -2
  154. package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +3 -2
  155. package/lib/components/viewers/TMMidViewer.d.ts +2 -2
  156. package/lib/components/viewers/TMTidViewer.d.ts +2 -2
  157. package/lib/components/viewers/TMTidViewer.js +1 -1
  158. package/lib/components/wizard/TMWizard.d.ts +1 -0
  159. package/lib/components/wizard/TMWizard.js +5 -3
  160. package/lib/helper/Enum_Localizator.js +1 -0
  161. package/lib/helper/GlobalStyles.js +6 -0
  162. package/lib/helper/MergePdfManager.d.ts +45 -0
  163. package/lib/helper/MergePdfManager.js +148 -0
  164. package/lib/helper/SDKUI_Globals.d.ts +15 -0
  165. package/lib/helper/SDKUI_Globals.js +16 -1
  166. package/lib/helper/SDKUI_Localizator.d.ts +112 -2
  167. package/lib/helper/SDKUI_Localizator.js +1120 -12
  168. package/lib/helper/TMCommandsContextMenu.d.ts +1 -1
  169. package/lib/helper/TMIcons.d.ts +278 -278
  170. package/lib/helper/TMPdfViewer.d.ts +2 -1
  171. package/lib/helper/TMPdfViewer.js +25 -24
  172. package/lib/helper/TMToppyMessage.d.ts +2 -2
  173. package/lib/helper/TMUtils.d.ts +25 -1
  174. package/lib/helper/TMUtils.js +72 -0
  175. package/lib/helper/ZipManager.d.ts +56 -0
  176. package/lib/helper/ZipManager.js +127 -0
  177. package/lib/helper/checkinCheckoutManager.d.ts +4 -3
  178. package/lib/helper/checkinCheckoutManager.js +29 -11
  179. package/lib/helper/helpers.d.ts +3 -2
  180. package/lib/helper/helpers.js +1 -0
  181. package/lib/helper/index.d.ts +1 -0
  182. package/lib/helper/index.js +1 -0
  183. package/lib/hooks/useCheckInOutOperations.d.ts +4 -3
  184. package/lib/hooks/useDataUserIdItem.js +6 -4
  185. package/lib/hooks/useDcmtOperations.d.ts +26 -2
  186. package/lib/hooks/useDcmtOperations.js +292 -38
  187. package/lib/hooks/useDocumentOperations.d.ts +3 -0
  188. package/lib/hooks/useDocumentOperations.js +254 -26
  189. package/lib/hooks/useForm.js +5 -2
  190. package/lib/hooks/useInputDialog.d.ts +2 -1
  191. package/lib/hooks/useRelatedDocuments.js +4 -4
  192. package/lib/hooks/useResizeObserver.d.ts +1 -1
  193. package/lib/hooks/useResizeObserver.js +16 -15
  194. package/lib/services/platform_services.d.ts +7 -6
  195. package/lib/ts/types.d.ts +3 -1
  196. package/lib/ts/types.js +1 -0
  197. package/package.json +15 -7
@@ -0,0 +1,401 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useRef, useState } from 'react';
3
+ import { DownloadTypes } from '../../../ts';
4
+ import { calcResponsiveSizes, DocumentDownloadSettings, IconDelete, IconFolderOpen, IconPlay, IconSave, IconUndo, SDKUI_Globals, SDKUI_Localizator, ZipManager, } from '../../../helper';
5
+ import { DcmtOpers, GeneralRetrieveFormats, ResultTypes, RetrieveFileOptions, ValidationItem, } from '@topconsultnpm/sdk-ts';
6
+ import TMModal from '../../base/TMModal';
7
+ import { useDeviceType } from '../../base/TMDeviceProvider';
8
+ import TMRadioButton from '../../editors/TMRadioButton';
9
+ import TMTextBox from '../../editors/TMTextBox';
10
+ import TMDropDown from '../../editors/TMDropDown';
11
+ import TMInvoiceRetrieveFormats from '../../choosers/TMInvoiceRetrieveFormats';
12
+ import TMOrderRetrieveFormats from '../../choosers/TMOrderRetrieveFormats';
13
+ import TMButton from '../../base/TMButton';
14
+ import { ButtonNames, TMMessageBoxManager } from '../../base/TMPopUp';
15
+ import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
16
+ import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
17
+ import { TMSplitterLayout } from '../../base/TMLayout';
18
+ import TMCheckBox from '../../editors/TMCheckBox';
19
+ import ShowAlert from '../../base/TMAlert';
20
+ import { TMColors } from '../../../utils/theme';
21
+ import TMDownloadRelationViewerSection from './TMDownloadRelationViewerSection';
22
+ import { buildInitialDownloadSettings, fileExists, generateTargetFileName, generateUniqueFileName, getDcmtInfosToDownload, getFloatingLabelStyle, isDirectoryPickerSupported, } from './copyAndMergeDcmtsShared';
23
+ /**
24
+ * Form per la copia/zip dei documenti in una cartella locale.
25
+ * Logica condivisa con TMMergeToPdfForm è esternalizzata in copyAndMergeDcmtsShared
26
+ * e TMDownloadRelationViewerSection.
27
+ */
28
+ const TMCopyToFolderForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationViewer, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
29
+ const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, } = useDcmtOperations();
30
+ // Get the current device type (e.g., mobile, tablet, desktop) using a custom hook.
31
+ const deviceType = useDeviceType();
32
+ // ---- Stato dei settings ----
33
+ const [settings, setSettings] = useState(() => buildInitialDownloadSettings(SDKUI_Globals.userSettings.documentDownloadSettings, SDKUI_Globals.userSettings.searchSettings.invoiceRetrieveFormat, SDKUI_Globals.userSettings.searchSettings.orderRetrieveFormat));
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);
40
+ const [hasSavedLayout, setHasSavedLayout] = useState(() => {
41
+ const saved = SDKUI_Globals.userSettings.documentDownloadSettings;
42
+ const defaults = new DocumentDownloadSettings();
43
+ return JSON.stringify(saved) !== JSON.stringify(defaults);
44
+ });
45
+ const updateSettings = (key, value) => {
46
+ setSettings(prev => ({ ...prev, [key]: value }));
47
+ };
48
+ // ---- Ref per la selezione cartella (File System Access API) ----
49
+ const folderHandleRef = useRef(null);
50
+ const skipSelectFolderRef = useRef(false);
51
+ const isPickerActiveRef = useRef(false);
52
+ const getTitle = () => {
53
+ const count = ` (${selectedDcmtInfos.length})`;
54
+ const modeLabelMap = {
55
+ onlySelected: SDKUI_Localizator.SelectedDocuments,
56
+ customized: SDKUI_Localizator.SelectedDocumentsAndRelated,
57
+ };
58
+ const modeLabel = modeLabelMap[mode] || modeLabelMap.onlySelected;
59
+ return `${SDKUI_Localizator.CopyToFolder} - ${modeLabel}${count}`;
60
+ };
61
+ const isUsingDefaultDownloads = settings.destinationFolder === 'Download' && !folderHandleRef.current;
62
+ // ---- Validazione ----
63
+ const { folderValidationItems, zipValidationItems } = useMemo(() => {
64
+ const folderItems = [];
65
+ const zipItems = [];
66
+ if (settings.exportMode === 'copy' && !settings.destinationFolder.trim()) {
67
+ folderItems.push(new ValidationItem(ResultTypes.ERROR, SDKUI_Localizator.FolderName, SDKUI_Localizator.RequiredField));
68
+ }
69
+ if (settings.exportMode === 'zip' && !settings.zipFileName.trim()) {
70
+ zipItems.push(new ValidationItem(ResultTypes.ERROR, SDKUI_Localizator.ZipFileName, SDKUI_Localizator.RequiredField));
71
+ }
72
+ return { folderValidationItems: folderItems, zipValidationItems: zipItems };
73
+ }, [settings.exportMode, settings.destinationFolder, settings.zipFileName]);
74
+ const isFormValid = () => {
75
+ if (settings.exportMode === 'copy')
76
+ return folderValidationItems.length === 0;
77
+ if (settings.exportMode === 'zip')
78
+ return zipValidationItems.length === 0;
79
+ return false;
80
+ };
81
+ // ---- Handler dei campi ----
82
+ const handleFolderValueChange = (e) => {
83
+ updateSettings('destinationFolder', e.target.value);
84
+ folderHandleRef.current = null;
85
+ };
86
+ const handleSelectFolder = async () => {
87
+ if (skipSelectFolderRef.current) {
88
+ skipSelectFolderRef.current = false;
89
+ return;
90
+ }
91
+ if (isPickerActiveRef.current)
92
+ return;
93
+ try {
94
+ isPickerActiveRef.current = true;
95
+ const dirHandle = await window.showDirectoryPicker({ mode: 'readwrite' });
96
+ folderHandleRef.current = dirHandle;
97
+ updateSettings('destinationFolder', dirHandle.name);
98
+ }
99
+ catch (err) {
100
+ if (err.name !== 'AbortError') {
101
+ console.error('Error selecting folder:', err);
102
+ }
103
+ }
104
+ finally {
105
+ isPickerActiveRef.current = false;
106
+ }
107
+ };
108
+ const handleFileNamingModeChange = (e) => {
109
+ updateSettings('fileNamingMode', e.target.value);
110
+ };
111
+ const handleSeparatorChange = (e) => {
112
+ updateSettings('separatorChar', e.target.value.slice(0, 1));
113
+ };
114
+ // ---- Scrittura file nel filesystem locale ----
115
+ const writeFileToFolder = async (file, dcmtInfo) => {
116
+ try {
117
+ let targetFileName = await generateTargetFileName(file, dcmtInfo, {
118
+ fileNamingMode: settings.fileNamingMode,
119
+ separatorChar: settings.separatorChar,
120
+ });
121
+ // Se non c'è un handle della cartella: download standard del browser
122
+ if (!folderHandleRef.current) {
123
+ const url = URL.createObjectURL(file);
124
+ const a = document.createElement('a');
125
+ a.href = url;
126
+ a.download = targetFileName;
127
+ document.body.appendChild(a);
128
+ a.target = '_blank';
129
+ a.rel = 'noreferrer';
130
+ a.click();
131
+ document.body.removeChild(a);
132
+ URL.revokeObjectURL(url);
133
+ return;
134
+ }
135
+ const exists = await fileExists(folderHandleRef.current, targetFileName);
136
+ if (exists) {
137
+ switch (settings.fileExistsMode) {
138
+ case 'skip':
139
+ return;
140
+ case 'rename':
141
+ targetFileName = await generateUniqueFileName(folderHandleRef.current, targetFileName);
142
+ break;
143
+ case 'overwrite':
144
+ default:
145
+ break;
146
+ }
147
+ }
148
+ const fileHandle = await folderHandleRef.current.getFileHandle(targetFileName, { create: true });
149
+ const writable = await fileHandle.createWritable();
150
+ await writable.write(file);
151
+ await writable.close();
152
+ }
153
+ catch (err) {
154
+ console.error('Errore nella scrittura del file:', err);
155
+ throw err;
156
+ }
157
+ };
158
+ // ---- Esecuzione (Copia oppure ZIP) ----
159
+ const run = async () => {
160
+ if (settings.exportMode === 'copy' && folderValidationItems.length > 0) {
161
+ TMMessageBoxManager.show({ message: SDKUI_Localizator.PleaseCorrectErrorsBeforeProceeding, buttons: [ButtonNames.OK] });
162
+ return;
163
+ }
164
+ if (settings.exportMode === 'zip' && zipValidationItems.length > 0) {
165
+ TMMessageBoxManager.show({ message: SDKUI_Localizator.PleaseCorrectErrorsBeforeProceeding, buttons: [ButtonNames.OK] });
166
+ return;
167
+ }
168
+ const dcmtInfosToDownload = getDcmtInfosToDownload(selectedDcmtInfos, selectedItemsRelationViewer, showTMRelationViewer);
169
+ if (dcmtInfosToDownload.length === 0) {
170
+ TMMessageBoxManager.show({ message: SDKUI_Localizator.NoDocumentsSelected, buttons: [ButtonNames.OK] });
171
+ return;
172
+ }
173
+ const retrieveOptions = new RetrieveFileOptions();
174
+ retrieveOptions.retrieveReason = DcmtOpers.None;
175
+ retrieveOptions.generalRetrieveFormat = settings.removeSignature ? GeneralRetrieveFormats.OriginalUnsigned : GeneralRetrieveFormats.Original;
176
+ retrieveOptions.invoiceRetrieveFormat = settings.invoiceFormat ?? SDKUI_Globals.userSettings.searchSettings.invoiceRetrieveFormat;
177
+ retrieveOptions.orderRetrieveFormat = settings.orderFormat ?? SDKUI_Globals.userSettings.searchSettings.orderRetrieveFormat;
178
+ if (settings.exportMode === 'copy') {
179
+ await downloadDcmtsAsync({ inputDcmts: dcmtInfosToDownload, downloadType: DownloadTypes.Dcmt, downloadMode: 'download', onFileDownloaded: writeFileToFolder, skipConfirmation: true, retrieveOptions, useCache: false });
180
+ }
181
+ else if (settings.exportMode === 'zip') {
182
+ const zipEntries = [];
183
+ const fileNameCounts = new Map();
184
+ const getUniqueZipFileName = (fileName) => {
185
+ const lowerName = fileName.toLowerCase();
186
+ const count = fileNameCounts.get(lowerName) ?? 0;
187
+ fileNameCounts.set(lowerName, count + 1);
188
+ if (count === 0)
189
+ return fileName;
190
+ const dotIndex = fileName.lastIndexOf('.');
191
+ const baseName = dotIndex > 0 ? fileName.substring(0, dotIndex) : fileName;
192
+ const ext = dotIndex > 0 ? fileName.substring(dotIndex) : '';
193
+ return `${baseName} (${count})${ext}`;
194
+ };
195
+ const collectFileForZip = async (file, dcmtInfo) => {
196
+ const targetFileName = await generateTargetFileName(file, dcmtInfo, {
197
+ fileNamingMode: settings.fileNamingMode,
198
+ separatorChar: settings.separatorChar,
199
+ });
200
+ zipEntries.push({ filename: getUniqueZipFileName(targetFileName), data: file });
201
+ };
202
+ await downloadDcmtsAsync({ inputDcmts: dcmtInfosToDownload, downloadType: DownloadTypes.Dcmt, downloadMode: 'download', onFileDownloaded: collectFileForZip, skipConfirmation: true, retrieveOptions, useCache: false });
203
+ if (zipEntries.length > 0) {
204
+ const zipFileName = settings.zipFileName.trim().toLowerCase().endsWith('.zip')
205
+ ? settings.zipFileName.trim()
206
+ : settings.zipFileName.trim() + '.zip';
207
+ // Crea il blob ZIP
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
+ }
238
+ }
239
+ else {
240
+ // Se non c'è un handle della cartella: download zip standard del browser
241
+ ZipManager.downloadBlob(zipBlob, zipFileName);
242
+ ShowAlert({ message: SDKUI_Localizator.ZipCreatedSavedInFolder.replaceParams(zipFileName, "Download"), mode: 'success', duration: 5000, title: SDKUI_Localizator.CompressToZipFile });
243
+ }
244
+ }
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);
251
+ }
252
+ }
253
+ }
254
+ else {
255
+ TMMessageBoxManager.show({ message: SDKUI_Localizator.ExportModeNotSupported, buttons: [ButtonNames.OK] });
256
+ return;
257
+ }
258
+ onClose();
259
+ };
260
+ // ---- Layout salva/rimuovi ----
261
+ const saveLayout = () => {
262
+ const { zipPassword, ...settingsToSave } = settings;
263
+ SDKUI_Globals.userSettings.documentDownloadSettings = { ...settingsToSave, zipPassword: '' };
264
+ const defaults = new DocumentDownloadSettings();
265
+ const hasChanges = JSON.stringify(settings) !== JSON.stringify(defaults);
266
+ if (hasChanges) {
267
+ setHasSavedLayout(true);
268
+ ShowAlert({ mode: 'success', message: SDKUI_Localizator.OperationSuccess, title: SDKUI_Localizator.Save, duration: 3000 });
269
+ }
270
+ };
271
+ const removeLayout = () => {
272
+ const defaults = new DocumentDownloadSettings();
273
+ SDKUI_Globals.userSettings.documentDownloadSettings = { ...defaults };
274
+ setSettings(defaults);
275
+ folderHandleRef.current = null;
276
+ setHasSavedLayout(false);
277
+ ShowAlert({ mode: 'success', message: SDKUI_Localizator.OperationSuccess, title: SDKUI_Localizator.Remove, duration: 3000 });
278
+ };
279
+ const isLayoutSameAsSaved = () => {
280
+ const saved = SDKUI_Globals.userSettings.documentDownloadSettings;
281
+ if (!saved) {
282
+ const defaults = new DocumentDownloadSettings();
283
+ return JSON.stringify(settings) === JSON.stringify(defaults);
284
+ }
285
+ return JSON.stringify(settings) === JSON.stringify(saved);
286
+ };
287
+ // ---- Componenti comuni riutilizzati in entrambe le modalità (copy/zip) ----
288
+ const folderSelector = isDirectoryPickerSupported() ? (_jsx("div", { style: { flex: '1 1 280px', minWidth: '280px' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.FolderName, value: settings.destinationFolder, validationItems: folderValidationItems, onValueChanged: handleFolderValueChange, readOnly: true, placeHolder: "Download", onClick: handleSelectFolder, buttons: [
289
+ {
290
+ icon: _jsx(IconFolderOpen, {}),
291
+ text: SDKUI_Localizator.SelectFolder,
292
+ onClick: handleSelectFolder
293
+ },
294
+ ...(!isUsingDefaultDownloads ? [{
295
+ icon: _jsx(IconUndo, {}),
296
+ text: SDKUI_Localizator.RestoreDownload,
297
+ onClick: () => {
298
+ skipSelectFolderRef.current = true;
299
+ updateSettings('destinationFolder', 'Download');
300
+ folderHandleRef.current = null;
301
+ }
302
+ }] : [])
303
+ ] }) })) : (_jsx("div", { style: { flex: '1 1 280px', minWidth: '280px' }, children: _jsxs("div", { style: { position: 'relative', marginTop: '16px' }, children: [_jsx("span", { style: {
304
+ position: 'absolute',
305
+ top: '-10px',
306
+ left: '12px',
307
+ fontSize: '0.9rem',
308
+ color: TMColors.label_normal,
309
+ padding: '0 3px',
310
+ userSelect: 'none',
311
+ WebkitTouchCallout: 'none',
312
+ WebkitUserSelect: 'none',
313
+ width: 'max-content',
314
+ backgroundColor: TMColors.default_background,
315
+ zIndex: 1,
316
+ }, children: SDKUI_Localizator.Path }), _jsxs("div", { style: { border: `1px solid ${TMColors.border_normal}`, borderRadius: '5px', padding: '4px 10px 4px 13px', display: 'flex', alignItems: 'center', gap: '8px', backgroundColor: '#fafafa' }, children: [_jsx(IconFolderOpen, {}), _jsx("span", { style: { fontSize: '0.9rem', color: '#333' }, children: "Download" })] }), _jsx("span", { style: { fontSize: '0.8rem', color: '#888', fontStyle: 'italic', marginTop: '4px', display: 'block' }, children: SDKUI_Localizator.BrowserDoesNotSupportFolderSelection })] }) }));
317
+ const fileNamingRow = (_jsxs("div", { style: {
318
+ display: 'flex',
319
+ flexWrap: 'wrap',
320
+ alignItems: 'flex-end',
321
+ gap: '10px',
322
+ width: '100%',
323
+ }, children: [_jsx(TMDropDown, { label: SDKUI_Localizator.UseForFileName, value: settings.fileNamingMode, dataSource: [
324
+ { value: 'onlyDid', display: SDKUI_Localizator.OnlyDID },
325
+ { value: 'documentTypeAndDid', display: SDKUI_Localizator.DocumentTypeNameAndDID },
326
+ { value: 'documentTypeAndCustomMetadata', display: SDKUI_Localizator.DocumentTypeNameAndCustomMetadata },
327
+ { value: 'onlyCustomMetadata', display: SDKUI_Localizator.OnlyCustomMetadata },
328
+ ], onValueChanged: handleFileNamingModeChange, width: '400px' }), _jsx(TMTextBox, { label: SDKUI_Localizator.Separator, value: settings.separatorChar, maxLength: 1, onValueChanged: (e) => handleSeparatorChange(e), width: '100px', elementStyle: { textAlign: 'center' } }), _jsx("div", { style: { paddingBottom: '7px' }, children: _jsx(TMCheckBox, { label: SDKUI_Localizator.RemoveSignatureIfPresent, value: settings.removeSignature, onValueChanged: (value) => updateSettings('removeSignature', value) }) })] }));
329
+ const formatSelectorsRow = (_jsxs("div", { style: { display: 'flex', flexWrap: 'wrap', columnGap: '10px', width: '100%' }, children: [_jsx("div", { style: { flex: '1 1 280px', minWidth: '280px' }, children: _jsx(TMInvoiceRetrieveFormats, { width: '100%', label: SDKUI_Localizator.ElectronicInvoice + ' - ' + SDKUI_Localizator.DisplayFormat, onValueChanged: (newValue) => updateSettings('invoiceFormat', newValue), value: settings.invoiceFormat, valueOrig: settings.invoiceFormat }) }), _jsx("div", { style: { flex: '1 1 280px', minWidth: '280px' }, children: _jsx(TMOrderRetrieveFormats, { width: '100%', label: SDKUI_Localizator.ElectronicOrder + ' - ' + SDKUI_Localizator.DisplayFormat, value: settings.orderFormat, valueOrig: settings.orderFormat, onValueChanged: (newValue) => updateSettings('orderFormat', newValue) }) })] }));
330
+ // ---- Render della sezione configurazione ----
331
+ const configSection = (_jsxs("div", { style: {
332
+ position: 'relative',
333
+ border: `1px solid ${TMColors.border_normal}`,
334
+ borderRadius: '8px',
335
+ padding: '10px 6px 6px 6px',
336
+ height: showTMRelationViewer ? 'calc(100% - 7px)' : undefined,
337
+ marginTop: '7px',
338
+ flex: showTMRelationViewer ? undefined : 1,
339
+ minHeight: 0,
340
+ display: 'flex',
341
+ flexDirection: 'column',
342
+ boxSizing: 'border-box'
343
+ }, children: [_jsx("span", { style: { ...getFloatingLabelStyle(), fontWeight: 600 }, children: SDKUI_Localizator.ConfigurationParameters }), _jsxs("div", { style: {
344
+ position: 'absolute',
345
+ top: '-8px',
346
+ right: '12px',
347
+ display: 'flex',
348
+ alignItems: 'center',
349
+ gap: '4px',
350
+ backgroundColor: 'white',
351
+ padding: '0 4px',
352
+ zIndex: 1
353
+ }, children: [_jsx(TMButton, { btnStyle: "toolbar", icon: _jsx(IconSave, {}), caption: SDKUI_Localizator.SaveLayout, color: "success", disabled: isLayoutSameAsSaved(), onClick: saveLayout }), hasSavedLayout && (_jsx(TMButton, { btnStyle: "toolbar", icon: _jsx(IconDelete, {}), caption: SDKUI_Localizator.RemoveLayout, color: "error", onClick: removeLayout }))] }), _jsxs("div", { style: {
354
+ display: 'flex',
355
+ flexDirection: 'column',
356
+ flex: 1,
357
+ overflowY: 'auto',
358
+ minHeight: 0,
359
+ }, children: [_jsx("div", { style: { display: 'flex', justifyContent: 'flex-start', alignItems: 'center', marginTop: "8px" }, children: _jsx(TMRadioButton, { dataSource: [
360
+ { value: 'copy', display: SDKUI_Localizator.CopyToFolder },
361
+ { value: 'zip', display: SDKUI_Localizator.CompressToZipFile }
362
+ ], value: settings.exportMode, direction: "row", onValueChanged: (value) => updateSettings('exportMode', value) }) }), settings.exportMode === 'copy' && (_jsxs("div", { style: { display: 'flex', flexWrap: 'wrap', columnGap: '10px' }, children: [folderSelector, _jsx("div", { style: { flex: '1.5 1 420px', minWidth: '350px', width: '100%' }, children: _jsxs("div", { style: { position: 'relative', marginTop: '16px' }, children: [_jsx("span", { style: {
363
+ position: 'absolute',
364
+ top: '-10px',
365
+ left: '12px',
366
+ fontSize: '0.9rem',
367
+ color: TMColors.label_normal,
368
+ padding: '0 3px',
369
+ userSelect: 'none',
370
+ WebkitTouchCallout: 'none',
371
+ WebkitUserSelect: 'none',
372
+ width: 'max-content',
373
+ backgroundColor: TMColors.default_background,
374
+ zIndex: 1,
375
+ }, children: SDKUI_Localizator.IfFileExists }), _jsx("div", { style: { border: `1px solid ${TMColors.border_normal}`, borderRadius: '5px', padding: '4px 10px 4px 13px' }, children: _jsx(TMRadioButton, { dataSource: [
376
+ { value: 'overwrite', display: SDKUI_Localizator.CopyAndReplace },
377
+ { value: 'skip', display: SDKUI_Localizator.DoNotCopy },
378
+ { value: 'rename', display: SDKUI_Localizator.CopyButRename },
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] }))] })] }));
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: {
381
+ display: 'flex',
382
+ alignItems: 'center',
383
+ justifyContent: 'center',
384
+ gap: '6px',
385
+ padding: '8px 20px',
386
+ fontSize: '0.95rem',
387
+ fontWeight: 600,
388
+ color: '#fff',
389
+ background: (!isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0))
390
+ ? '#b0b0b0'
391
+ : 'linear-gradient(135deg, #28a745 0%, #218838 100%)',
392
+ border: 'none',
393
+ borderRadius: '6px',
394
+ cursor: (!isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0)) ? 'not-allowed' : 'pointer',
395
+ boxShadow: (!isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0))
396
+ ? 'none'
397
+ : '0 2px 8px rgba(40, 167, 69, 0.35)',
398
+ transition: 'all 0.2s ease',
399
+ }, children: [_jsx(IconPlay, {}), _jsx("span", { children: SDKUI_Localizator.Execute })] }) })] }) }) }));
400
+ };
401
+ export default TMCopyToFolderForm;
@@ -23,6 +23,7 @@ interface ITMDcmtFormProps {
23
23
  showHeader?: boolean;
24
24
  showBackButton?: boolean;
25
25
  showDcmtFormSidebar?: boolean;
26
+ showTodoDcmtForm?: boolean;
26
27
  isExpertMode?: boolean;
27
28
  isClosable?: boolean;
28
29
  isModal?: boolean;