@topconsultnpm/sdkui-react 6.21.0-dev4.7 → 6.21.0-dev4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/features/documents/TMMergeToPdfForm.d.ts +2 -2
- package/lib/components/features/documents/TMMergeToPdfForm.js +91 -48
- package/lib/components/features/documents/TMRelationViewer.js +1 -0
- package/lib/components/features/documents/mergePdfUtils.d.ts +52 -0
- package/lib/components/features/documents/mergePdfUtils.js +268 -0
- package/lib/helper/SDKUI_Localizator.js +12 -12
- package/lib/hooks/useDcmtOperations.js +1 -1
- package/lib/hooks/useDocumentOperations.js +2 -1
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { DcmtInfo } from '../../../ts';
|
|
3
2
|
import { HomeBlogPost, TaskDescriptor } from '@topconsultnpm/sdk-ts';
|
|
4
3
|
import { TMCopyToFolderMode } from '../../../hooks/useDocumentOperations';
|
|
5
4
|
interface ITMMergeToPdfFormProps {
|
|
6
5
|
mode: TMCopyToFolderMode;
|
|
7
6
|
selectedDcmtInfos: Array<DcmtInfo>;
|
|
7
|
+
selectedItemsFull: Array<any>;
|
|
8
8
|
onClose: () => void;
|
|
9
9
|
showTMRelationViewer: boolean;
|
|
10
10
|
allTasks?: Array<TaskDescriptor>;
|
|
@@ -20,5 +20,5 @@ interface ITMMergeToPdfFormProps {
|
|
|
20
20
|
* Condivide TMDownloadRelationViewerSection e gli helper in copyAndMergeDcmtsShared
|
|
21
21
|
* con TMCopyToFolderForm.
|
|
22
22
|
*/
|
|
23
|
-
declare const TMMergeToPdfForm:
|
|
23
|
+
declare const TMMergeToPdfForm: (props: ITMMergeToPdfFormProps) => import("react/jsx-runtime").JSX.Element;
|
|
24
24
|
export default TMMergeToPdfForm;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useRef, useState } from 'react';
|
|
3
3
|
import { DownloadTypes } from '../../../ts';
|
|
4
|
-
import { calcResponsiveSizes, IconFolderOpen, IconPlay, IconUndo,
|
|
4
|
+
import { calcResponsiveSizes, getExceptionMessage, IconFolderOpen, IconPlay, IconUndo, SDKUI_Globals, SDKUI_Localizator, } from '../../../helper';
|
|
5
5
|
import { DcmtOpers, FileFormats, GeneralRetrieveFormats, ResultTypes, RetrieveFileOptions, ValidationItem, } from '@topconsultnpm/sdk-ts';
|
|
6
6
|
import TMModal from '../../base/TMModal';
|
|
7
7
|
import { useDeviceType } from '../../base/TMDeviceProvider';
|
|
@@ -12,16 +12,19 @@ import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
|
|
|
12
12
|
import { TMSplitterLayout } from '../../base/TMLayout';
|
|
13
13
|
import { TMColors } from '../../../utils/theme';
|
|
14
14
|
import TMDownloadRelationViewerSection from './TMDownloadRelationViewerSection';
|
|
15
|
-
import { getDcmtInfosToDownload, getFloatingLabelStyle, isDirectoryPickerSupported,
|
|
15
|
+
import { getDcmtInfosToDownload, getFloatingLabelStyle, isDirectoryPickerSupported, MIN_PDF_FOR_MERGE, } from './copyAndMergeDcmtsShared';
|
|
16
|
+
import { createMetadataPdfFromDocument, getMergePdfSelectionStats, isMetadataOnlyDcmt } from './mergePdfUtils';
|
|
16
17
|
import ShowAlert from '../../base/TMAlert';
|
|
17
18
|
import TMTooltip from '../../base/TMTooltip';
|
|
18
19
|
import MergePdfManager from '../../../helper/MergePdfManager';
|
|
20
|
+
import { TMResultManager } from '../../forms/TMResultDialog';
|
|
19
21
|
/**
|
|
20
22
|
* Form per l'unione di più documenti PDF in un singolo file.
|
|
21
23
|
* Condivide TMDownloadRelationViewerSection e gli helper in copyAndMergeDcmtsShared
|
|
22
24
|
* con TMCopyToFolderForm.
|
|
23
25
|
*/
|
|
24
|
-
const TMMergeToPdfForm = (
|
|
26
|
+
const TMMergeToPdfForm = (props) => {
|
|
27
|
+
const { mode, selectedDcmtInfos, selectedItemsFull, onClose, showTMRelationViewer, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers } = props;
|
|
25
28
|
const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, } = useDcmtOperations();
|
|
26
29
|
const deviceType = useDeviceType();
|
|
27
30
|
const [pdfFileName, setPdfFileName] = useState(`${SDKUI_Localizator.Result.toLowerCase()}.pdf`);
|
|
@@ -79,36 +82,7 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
|
|
|
79
82
|
pdfValidationItems.push(new ValidationItem(ResultTypes.ERROR, SDKUI_Localizator.PdfFileName, SDKUI_Localizator.RequiredField));
|
|
80
83
|
}
|
|
81
84
|
// ---- Statistiche selezione PDF / convertibili / non-PDF ----
|
|
82
|
-
const convertibleSelectedItems = (
|
|
83
|
-
if (showTMRelationViewer) {
|
|
84
|
-
return selectedItemsRelationViewer
|
|
85
|
-
.filter(i => i.isDcmt && isConvertibleToPdfExt(i.fileExt))
|
|
86
|
-
.map(i => ({ key: `${i.tid}_${i.did}`, ext: i.fileExt ?? undefined }));
|
|
87
|
-
}
|
|
88
|
-
return selectedDcmtInfos
|
|
89
|
-
.filter(d => isConvertibleToPdfExt(d.FILEEXT))
|
|
90
|
-
.map(d => ({ key: `${d.TID}_${d.DID}`, ext: d.FILEEXT }));
|
|
91
|
-
})();
|
|
92
|
-
const hasConvertibleSelected = convertibleSelectedItems.length > 0;
|
|
93
|
-
const nonPdfSelectedItems = (() => {
|
|
94
|
-
if (showTMRelationViewer) {
|
|
95
|
-
return selectedItemsRelationViewer
|
|
96
|
-
.filter(i => i.isDcmt && !isPdfExt(i.fileExt) && !isConvertibleToPdfExt(i.fileExt))
|
|
97
|
-
.map(i => ({ key: `${i.tid}_${i.did}`, ext: i.fileExt ?? undefined }));
|
|
98
|
-
}
|
|
99
|
-
return selectedDcmtInfos
|
|
100
|
-
.filter(d => !isPdfExt(d.FILEEXT) && !isConvertibleToPdfExt(d.FILEEXT))
|
|
101
|
-
.map(d => ({ key: `${d.TID}_${d.DID}`, ext: d.FILEEXT }));
|
|
102
|
-
})();
|
|
103
|
-
const hasNonPdfSelected = nonPdfSelectedItems.length > 0;
|
|
104
|
-
// Conteggio file unibili: PDF nativi + file convertibili
|
|
105
|
-
const mergeableSelectedCount = (() => {
|
|
106
|
-
if (showTMRelationViewer) {
|
|
107
|
-
return selectedItemsRelationViewer.filter(i => i.isDcmt && (isPdfExt(i.fileExt) || isConvertibleToPdfExt(i.fileExt))).length;
|
|
108
|
-
}
|
|
109
|
-
return selectedDcmtInfos.filter(d => isPdfExt(d.FILEEXT) || isConvertibleToPdfExt(d.FILEEXT)).length;
|
|
110
|
-
})();
|
|
111
|
-
const hasEnoughPdfForMerge = mergeableSelectedCount >= MIN_PDF_FOR_MERGE;
|
|
85
|
+
const { convertibleSelectedItems, hasConvertibleSelected, nonPdfSelectedItems, hasNonPdfSelected, metadataOnlySelectedItems, hasMetadataOnlySelected, mergeableSelectedCount, hasEnoughPdfForMerge, } = getMergePdfSelectionStats(selectedDcmtInfos, selectedItemsFull, selectedItemsRelationViewer, showTMRelationViewer);
|
|
112
86
|
const isFormValid = () => pdfValidationItems.length === 0;
|
|
113
87
|
// ---- Recupero dei file PDF da unire (condiviso tra Esegui e Anteprima) ----
|
|
114
88
|
const collectPdfFilesToMerge = async () => {
|
|
@@ -133,17 +107,81 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
|
|
|
133
107
|
});
|
|
134
108
|
return null;
|
|
135
109
|
}
|
|
110
|
+
// Mappa per lookup veloce di FILECOUNT e FILEEXT da selectedItemsFull
|
|
111
|
+
const fileInfoMap = new Map(selectedItemsFull.map(d => [`${d.TID}_${d.DID}`, { fileExt: d.FILEEXT, fileCount: d.FILECOUNT }]));
|
|
112
|
+
// Mappa per i risultati: mantiene l'ordine originale
|
|
113
|
+
const pdfFilesMap = new Map();
|
|
114
|
+
// Identifica documenti di soli metadati e documenti con file
|
|
115
|
+
const metadataOnlyDcmts = [];
|
|
116
|
+
const dcmtsWithFile = [];
|
|
117
|
+
for (const dcmt of pdfDcmtInfosToDownload) {
|
|
118
|
+
const key = `${dcmt.TID}_${dcmt.DID}`;
|
|
119
|
+
const info = fileInfoMap.get(key);
|
|
120
|
+
if (isMetadataOnlyDcmt(info?.fileExt, info?.fileCount)) {
|
|
121
|
+
metadataOnlyDcmts.push(dcmt);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
dcmtsWithFile.push(dcmt);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Per i documenti di soli metadati, genera PDF con createMetadataPdfFromDocument
|
|
128
|
+
// Raccoglie gli errori come downloadDcmtsAsync
|
|
129
|
+
const metadataConversionResults = [];
|
|
130
|
+
if (metadataOnlyDcmts.length > 0) {
|
|
131
|
+
setIsMergingPdf(true);
|
|
132
|
+
setMergeProgressMax(metadataOnlyDcmts.length);
|
|
133
|
+
setMergeProgressValue(0);
|
|
134
|
+
setMergeProgressText('Creazione PDF metadati...');
|
|
135
|
+
for (let i = 0; i < metadataOnlyDcmts.length; i++) {
|
|
136
|
+
const dcmt = metadataOnlyDcmts[i];
|
|
137
|
+
try {
|
|
138
|
+
setMergeProgressValue(i);
|
|
139
|
+
setMergeProgressText(`Creazione PDF metadati... (${i + 1}/${metadataOnlyDcmts.length})`);
|
|
140
|
+
const conversionResult = await createMetadataPdfFromDocument(dcmt);
|
|
141
|
+
if (conversionResult) {
|
|
142
|
+
pdfFilesMap.set(`${dcmt.TID}_${dcmt.DID}`, conversionResult.file);
|
|
143
|
+
metadataConversionResults.push({ rowIndex: i, id1: dcmt.TID, id2: dcmt.DID, resultType: ResultTypes.SUCCESS });
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// createMetadataPdfFromDocument ha restituito null (errore interno loggato)
|
|
147
|
+
metadataConversionResults.push({ rowIndex: i, id1: dcmt.TID, id2: dcmt.DID, resultType: ResultTypes.ERROR, description: 'Creazione PDF metadati fallita' });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
console.error(`Errore creazione PDF metadati per TID=${dcmt.TID}, DID=${dcmt.DID}`, error);
|
|
152
|
+
metadataConversionResults.push({ rowIndex: i, id1: dcmt.TID, id2: dcmt.DID, resultType: ResultTypes.ERROR, description: getExceptionMessage(error) });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
setMergeProgressValue(metadataOnlyDcmts.length);
|
|
156
|
+
setIsMergingPdf(false);
|
|
157
|
+
// Mostra riepilogo errori se presenti (come downloadDcmtsAsync)
|
|
158
|
+
const hasErrors = metadataConversionResults.some(r => r.resultType === ResultTypes.ERROR);
|
|
159
|
+
if (hasErrors) {
|
|
160
|
+
TMResultManager.show(metadataConversionResults, 'Conversione PDF metadati', 'TID', 'DID', undefined, undefined, false);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Per i documenti con file, usa il download normale
|
|
164
|
+
if (dcmtsWithFile.length > 0) {
|
|
165
|
+
const rfo = new RetrieveFileOptions();
|
|
166
|
+
rfo.retrieveReason = DcmtOpers.None;
|
|
167
|
+
rfo.generalRetrieveFormat = GeneralRetrieveFormats.OriginalUnsigned;
|
|
168
|
+
rfo.cvtFormat = FileFormats.PDF;
|
|
169
|
+
rfo.invoiceRetrieveFormat = SDKUI_Globals.userSettings?.searchSettings.invoiceRetrieveFormat;
|
|
170
|
+
rfo.orderRetrieveFormat = SDKUI_Globals.userSettings?.searchSettings.orderRetrieveFormat;
|
|
171
|
+
const collectFileForMerge = async (file, dcmtInfo) => {
|
|
172
|
+
pdfFilesMap.set(`${dcmtInfo.TID}_${dcmtInfo.DID}`, file);
|
|
173
|
+
};
|
|
174
|
+
await downloadDcmtsAsync({ inputDcmts: dcmtsWithFile, downloadType: DownloadTypes.Dcmt, downloadMode: 'download', onFileDownloaded: collectFileForMerge, skipConfirmation: true, retrieveOptions: rfo, useCache: false });
|
|
175
|
+
}
|
|
176
|
+
// Ricostruisci l'array pdfFiles nell'ordine originale di selezione
|
|
136
177
|
const pdfFiles = [];
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
pdfFiles.push(file);
|
|
145
|
-
};
|
|
146
|
-
await downloadDcmtsAsync({ inputDcmts: pdfDcmtInfosToDownload, downloadType: DownloadTypes.Dcmt, downloadMode: 'download', onFileDownloaded: collectFileForMerge, skipConfirmation: true, retrieveOptions: rfo, useCache: false });
|
|
178
|
+
for (const dcmt of pdfDcmtInfosToDownload) {
|
|
179
|
+
const key = `${dcmt.TID}_${dcmt.DID}`;
|
|
180
|
+
const file = pdfFilesMap.get(key);
|
|
181
|
+
if (file) {
|
|
182
|
+
pdfFiles.push(file);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
147
185
|
if (pdfFiles.length === 0) {
|
|
148
186
|
TMMessageBoxManager.show({ message: SDKUI_Localizator.NoFilesAvailableForMerge, buttons: [ButtonNames.OK] });
|
|
149
187
|
return null;
|
|
@@ -244,7 +282,7 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
|
|
|
244
282
|
width: 'max-content',
|
|
245
283
|
backgroundColor: TMColors.default_background,
|
|
246
284
|
zIndex: 1,
|
|
247
|
-
}, 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 })] }) })), _jsx("div", { style: { flex: '1.5 1 420px', minWidth: '350px', width: '100%' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.PdfFileName, value: pdfFileName, validationItems: pdfValidationItems, autoComplete: "one-time-code", onValueChanged: (e) => setPdfFileName(e.target.value) }) })] }), (hasConvertibleSelected || !hasEnoughPdfForMerge || hasNonPdfSelected) && (_jsxs("div", { style: {
|
|
285
|
+
}, 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 })] }) })), _jsx("div", { style: { flex: '1.5 1 420px', minWidth: '350px', width: '100%' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.PdfFileName, value: pdfFileName, validationItems: pdfValidationItems, autoComplete: "one-time-code", onValueChanged: (e) => setPdfFileName(e.target.value) }) })] }), (hasConvertibleSelected || hasMetadataOnlySelected || !hasEnoughPdfForMerge || hasNonPdfSelected) && (_jsxs("div", { style: {
|
|
248
286
|
display: 'flex',
|
|
249
287
|
flexDirection: 'column',
|
|
250
288
|
gap: '6px',
|
|
@@ -264,14 +302,19 @@ const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationView
|
|
|
264
302
|
borderBottom: '1px solid #e0e0e0',
|
|
265
303
|
paddingBottom: '6px',
|
|
266
304
|
marginBottom: '2px'
|
|
267
|
-
}, children: SDKUI_Localizator.NotesAndWarnings }), _jsxs("ul", { style: { margin: 0, paddingLeft: '18px', display: 'flex', flexDirection: 'column', gap: '4px' }, children: [hasConvertibleSelected && (_jsx("li", { style: { color: '#00527a' }, children: (() => {
|
|
268
|
-
|
|
305
|
+
}, children: SDKUI_Localizator.NotesAndWarnings }), _jsxs("ul", { style: { margin: 0, paddingLeft: '18px', display: 'flex', flexDirection: 'column', gap: '4px' }, children: [(hasConvertibleSelected || hasMetadataOnlySelected) && (_jsx("li", { style: { color: '#00527a' }, children: (() => {
|
|
306
|
+
// Combina convertibili + metadataOnly
|
|
307
|
+
const allConvertible = [...convertibleSelectedItems, ...metadataOnlySelectedItems];
|
|
308
|
+
const extSet = Array.from(new Set([
|
|
309
|
+
...convertibleSelectedItems.map(i => (i.ext ?? '').toString().trim().toLowerCase().replace(/^\./, '')).filter(e => e.length > 0),
|
|
310
|
+
...(hasMetadataOnlySelected ? ['metadati'] : [])
|
|
311
|
+
]));
|
|
269
312
|
const extLabel = extSet.length > 0
|
|
270
313
|
? ` (${extSet.map(e => '.' + e).join(', ')})`
|
|
271
314
|
: '';
|
|
272
|
-
return
|
|
315
|
+
return allConvertible.length === 1
|
|
273
316
|
? SDKUI_Localizator.DocumentWillBeConvertedDuringMerge.replaceParams(extLabel)
|
|
274
|
-
: SDKUI_Localizator.DocumentsWillBeConvertedDuringMerge.replaceParams(
|
|
317
|
+
: SDKUI_Localizator.DocumentsWillBeConvertedDuringMerge.replaceParams(allConvertible.length.toString(), extLabel);
|
|
275
318
|
})() })), !hasEnoughPdfForMerge && (_jsx("li", { style: { color: '#7a5d00' }, children: mergeableSelectedCount === 0
|
|
276
319
|
? SDKUI_Localizator.NoPdfOrConvertibleFilesSelected_Param.replaceParams(MIN_PDF_FOR_MERGE.toString())
|
|
277
320
|
: SDKUI_Localizator.OnlyOnePdfOrConvertibleFileSelected.replaceParams(MIN_PDF_FOR_MERGE.toString()) })), hasNonPdfSelected && (_jsx("li", { style: { color: '#7a5d00' }, children: (() => {
|
|
@@ -341,6 +341,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
341
341
|
isExpandible: canExpand, // Can this doc be expanded?
|
|
342
342
|
values: row,
|
|
343
343
|
searchResult: [searchResult],
|
|
344
|
+
fileExt: row?.FILEEXT?.value,
|
|
344
345
|
// Leave items and itemsCount undefined so TMTreeView shows expand arrow based on isExpandible
|
|
345
346
|
// Children will be loaded lazily by calculateItemsForNode when expanded
|
|
346
347
|
expanded: false,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { DcmtInfo } from '../../../ts';
|
|
2
|
+
import { IRelatedDcmt } from './TMMasterDetailDcmts';
|
|
3
|
+
/** Tipo per gli elementi con chiave e estensione */
|
|
4
|
+
export interface ISelectedItemInfo {
|
|
5
|
+
key: string;
|
|
6
|
+
ext: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
/** Risultato delle statistiche di selezione per il merge PDF */
|
|
9
|
+
export interface IMergePdfSelectionStats {
|
|
10
|
+
/** Elementi con estensioni convertibili in PDF (non nativamente PDF) */
|
|
11
|
+
convertibleSelectedItems: Array<ISelectedItemInfo>;
|
|
12
|
+
/** True se ci sono elementi convertibili selezionati */
|
|
13
|
+
hasConvertibleSelected: boolean;
|
|
14
|
+
/** Elementi che NON sono PDF e NON sono convertibili */
|
|
15
|
+
nonPdfSelectedItems: Array<ISelectedItemInfo>;
|
|
16
|
+
/** True se ci sono elementi non-PDF selezionati */
|
|
17
|
+
hasNonPdfSelected: boolean;
|
|
18
|
+
/** Documenti di soli metadati (senza file allegato) */
|
|
19
|
+
metadataOnlySelectedItems: Array<ISelectedItemInfo>;
|
|
20
|
+
/** True se ci sono documenti di soli metadati selezionati */
|
|
21
|
+
hasMetadataOnlySelected: boolean;
|
|
22
|
+
/** Numero totale di file unibili (PDF nativi + convertibili) */
|
|
23
|
+
mergeableSelectedCount: number;
|
|
24
|
+
/** True se ci sono abbastanza file per il merge (>= MIN_PDF_FOR_MERGE) */
|
|
25
|
+
hasEnoughPdfForMerge: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Documento di soli metadati: FILEEXT null/undefined oppure FILECOUNT 0 (verrà convertito frontend) */
|
|
28
|
+
export declare const isMetadataOnlyDcmt: (fileExt: string | null | undefined, fileCount: string | number | null | undefined) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Calcola tutte le statistiche di selezione necessarie per il merge PDF.
|
|
31
|
+
* Restituisce info su file convertibili, non-PDF e conteggio file unibili.
|
|
32
|
+
*
|
|
33
|
+
* @param selectedDcmtInfos - Lista dei DcmtInfo selezionati (usata se showTMRelationViewer è false)
|
|
34
|
+
* @param selectedItemsFull - Lista completa con FILEEXT e FILECOUNT per check documenti di soli metadati
|
|
35
|
+
* @param selectedItemsRelationViewer - Lista degli IRelatedDcmt selezionati nel RelationViewer
|
|
36
|
+
* @param showTMRelationViewer - Se true, usa selectedItemsRelationViewer, altrimenti selectedDcmtInfos
|
|
37
|
+
*/
|
|
38
|
+
export declare const getMergePdfSelectionStats: (selectedDcmtInfos: Array<DcmtInfo>, selectedItemsFull: Array<any>, selectedItemsRelationViewer: Array<IRelatedDcmt>, showTMRelationViewer: boolean) => IMergePdfSelectionStats;
|
|
39
|
+
export interface IMetadataKeyValue {
|
|
40
|
+
label: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}
|
|
43
|
+
export interface IMetadataPdfResult {
|
|
44
|
+
file: File;
|
|
45
|
+
blob: Blob;
|
|
46
|
+
bytes: Uint8Array;
|
|
47
|
+
}
|
|
48
|
+
/** Crea PDF con metadati documento (header + lista label=valore). Supporta wrapping e paginazione.
|
|
49
|
+
* @param dcmtInfo - Informazioni del documento
|
|
50
|
+
* @param showSystemMetadata - Se true, include i metadati di sistema (mid < 100). Default: false
|
|
51
|
+
*/
|
|
52
|
+
export declare const createMetadataPdfFromDocument: (dcmtInfo: DcmtInfo, showSystemMetadata?: boolean) => Promise<IMetadataPdfResult | null>;
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { DcmtTypeListCacheService, LayoutModes, MetadataDataTypes, SDK_Globals } from '@topconsultnpm/sdk-ts';
|
|
2
|
+
import { Globalization, isConvertibleToPdfExt, searchResultToMetadataValues } from '../../../helper';
|
|
3
|
+
import { isPdfExt, MIN_PDF_FOR_MERGE } from './copyAndMergeDcmtsShared';
|
|
4
|
+
/** Documento di soli metadati: FILEEXT null/undefined oppure FILECOUNT 0 (verrà convertito frontend) */
|
|
5
|
+
export const isMetadataOnlyDcmt = (fileExt, fileCount) => {
|
|
6
|
+
if (!fileExt)
|
|
7
|
+
return true;
|
|
8
|
+
return Number(fileCount) === 0;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Calcola tutte le statistiche di selezione necessarie per il merge PDF.
|
|
12
|
+
* Restituisce info su file convertibili, non-PDF e conteggio file unibili.
|
|
13
|
+
*
|
|
14
|
+
* @param selectedDcmtInfos - Lista dei DcmtInfo selezionati (usata se showTMRelationViewer è false)
|
|
15
|
+
* @param selectedItemsFull - Lista completa con FILEEXT e FILECOUNT per check documenti di soli metadati
|
|
16
|
+
* @param selectedItemsRelationViewer - Lista degli IRelatedDcmt selezionati nel RelationViewer
|
|
17
|
+
* @param showTMRelationViewer - Se true, usa selectedItemsRelationViewer, altrimenti selectedDcmtInfos
|
|
18
|
+
*/
|
|
19
|
+
export const getMergePdfSelectionStats = (selectedDcmtInfos, selectedItemsFull, selectedItemsRelationViewer, showTMRelationViewer) => {
|
|
20
|
+
// Mappa per lookup veloce di FILECOUNT da selectedItemsFull (usato solo per isMetadataOnly)
|
|
21
|
+
const fileCountMap = new Map(selectedItemsFull.map(d => [`${d.TID}_${d.DID}`, d.FILECOUNT]));
|
|
22
|
+
// Pre-calcolo delle informazioni sui documenti selezionati
|
|
23
|
+
const docs = showTMRelationViewer
|
|
24
|
+
? selectedItemsRelationViewer
|
|
25
|
+
.filter(i => i.isDcmt)
|
|
26
|
+
.map(i => {
|
|
27
|
+
const ext = i.fileExt ?? undefined;
|
|
28
|
+
return {
|
|
29
|
+
key: `${i.tid}_${i.did}`,
|
|
30
|
+
ext,
|
|
31
|
+
isPdf: isPdfExt(ext),
|
|
32
|
+
isConvertible: isConvertibleToPdfExt(ext),
|
|
33
|
+
isMetadataOnly: isMetadataOnlyDcmt(ext, null)
|
|
34
|
+
};
|
|
35
|
+
})
|
|
36
|
+
: selectedDcmtInfos.map(d => {
|
|
37
|
+
const ext = d.FILEEXT ?? undefined;
|
|
38
|
+
const key = `${d.TID}_${d.DID}`;
|
|
39
|
+
const fileCount = fileCountMap.get(key);
|
|
40
|
+
return {
|
|
41
|
+
key,
|
|
42
|
+
ext,
|
|
43
|
+
isPdf: isPdfExt(ext),
|
|
44
|
+
isConvertible: isConvertibleToPdfExt(ext),
|
|
45
|
+
isMetadataOnly: isMetadataOnlyDcmt(ext, fileCount)
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
// Elementi convertibili: file con estensione convertibile (esclusi documenti di soli metadati)
|
|
49
|
+
const convertibleSelectedItems = docs
|
|
50
|
+
.filter(i => i.isConvertible && !i.isMetadataOnly)
|
|
51
|
+
.map(i => ({ key: i.key, ext: i.ext }));
|
|
52
|
+
// Elementi NON PDF e NON convertibili (esclusi documenti di soli metadati)
|
|
53
|
+
const nonPdfSelectedItems = docs
|
|
54
|
+
.filter(i => !i.isPdf && !i.isConvertible && !i.isMetadataOnly)
|
|
55
|
+
.map(i => ({ key: i.key, ext: i.ext }));
|
|
56
|
+
// Documenti di soli metadati (senza file allegato)
|
|
57
|
+
const metadataOnlySelectedItems = docs
|
|
58
|
+
.filter(i => i.isMetadataOnly)
|
|
59
|
+
.map(i => ({ key: i.key, ext: i.ext }));
|
|
60
|
+
// Conteggio file unibili: PDF nativi + convertibili + documenti di soli metadati
|
|
61
|
+
const mergeableSelectedCount = docs
|
|
62
|
+
.filter(i => i.isPdf || i.isConvertible || i.isMetadataOnly).length;
|
|
63
|
+
return {
|
|
64
|
+
convertibleSelectedItems,
|
|
65
|
+
hasConvertibleSelected: convertibleSelectedItems.length > 0,
|
|
66
|
+
nonPdfSelectedItems,
|
|
67
|
+
hasNonPdfSelected: nonPdfSelectedItems.length > 0,
|
|
68
|
+
metadataOnlySelectedItems,
|
|
69
|
+
hasMetadataOnlySelected: metadataOnlySelectedItems.length > 0,
|
|
70
|
+
mergeableSelectedCount,
|
|
71
|
+
hasEnoughPdfForMerge: mergeableSelectedCount >= MIN_PDF_FOR_MERGE,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
// LAZY LOADING pdf-lib
|
|
75
|
+
let pdfLibModule = null;
|
|
76
|
+
const loadPdfLib = async () => {
|
|
77
|
+
if (!pdfLibModule) {
|
|
78
|
+
pdfLibModule = await import('pdf-lib');
|
|
79
|
+
}
|
|
80
|
+
return pdfLibModule;
|
|
81
|
+
};
|
|
82
|
+
// HELPER FUNCTIONS
|
|
83
|
+
/** Ottiene label localizzata del metadato (customName > nameLoc > name) */
|
|
84
|
+
const getMetadataLabel = (md, customName) => {
|
|
85
|
+
if (customName)
|
|
86
|
+
return customName;
|
|
87
|
+
if (!md)
|
|
88
|
+
return '';
|
|
89
|
+
return md.nameLoc || md.name || '';
|
|
90
|
+
};
|
|
91
|
+
/** Formatta valore metadato per PDF (null/undefined -> stringa vuota, datetime -> dd/MM/yyyy HH:mm) */
|
|
92
|
+
const formatMetadataValueForPdf = (value, md) => {
|
|
93
|
+
if (value === undefined || value === null)
|
|
94
|
+
return '';
|
|
95
|
+
// Se il metadato è di tipo DateTime, formatta in modo leggibile usando Globalization
|
|
96
|
+
if (md?.dataType === MetadataDataTypes.DateTime) {
|
|
97
|
+
return Globalization.getDateTimeDisplayValueCompact(value, undefined, md.format?.format);
|
|
98
|
+
}
|
|
99
|
+
return value.toString().trim();
|
|
100
|
+
};
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// CREAZIONE PDF DA METADATI DOCUMENTO
|
|
103
|
+
// ============================================================================
|
|
104
|
+
/** Crea PDF con metadati documento (header + lista label=valore). Supporta wrapping e paginazione.
|
|
105
|
+
* @param dcmtInfo - Informazioni del documento
|
|
106
|
+
* @param showSystemMetadata - Se true, include i metadati di sistema (mid < 100). Default: false
|
|
107
|
+
*/
|
|
108
|
+
export const createMetadataPdfFromDocument = async (dcmtInfo, showSystemMetadata = false) => {
|
|
109
|
+
// Configurazione ottimale per PDF A4
|
|
110
|
+
const pageWidth = 595; // A4 width in points
|
|
111
|
+
const pageHeight = 842; // A4 height in points
|
|
112
|
+
const margin = 50; // Margine confortevole
|
|
113
|
+
const titleFontSize = 14; // Titolo leggibile ma non troppo grande
|
|
114
|
+
const contentFontSize = 10; // Font contenuto ottimale per leggibilità
|
|
115
|
+
try {
|
|
116
|
+
// Recupera i metadati del documento
|
|
117
|
+
const metadata = await SDK_Globals.tmSession?.NewSearchEngine().GetMetadataAsync(dcmtInfo.TID, dcmtInfo.DID, true);
|
|
118
|
+
if (!metadata) {
|
|
119
|
+
console.warn('createMetadataPdfFromDocument: impossibile recuperare i metadati');
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const dtdResult = metadata.dtdResult;
|
|
123
|
+
const rows = dtdResult?.rows?.[0] ?? [];
|
|
124
|
+
const mids = metadata.selectMIDs;
|
|
125
|
+
// Recupera il tipo documento con metadati
|
|
126
|
+
const dtdWithMetadata = await DcmtTypeListCacheService.GetWithNotGrantedAsync(dcmtInfo.TID, dcmtInfo.DID, metadata);
|
|
127
|
+
if (!dtdWithMetadata) {
|
|
128
|
+
console.warn('createMetadataPdfFromDocument: impossibile recuperare il tipo documento');
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const mdList = dtdWithMetadata.metadata ?? [];
|
|
132
|
+
// Converte i metadati in formato leggibile
|
|
133
|
+
const metadataList = searchResultToMetadataValues(dcmtInfo.TID, dtdResult, rows, mids, mdList, LayoutModes.Update);
|
|
134
|
+
// Ottiene il nome del tipo documento (localizzato se abilitato)
|
|
135
|
+
const dcmtTypeName = dtdWithMetadata.nameLoc || dtdWithMetadata.name || 'Documento';
|
|
136
|
+
// Prepara la lista di metadati chiave-valore
|
|
137
|
+
const metadataKeyValues = metadataList
|
|
138
|
+
.filter(mvd => mvd.md && mvd.mid && mvd.mid > 0) // Filtra solo metadati validi
|
|
139
|
+
.filter(mvd => showSystemMetadata || (mvd.mid && mvd.mid >= 100)) // Filtra metadati di sistema se showSystemMetadata è false
|
|
140
|
+
.map(mvd => ({
|
|
141
|
+
label: getMetadataLabel(mvd.md, mvd.customName),
|
|
142
|
+
value: formatMetadataValueForPdf(mvd.value, mvd.md)
|
|
143
|
+
}))
|
|
144
|
+
.filter(kv => kv.label.length > 0); // Rimuovi metadati senza label
|
|
145
|
+
// Carica pdf-lib on-demand
|
|
146
|
+
const { PDFDocument, StandardFonts, rgb } = await loadPdfLib();
|
|
147
|
+
// Crea il documento PDF
|
|
148
|
+
const pdfDoc = await PDFDocument.create();
|
|
149
|
+
const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
150
|
+
const helveticaBoldFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
|
|
151
|
+
// Calcola dimensioni
|
|
152
|
+
const contentWidth = pageWidth - (margin * 2);
|
|
153
|
+
const lineHeight = contentFontSize + 5;
|
|
154
|
+
const titleLineHeight = titleFontSize + 6;
|
|
155
|
+
// Funzione per aggiungere una nuova pagina
|
|
156
|
+
const addPage = () => {
|
|
157
|
+
const page = pdfDoc.addPage([pageWidth, pageHeight]);
|
|
158
|
+
return { page, yPosition: pageHeight - margin };
|
|
159
|
+
};
|
|
160
|
+
// Funzione per calcolare la larghezza del testo
|
|
161
|
+
const getTextWidth = (text, font, size) => {
|
|
162
|
+
try {
|
|
163
|
+
return font.widthOfTextAtSize(text, size);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
// Fallback per caratteri non supportati
|
|
167
|
+
return text.length * size * 0.5;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
// Funzione per spezzare il testo in righe che entrano nella larghezza disponibile
|
|
171
|
+
const wrapText = (text, font, fontSize, maxWidth) => {
|
|
172
|
+
const lines = [];
|
|
173
|
+
const words = text.split(' ');
|
|
174
|
+
let currentLine = '';
|
|
175
|
+
for (const word of words) {
|
|
176
|
+
const testLine = currentLine ? `${currentLine} ${word}` : word;
|
|
177
|
+
const testWidth = getTextWidth(testLine, font, fontSize);
|
|
178
|
+
if (testWidth > maxWidth && currentLine) {
|
|
179
|
+
lines.push(currentLine);
|
|
180
|
+
currentLine = word;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
currentLine = testLine;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (currentLine) {
|
|
187
|
+
lines.push(currentLine);
|
|
188
|
+
}
|
|
189
|
+
// Se una singola parola è troppo lunga, spezzala in più righe (carattere per carattere)
|
|
190
|
+
const result = [];
|
|
191
|
+
for (const line of lines) {
|
|
192
|
+
if (getTextWidth(line, font, fontSize) <= maxWidth) {
|
|
193
|
+
result.push(line);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// Spezza la parola/linea troppo lunga carattere per carattere
|
|
197
|
+
let chunk = '';
|
|
198
|
+
for (const char of line) {
|
|
199
|
+
const testChunk = chunk + char;
|
|
200
|
+
if (getTextWidth(testChunk, font, fontSize) > maxWidth && chunk) {
|
|
201
|
+
result.push(chunk);
|
|
202
|
+
chunk = char;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
chunk = testChunk;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (chunk) {
|
|
209
|
+
result.push(chunk);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
};
|
|
215
|
+
// Sanitizza testo per Helvetica (solo ASCII)
|
|
216
|
+
const sanitize = (text) => text.replace(/[^\x20-\x7E]/g, '_');
|
|
217
|
+
let { page, yPosition } = addPage();
|
|
218
|
+
// Header (titolo centrato)
|
|
219
|
+
const titleText = sanitize(`${dcmtTypeName}`);
|
|
220
|
+
const titleWidth = getTextWidth(titleText, helveticaBoldFont, titleFontSize);
|
|
221
|
+
const titleX = Math.max(margin, margin + (contentWidth - titleWidth) / 2);
|
|
222
|
+
page.drawText(titleText, { x: titleX, y: yPosition, size: titleFontSize, font: helveticaBoldFont, color: rgb(0, 0, 0) });
|
|
223
|
+
yPosition -= titleLineHeight + 8;
|
|
224
|
+
// Metadati (label in grassetto, valore normale)
|
|
225
|
+
for (const kv of metadataKeyValues) {
|
|
226
|
+
const labelText = sanitize(kv.label) + ': ';
|
|
227
|
+
const labelWidth = getTextWidth(labelText, helveticaBoldFont, contentFontSize);
|
|
228
|
+
const valueMaxWidth = contentWidth - labelWidth;
|
|
229
|
+
const continuationIndent = labelWidth; // Indentazione per righe successive
|
|
230
|
+
// Wrappa il valore
|
|
231
|
+
const valueText = sanitize(kv.value);
|
|
232
|
+
const valueLines = wrapText(valueText, helveticaFont, contentFontSize, valueMaxWidth);
|
|
233
|
+
// Prima riga: label (bold) + primo pezzo di valore
|
|
234
|
+
if (yPosition < margin + lineHeight) {
|
|
235
|
+
({ page, yPosition } = addPage());
|
|
236
|
+
}
|
|
237
|
+
page.drawText(labelText, { x: margin, y: yPosition, size: contentFontSize, font: helveticaBoldFont, color: rgb(0, 0, 0) });
|
|
238
|
+
if (valueLines.length > 0) {
|
|
239
|
+
page.drawText(valueLines[0], { x: margin + labelWidth, y: yPosition, size: contentFontSize, font: helveticaFont, color: rgb(0, 0, 0) });
|
|
240
|
+
}
|
|
241
|
+
yPosition -= lineHeight;
|
|
242
|
+
// Righe successive del valore (indentate)
|
|
243
|
+
for (let i = 1; i < valueLines.length; i++) {
|
|
244
|
+
if (yPosition < margin + lineHeight) {
|
|
245
|
+
({ page, yPosition } = addPage());
|
|
246
|
+
}
|
|
247
|
+
page.drawText(valueLines[i], { x: margin + continuationIndent, y: yPosition, size: contentFontSize, font: helveticaFont, color: rgb(0, 0, 0) });
|
|
248
|
+
yPosition -= lineHeight;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Salva il PDF
|
|
252
|
+
const pdfBytes = await pdfDoc.save();
|
|
253
|
+
// Converte in Blob e File
|
|
254
|
+
const pdfBuffer = pdfBytes.buffer.slice(pdfBytes.byteOffset, pdfBytes.byteOffset + pdfBytes.byteLength);
|
|
255
|
+
const blob = new Blob([pdfBuffer], { type: 'application/pdf' });
|
|
256
|
+
const finalFileName = `${dcmtTypeName}_${dcmtInfo.DID}.pdf`;
|
|
257
|
+
const file = new File([blob], finalFileName, { type: 'application/pdf' });
|
|
258
|
+
return {
|
|
259
|
+
file,
|
|
260
|
+
blob,
|
|
261
|
+
bytes: pdfBytes
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
console.error('createMetadataPdfFromDocument: errore durante la creazione del PDF', error);
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
};
|
|
@@ -2869,22 +2869,22 @@ export class SDKUI_Localizator {
|
|
|
2869
2869
|
}
|
|
2870
2870
|
static get FileNotPdfWillBeExcluded() {
|
|
2871
2871
|
switch (this._cultureID) {
|
|
2872
|
-
case CultureIDs.De_DE: return "Ein Dokument
|
|
2873
|
-
case CultureIDs.En_US: return "One document
|
|
2874
|
-
case CultureIDs.Es_ES: return "Un documento no
|
|
2875
|
-
case CultureIDs.Fr_FR: return "Un document n'
|
|
2876
|
-
case CultureIDs.Pt_PT: return "Um documento não
|
|
2877
|
-
default: return "Un documento non
|
|
2872
|
+
case CultureIDs.De_DE: return "Ein Dokument {{0}} hat kein unterstütztes Format und wird von der Zusammenführung ausgeschlossen.";
|
|
2873
|
+
case CultureIDs.En_US: return "One document {{0}} does not have a supported format and will be excluded from the merge.";
|
|
2874
|
+
case CultureIDs.Es_ES: return "Un documento {{0}} no tiene un formato compatible y será excluido de la fusión.";
|
|
2875
|
+
case CultureIDs.Fr_FR: return "Un document {{0}} n'a pas un format pris en charge et sera exclu de la fusion.";
|
|
2876
|
+
case CultureIDs.Pt_PT: return "Um documento {{0}} não possui um formato suportado e será excluído da fusão.";
|
|
2877
|
+
default: return "Un documento {{0}} non ha un formato supportato e verrà escluso dall'unione.";
|
|
2878
2878
|
}
|
|
2879
2879
|
}
|
|
2880
2880
|
static get FilesNotPdfWillBeExcluded() {
|
|
2881
2881
|
switch (this._cultureID) {
|
|
2882
|
-
case CultureIDs.De_DE: return "{{0}} Dokumente
|
|
2883
|
-
case CultureIDs.En_US: return "{{0}} documents
|
|
2884
|
-
case CultureIDs.Es_ES: return "{{0}} documentos no
|
|
2885
|
-
case CultureIDs.Fr_FR: return "{{0}} documents
|
|
2886
|
-
case CultureIDs.Pt_PT: return "{{0}} documentos não
|
|
2887
|
-
default: return "{{0}} documenti non
|
|
2882
|
+
case CultureIDs.De_DE: return "{{0}} Dokumente {{1}} haben kein unterstütztes Format und werden von der Zusammenführung ausgeschlossen.";
|
|
2883
|
+
case CultureIDs.En_US: return "{{0}} documents {{1}} do not have a supported format and will be excluded from the merge.";
|
|
2884
|
+
case CultureIDs.Es_ES: return "{{0}} documentos {{1}} no tienen un formato compatible y serán excluidos de la fusión.";
|
|
2885
|
+
case CultureIDs.Fr_FR: return "{{0}} documents {{1}} n'ont pas un format pris en charge et seront exclus de la fusion.";
|
|
2886
|
+
case CultureIDs.Pt_PT: return "{{0}} documentos {{1}} não possuem um formato suportado e serão excluídos da fusão.";
|
|
2887
|
+
default: return "{{0}} documenti {{1}} non hanno un formato supportato e verranno esclusi dall'unione.";
|
|
2888
2888
|
}
|
|
2889
2889
|
}
|
|
2890
2890
|
static get FileUpload() {
|
|
@@ -133,7 +133,7 @@ export const useDcmtOperations = () => {
|
|
|
133
133
|
let maxFileSize = 0;
|
|
134
134
|
let signerInfoDescriptor = undefined;
|
|
135
135
|
if (inputDcmt?.FILEEXT == undefined || inputDcmt.FILEEXT == '') {
|
|
136
|
-
throw new Error('WARNING#
|
|
136
|
+
throw new Error('WARNING#' + SDKUI_Localizator.MetadataOnlyDocument);
|
|
137
137
|
}
|
|
138
138
|
let ue = SDK_Globals.tmSession?.NewUpdateEngineByID();
|
|
139
139
|
if (ue) {
|
|
@@ -1288,6 +1288,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1288
1288
|
...(SDK_Globals.tmSession?.SessionDescr?.appModuleID === AppModules.SURFER ? [createContextualTaskMenuItem()] : []),
|
|
1289
1289
|
downloadFileMenuItem(),
|
|
1290
1290
|
downloadXMLAttachmentsMenuItem(),
|
|
1291
|
+
copyCompliantMenuItem(),
|
|
1291
1292
|
...(selectedDcmtInfos.length > 0 && isPdfEditorAvailable(dtd, selectedDcmtInfos[0]?.FILEEXT) && onOpenPdfEditorRequest ? [pdfEditorMenuItem(onOpenPdfEditorRequest)] : []),
|
|
1292
1293
|
...(!isMobile ? [printMenuItem()] : [])
|
|
1293
1294
|
]
|
|
@@ -1442,7 +1443,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1442
1443
|
updateBatchUpdateForm(false);
|
|
1443
1444
|
setIsModifiedBatchUpdate(false);
|
|
1444
1445
|
await onRefreshDataRowsAsync?.();
|
|
1445
|
-
}, onStatusChanged: (isModified) => { setIsModifiedBatchUpdate(isModified); } }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: approvalVID ? selectedDcmtInfos.map(item => ({ ...item, TID: approvalVID })) : selectedDcmtInfos, isReject: 0, onClose: () => updateShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: approvalVID ? selectedDcmtInfos.map(item => ({ ...item, TID: approvalVID })) : selectedDcmtInfos, isReject: 1, onClose: () => updateShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: approvalVID ? selectedDcmtInfos.map(item => ({ ...item, TID: approvalVID })) : selectedDcmtInfos, onClose: () => updateShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { fromDTD: dtd, TID: contextConfig.approvalTID, DID: focusedItem?.DID, deviceType: deviceType, onCompleted: handleWFOperationCompleted, onClose: () => updateShowMoreInfoPopup(false), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, triggerBlogRefresh: onRefreshBlogDatagrid }), openCopyToFolderForm.open && openCopyToFolderForm.operationType === 'mergeToPdf' && _jsx(TMMergeToPdfForm, { mode: openCopyToFolderForm.mode, selectedDcmtInfos: selectedDcmtInfos, onClose: () => setOpenCopyToFolderForm({ open: false, operationType: 'copyToFolder', mode: 'onlySelected' }), showTMRelationViewer: showTMRelationViewerInCopyToFolderForm, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), openCopyToFolderForm.open && openCopyToFolderForm.operationType === 'copyToFolder' && _jsx(TMCopyToFolderForm, { mode: openCopyToFolderForm.mode, selectedDcmtInfos: selectedDcmtInfos, onClose: () => setOpenCopyToFolderForm({ open: false, operationType: 'copyToFolder', mode: 'onlySelected' }), showTMRelationViewer: showTMRelationViewerInCopyToFolderForm, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), _jsx(ConfirmFormatDialog, {}), _jsx(ConfirmAttachmentsDialog, {}), _jsx(FileSourceDialog, {}), taskFormDialogComponent, s4TViewerDialogComponent, currentCustomButton && _jsx(TMCustomButton, { button: currentCustomButton, formData: currentMetadataValues, selectedItems: selectedItemsFull, onClose: () => setCurrentCustomButton(undefined) })] }));
|
|
1446
|
+
}, onStatusChanged: (isModified) => { setIsModifiedBatchUpdate(isModified); } }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: approvalVID ? selectedDcmtInfos.map(item => ({ ...item, TID: approvalVID })) : selectedDcmtInfos, isReject: 0, onClose: () => updateShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: approvalVID ? selectedDcmtInfos.map(item => ({ ...item, TID: approvalVID })) : selectedDcmtInfos, isReject: 1, onClose: () => updateShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: approvalVID ? selectedDcmtInfos.map(item => ({ ...item, TID: approvalVID })) : selectedDcmtInfos, onClose: () => updateShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { fromDTD: dtd, TID: contextConfig.approvalTID, DID: focusedItem?.DID, deviceType: deviceType, onCompleted: handleWFOperationCompleted, onClose: () => updateShowMoreInfoPopup(false), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, triggerBlogRefresh: onRefreshBlogDatagrid }), openCopyToFolderForm.open && openCopyToFolderForm.operationType === 'mergeToPdf' && _jsx(TMMergeToPdfForm, { mode: openCopyToFolderForm.mode, selectedDcmtInfos: selectedDcmtInfos, selectedItemsFull: selectedItemsFull, onClose: () => setOpenCopyToFolderForm({ open: false, operationType: 'copyToFolder', mode: 'onlySelected' }), showTMRelationViewer: showTMRelationViewerInCopyToFolderForm, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), openCopyToFolderForm.open && openCopyToFolderForm.operationType === 'copyToFolder' && _jsx(TMCopyToFolderForm, { mode: openCopyToFolderForm.mode, selectedDcmtInfos: selectedDcmtInfos, onClose: () => setOpenCopyToFolderForm({ open: false, operationType: 'copyToFolder', mode: 'onlySelected' }), showTMRelationViewer: showTMRelationViewerInCopyToFolderForm, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), _jsx(ConfirmFormatDialog, {}), _jsx(ConfirmAttachmentsDialog, {}), _jsx(FileSourceDialog, {}), taskFormDialogComponent, s4TViewerDialogComponent, currentCustomButton && _jsx(TMCustomButton, { button: currentCustomButton, formData: currentMetadataValues, selectedItems: selectedItemsFull, onClose: () => setCurrentCustomButton(undefined) })] }));
|
|
1446
1447
|
return {
|
|
1447
1448
|
operationItems: operationItems(),
|
|
1448
1449
|
renderFloatingBar,
|