@topconsultnpm/sdkui-react 6.21.0-dev2.9 → 6.21.0-dev3.10
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/NewComponents/ContextMenu/styles.d.ts +4 -4
- package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +2 -2
- package/lib/components/base/TMAccordionNew.js +1 -0
- package/lib/components/base/TMAreaManager.js +19 -3
- package/lib/components/base/TMDataGrid.js +2 -2
- package/lib/components/base/TMFileManagerDataGridView.js +4 -4
- package/lib/components/base/TMFileManagerThumbnailItems.js +3 -3
- package/lib/components/base/TMFileManagerUtils.d.ts +7 -0
- package/lib/components/base/TMFileManagerUtils.js +14 -1
- package/lib/components/base/TMModal.d.ts +1 -0
- package/lib/components/base/TMModal.js +2 -2
- package/lib/components/base/TMPanel.d.ts +7 -4
- package/lib/components/base/TMPanel.js +58 -26
- package/lib/components/base/TMTreeView.js +24 -17
- package/lib/components/base/TMWaitPanel.d.ts +3 -1
- package/lib/components/base/TMWaitPanel.js +14 -9
- package/lib/components/choosers/TMDistinctValues.js +35 -21
- package/lib/components/choosers/TMDynDataListItemChooser.js +6 -1
- package/lib/components/choosers/TMUserChooser.d.ts +4 -0
- package/lib/components/choosers/TMUserChooser.js +7 -5
- package/lib/components/editors/TMEditorStyled.d.ts +6 -6
- package/lib/components/editors/TMFormulaEditor.d.ts +2 -0
- package/lib/components/editors/TMFormulaEditor.js +75 -21
- package/lib/components/editors/TMMetadataEditor.js +6 -2
- package/lib/components/editors/TMMetadataValues.js +2 -1
- package/lib/components/editors/TMRadioButton.js +7 -5
- package/lib/components/editors/TMTextBox.d.ts +2 -0
- package/lib/components/editors/TMTextBox.js +3 -3
- package/lib/components/features/archive/TMArchive.js +1 -1
- package/lib/components/features/blog/TMBlogCommentForm.js +5 -2
- package/lib/components/features/documents/TMCopyToFolderForm.d.ts +24 -0
- package/lib/components/features/documents/TMCopyToFolderForm.js +401 -0
- package/lib/components/features/documents/TMDcmtForm.d.ts +1 -0
- package/lib/components/features/documents/TMDcmtForm.js +126 -38
- package/lib/components/features/documents/TMDcmtIcon.js +1 -1
- package/lib/components/features/documents/TMDcmtPreview.d.ts +1 -0
- package/lib/components/features/documents/TMDcmtPreview.js +2 -2
- package/lib/components/features/documents/TMDcmtTasks.d.ts +1 -0
- package/lib/components/features/documents/TMDcmtTasks.js +2 -2
- package/lib/components/features/documents/TMDownloadRelationViewerSection.d.ts +23 -0
- package/lib/components/features/documents/TMDownloadRelationViewerSection.js +173 -0
- package/lib/components/features/documents/TMFileUploader.js +1 -1
- package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
- package/lib/components/features/documents/TMMasterDetailDcmts.js +28 -9
- package/lib/components/features/documents/TMMergeToPdfForm.d.ts +24 -0
- package/lib/components/features/documents/TMMergeToPdfForm.js +309 -0
- package/lib/components/features/documents/TMRelationViewer.d.ts +13 -0
- package/lib/components/features/documents/TMRelationViewer.js +80 -6
- package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +58 -0
- package/lib/components/features/documents/copyAndMergeDcmtsShared.js +266 -0
- package/lib/components/features/search/SignatureParamsManager.d.ts +70 -0
- package/lib/components/features/search/SignatureParamsManager.js +145 -0
- package/lib/components/features/search/TMSavedQuerySelector.d.ts +2 -2
- package/lib/components/features/search/TMSavedQuerySelector.js +3 -2
- package/lib/components/features/search/TMSearch.d.ts +4 -1
- package/lib/components/features/search/TMSearch.js +16 -10
- package/lib/components/features/search/TMSearchQueryEditor.js +14 -8
- package/lib/components/features/search/TMSearchQueryPanel.js +1 -1
- package/lib/components/features/search/TMSearchResult.d.ts +2 -0
- package/lib/components/features/search/TMSearchResult.js +118 -23
- package/lib/components/features/search/TMViewHistoryDcmt.js +1 -1
- package/lib/components/features/workflow/diagram/queryDescriptorParser.js +3 -6
- package/lib/components/forms/Login/TMLoginForm.d.ts +9 -0
- package/lib/components/forms/Login/TMLoginForm.js +61 -0
- package/lib/components/forms/TMResultDialog.d.ts +1 -1
- package/lib/components/forms/TMResultDialog.js +4 -2
- package/lib/components/grids/TMBlogAttachments.js +2 -2
- package/lib/components/grids/TMBlogsPost.js +5 -3
- package/lib/components/grids/TMBlogsPostUtils.d.ts +1 -0
- package/lib/components/grids/TMBlogsPostUtils.js +3 -1
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +1 -0
- package/lib/components/pages/TMPage.js +3 -1
- package/lib/components/query/TMQueryEditor.js +1 -1
- package/lib/components/viewers/TMTidViewer.js +1 -1
- package/lib/helper/MergePdfManager.d.ts +45 -0
- package/lib/helper/MergePdfManager.js +148 -0
- package/lib/helper/SDKUI_Globals.d.ts +15 -0
- package/lib/helper/SDKUI_Globals.js +16 -1
- package/lib/helper/SDKUI_Localizator.d.ts +108 -2
- package/lib/helper/SDKUI_Localizator.js +1080 -12
- package/lib/helper/TMPdfViewer.js +25 -24
- package/lib/helper/TMUtils.d.ts +24 -0
- package/lib/helper/TMUtils.js +72 -0
- package/lib/helper/ZipManager.d.ts +56 -0
- package/lib/helper/ZipManager.js +127 -0
- package/lib/helper/checkinCheckoutManager.d.ts +4 -3
- package/lib/helper/checkinCheckoutManager.js +29 -11
- package/lib/helper/index.d.ts +1 -0
- package/lib/helper/index.js +1 -0
- package/lib/hooks/useCheckInOutOperations.d.ts +4 -3
- package/lib/hooks/useDataUserIdItem.js +6 -4
- package/lib/hooks/useDcmtOperations.d.ts +26 -2
- package/lib/hooks/useDcmtOperations.js +123 -34
- package/lib/hooks/useDocumentOperations.d.ts +3 -0
- package/lib/hooks/useDocumentOperations.js +235 -26
- package/lib/hooks/useForm.js +5 -2
- package/lib/hooks/useRelatedDocuments.js +4 -4
- package/lib/hooks/useResizeObserver.d.ts +1 -1
- package/lib/hooks/useResizeObserver.js +16 -15
- package/lib/services/platform_services.d.ts +4 -4
- package/package.json +4 -2
|
@@ -154,11 +154,11 @@ const TMPdfViewer = (props) => {
|
|
|
154
154
|
// Pattern specifici per rilevare JavaScript effettivo nelle strutture PDF
|
|
155
155
|
const jsPatterns = [
|
|
156
156
|
// Esempio: /JavaScript [ (app.alert('Hello');) ]
|
|
157
|
-
{ name: 'JavaScript Dictionary Entry', pattern: /\/JavaScript\s
|
|
157
|
+
{ name: 'JavaScript Dictionary Entry', pattern: /\/JavaScript\s+[(\[<][\s\S]*?[)\]>]/i },
|
|
158
158
|
// Esempio: /JS 15 0 R (riferimento a un oggetto JavaScript)
|
|
159
159
|
{ name: 'JavaScript Object Reference', pattern: /\/JS\s+\d+\s+\d+\s+R/i },
|
|
160
160
|
// Esempio: /JS (app.alert('Click');) o /JS <hexstring>
|
|
161
|
-
{ name: 'Inline JavaScript Code', pattern: /\/JS\s
|
|
161
|
+
{ name: 'Inline JavaScript Code', pattern: /\/JS\s+[(<][\s\S]*?[)>]/i },
|
|
162
162
|
// Esempio: /AA << /O << /S /JavaScript /JS (app.alert('Open');) >> >>
|
|
163
163
|
{ name: 'Additional Actions (AA) with JavaScript', pattern: /\/AA\s*<<[\s\S]*?\/JS[\s\S]*?>>/is },
|
|
164
164
|
// Esempio: /OpenAction << /S /JavaScript /JS (this.print();) >>
|
|
@@ -258,11 +258,11 @@ const TMPdfViewer = (props) => {
|
|
|
258
258
|
const normalizedIndex = normalizedContext.indexOf(normalizedMatch);
|
|
259
259
|
if (normalizedIndex === -1) {
|
|
260
260
|
// Se ancora non trova, mostra tutto in grassetto rosso
|
|
261
|
-
return _jsx("strong", { style: { color: '#
|
|
261
|
+
return _jsx("strong", { style: { color: '#e65100', fontWeight: 'bold' }, children: context });
|
|
262
262
|
}
|
|
263
|
-
return (_jsxs(_Fragment, { children: [normalizedContext.substring(0, normalizedIndex), _jsx("strong", { style: { color: '#
|
|
263
|
+
return (_jsxs(_Fragment, { children: [normalizedContext.substring(0, normalizedIndex), _jsx("strong", { style: { color: '#e65100', fontWeight: 'bold', background: '#fff3e0' }, children: normalizedContext.substring(normalizedIndex, normalizedIndex + normalizedMatch.length) }), normalizedContext.substring(normalizedIndex + normalizedMatch.length)] }));
|
|
264
264
|
}
|
|
265
|
-
return (_jsxs(_Fragment, { children: [context.substring(0, matchIndex), _jsx("strong", { style: { color: '#
|
|
265
|
+
return (_jsxs(_Fragment, { children: [context.substring(0, matchIndex), _jsx("strong", { style: { color: '#e65100', fontWeight: 'bold', background: '#fff3e0' }, children: context.substring(matchIndex, matchIndex + matchText.length) }), context.substring(matchIndex + matchText.length)] }));
|
|
266
266
|
};
|
|
267
267
|
TMMessageBoxManager.show({
|
|
268
268
|
title: `${SDKUI_Localizator.Attention}: ${SDKUI_Localizator.PotentiallyUnsafeContent}`,
|
|
@@ -273,8 +273,8 @@ const TMPdfViewer = (props) => {
|
|
|
273
273
|
message: (_jsxs("div", { style: { maxHeight: '500px', overflowY: 'auto', padding: '10px', lineHeight: '1.6' }, children: [_jsxs("div", { style: {
|
|
274
274
|
marginBottom: '20px',
|
|
275
275
|
padding: '12px',
|
|
276
|
-
background: '#
|
|
277
|
-
border: '1px solid #
|
|
276
|
+
background: '#fff8e1',
|
|
277
|
+
border: '1px solid #ffe0b2',
|
|
278
278
|
borderRadius: '6px',
|
|
279
279
|
fontSize: '14px',
|
|
280
280
|
wordBreak: 'normal',
|
|
@@ -282,22 +282,22 @@ const TMPdfViewer = (props) => {
|
|
|
282
282
|
}, children: [_jsxs("strong", { children: [SDKUI_Localizator.Attention, ":"] }), " ", SDKUI_Localizator.PotentiallyUnsafeCodePatternsDetected.replaceParams(jsMatches.length.toString())] }), jsMatches.length > 0 ? (jsMatches.map((match, index) => (_jsxs("div", { style: {
|
|
283
283
|
marginBottom: '16px',
|
|
284
284
|
padding: '16px',
|
|
285
|
-
border: '1px solid #
|
|
285
|
+
border: '1px solid #ffe0b2',
|
|
286
286
|
borderRadius: '8px',
|
|
287
287
|
background: '#fff',
|
|
288
288
|
boxShadow: '0 1px 3px rgba(0,0,0,0.1)'
|
|
289
289
|
}, children: [_jsx("div", { style: {
|
|
290
290
|
marginBottom: '12px',
|
|
291
291
|
paddingBottom: '8px',
|
|
292
|
-
borderBottom: '2px solid #
|
|
292
|
+
borderBottom: '2px solid #ffb74d'
|
|
293
293
|
}, children: _jsxs("strong", { style: {
|
|
294
|
-
color: '#
|
|
294
|
+
color: '#e65100',
|
|
295
295
|
fontSize: '15px',
|
|
296
296
|
display: 'flex',
|
|
297
297
|
alignItems: 'center',
|
|
298
298
|
gap: '8px'
|
|
299
299
|
}, children: [_jsx("span", { style: {
|
|
300
|
-
background: '#
|
|
300
|
+
background: '#ff9800',
|
|
301
301
|
color: '#fff',
|
|
302
302
|
borderRadius: '50%',
|
|
303
303
|
width: '24px',
|
|
@@ -311,7 +311,7 @@ const TMPdfViewer = (props) => {
|
|
|
311
311
|
background: '#f5f5f5',
|
|
312
312
|
padding: '10px',
|
|
313
313
|
borderRadius: '4px',
|
|
314
|
-
borderLeft: '3px solid #
|
|
314
|
+
borderLeft: '3px solid #ff9800',
|
|
315
315
|
fontFamily: 'Consolas, Monaco, monospace',
|
|
316
316
|
fontSize: '12px',
|
|
317
317
|
wordBreak: 'break-all',
|
|
@@ -408,23 +408,24 @@ const TMPdfViewer = (props) => {
|
|
|
408
408
|
display: 'flex',
|
|
409
409
|
justifyContent: 'center',
|
|
410
410
|
alignItems: 'center',
|
|
411
|
-
padding: '
|
|
412
|
-
background: '#
|
|
413
|
-
borderTop: '
|
|
414
|
-
gap: '
|
|
411
|
+
padding: '8px 16px',
|
|
412
|
+
background: '#fff8e1',
|
|
413
|
+
borderTop: '1px solid #ffe0b2',
|
|
414
|
+
gap: '5px',
|
|
415
415
|
flexShrink: 0
|
|
416
|
-
}, children: [
|
|
416
|
+
}, children: [jsMatches.length > 0 && (_jsx("span", { className: "dx-icon-info", style: {
|
|
417
|
+
fontSize: '18px',
|
|
418
|
+
color: '#e65100',
|
|
419
|
+
cursor: 'pointer',
|
|
420
|
+
transition: 'color 0.2s',
|
|
421
|
+
flexShrink: 0
|
|
422
|
+
}, onClick: showMatchDetails, title: "Clicca per vedere i dettagli", onMouseEnter: (e) => e.currentTarget.style.color = '#bf360c', onMouseLeave: (e) => e.currentTarget.style.color = '#e65100' })), _jsxs("span", { style: {
|
|
417
423
|
color: '#856404',
|
|
424
|
+
fontSize: '13px',
|
|
418
425
|
whiteSpace: 'nowrap',
|
|
419
426
|
overflow: 'hidden',
|
|
420
427
|
textOverflow: 'ellipsis',
|
|
421
428
|
flex: 1
|
|
422
|
-
}, children: [_jsx("strong", { children: "Attenzione:" }), " Questo documento contiene contenuti potenzialmente non sicuri."] })
|
|
423
|
-
fontSize: '20px',
|
|
424
|
-
color: '#d32f2f',
|
|
425
|
-
cursor: 'pointer',
|
|
426
|
-
transition: 'color 0.2s',
|
|
427
|
-
marginLeft: '4px'
|
|
428
|
-
}, onClick: showMatchDetails, title: "Clicca per vedere i dettagli", onMouseEnter: (e) => e.currentTarget.style.color = '#b71c1c', onMouseLeave: (e) => e.currentTarget.style.color = '#d32f2f' }))] }))] }) }));
|
|
429
|
+
}, children: [_jsx("strong", { children: "Attenzione:" }), " Questo documento contiene contenuti potenzialmente non sicuri."] })] }))] }) }));
|
|
429
430
|
};
|
|
430
431
|
export default TMPdfViewer;
|
package/lib/helper/TMUtils.d.ts
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { FileItem } from '../components';
|
|
3
3
|
import { AppModules, DataColumnDescriptor, DcmtTypeDescriptor, PdGs, SearchResultDescriptor } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
/**
|
|
5
|
+
* Estensioni di firma/marca temporale note che possono avvolgere altre estensioni.
|
|
6
|
+
* Es: file.pdf.p7m, file.xml.p7m, file.docx.p7m, file.xml.p7m.ts
|
|
7
|
+
*/
|
|
8
|
+
export declare const SIGNATURE_EXTENSIONS: Set<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Estrae l'estensione completa da un nome file, gestendo estensioni composite
|
|
11
|
+
* a più livelli come .PDF.P7M, .XML.P7M.TS, etc.
|
|
12
|
+
*
|
|
13
|
+
* Esempi:
|
|
14
|
+
* - "documento.pdf" -> ".pdf"
|
|
15
|
+
* - "DCMT_123.PDF.P7M" -> ".PDF.P7M"
|
|
16
|
+
* - "fattura.xml.p7m" -> ".xml.p7m"
|
|
17
|
+
* - "example.XML.P7M.TS" -> ".XML.P7M.TS"
|
|
18
|
+
* - "file.tar.gz" -> ".gz" (tar.gz non è gestito come firma)
|
|
19
|
+
* - "file" -> ""
|
|
20
|
+
*/
|
|
21
|
+
export declare const getFullFileExtension: (fileName: string, depth?: number) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Estrae l'estensione base da un'estensione che può includere firme digitali.
|
|
24
|
+
* Es: pdf.p7m.tsd → pdf, pdf.p7m → pdf, pdf → pdf
|
|
25
|
+
*/
|
|
26
|
+
export declare const getBaseExtension: (ext: string) => string;
|
|
4
27
|
export declare const getFileIcon: (fileExtension: string | undefined, fileCount: number | undefined, tooltipContent?: JSX.Element | string) => import("react/jsx-runtime").JSX.Element;
|
|
5
28
|
export declare function formatBytes(bytes: number | undefined, decimalPlaces?: number): string;
|
|
6
29
|
export interface RowData {
|
|
@@ -53,4 +76,5 @@ type DcmtFormToolbarVisibility = {
|
|
|
53
76
|
tmDcmtTasks: boolean;
|
|
54
77
|
};
|
|
55
78
|
export declare const getDcmtFormToolbarVisibility: (appModuleID: AppModules) => DcmtFormToolbarVisibility;
|
|
79
|
+
export declare const isConvertibleToPdfExt: (ext: string | undefined | null) => boolean;
|
|
56
80
|
export {};
|
package/lib/helper/TMUtils.js
CHANGED
|
@@ -4,6 +4,61 @@ import { TMTooltip } from '../components';
|
|
|
4
4
|
import { IconCADossier, IconKey, IconMenuCAWorkingGroups } from './TMIcons';
|
|
5
5
|
import { AppModules, DataListCacheService, LicenseModuleStatus, MetadataDataDomains, PdGs, SDK_Globals } from '@topconsultnpm/sdk-ts';
|
|
6
6
|
import { SDKUI_Localizator } from './SDKUI_Localizator';
|
|
7
|
+
/**
|
|
8
|
+
* Estensioni di firma/marca temporale note che possono avvolgere altre estensioni.
|
|
9
|
+
* Es: file.pdf.p7m, file.xml.p7m, file.docx.p7m, file.xml.p7m.ts
|
|
10
|
+
*/
|
|
11
|
+
export const SIGNATURE_EXTENSIONS = new Set(['p7m', 'p7s', 'm7m', 'tsd', 'tsr', 'ts']);
|
|
12
|
+
/** Profondità massima di ricorsione per la ricerca di estensioni composite */
|
|
13
|
+
const MAX_EXTENSION_DEPTH = 5;
|
|
14
|
+
/**
|
|
15
|
+
* Estrae l'estensione completa da un nome file, gestendo estensioni composite
|
|
16
|
+
* a più livelli come .PDF.P7M, .XML.P7M.TS, etc.
|
|
17
|
+
*
|
|
18
|
+
* Esempi:
|
|
19
|
+
* - "documento.pdf" -> ".pdf"
|
|
20
|
+
* - "DCMT_123.PDF.P7M" -> ".PDF.P7M"
|
|
21
|
+
* - "fattura.xml.p7m" -> ".xml.p7m"
|
|
22
|
+
* - "example.XML.P7M.TS" -> ".XML.P7M.TS"
|
|
23
|
+
* - "file.tar.gz" -> ".gz" (tar.gz non è gestito come firma)
|
|
24
|
+
* - "file" -> ""
|
|
25
|
+
*/
|
|
26
|
+
export const getFullFileExtension = (fileName, depth = 0) => {
|
|
27
|
+
if (!fileName || depth > MAX_EXTENSION_DEPTH)
|
|
28
|
+
return '';
|
|
29
|
+
const lastDotIndex = fileName.lastIndexOf('.');
|
|
30
|
+
if (lastDotIndex <= 0)
|
|
31
|
+
return '';
|
|
32
|
+
const lastExtension = fileName.substring(lastDotIndex + 1).toLowerCase();
|
|
33
|
+
// Se l'ultima estensione è una firma/marca, cerca ricorsivamente le estensioni precedenti
|
|
34
|
+
if (SIGNATURE_EXTENSIONS.has(lastExtension)) {
|
|
35
|
+
const nameWithoutLastExt = fileName.substring(0, lastDotIndex);
|
|
36
|
+
const innerExtension = getFullFileExtension(nameWithoutLastExt, depth + 1);
|
|
37
|
+
if (innerExtension) {
|
|
38
|
+
// Concatena l'estensione interna con quella corrente
|
|
39
|
+
return innerExtension + fileName.substring(lastDotIndex);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Estensione singola (o estensione base dopo le firme)
|
|
43
|
+
return fileName.substring(lastDotIndex);
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Estrae l'estensione base da un'estensione che può includere firme digitali.
|
|
47
|
+
* Es: pdf.p7m.tsd → pdf, pdf.p7m → pdf, pdf → pdf
|
|
48
|
+
*/
|
|
49
|
+
export const getBaseExtension = (ext) => {
|
|
50
|
+
if (!ext)
|
|
51
|
+
return '';
|
|
52
|
+
const parts = ext.toLowerCase().split('.');
|
|
53
|
+
// Trova la prima parte che non è un'estensione di firma
|
|
54
|
+
for (const part of parts) {
|
|
55
|
+
if (!SIGNATURE_EXTENSIONS.has(part)) {
|
|
56
|
+
return part;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Se tutte sono firme, ritorna la prima
|
|
60
|
+
return parts[0] || '';
|
|
61
|
+
};
|
|
7
62
|
const StyledIconFileContainer = styled.div `
|
|
8
63
|
height: 22px;
|
|
9
64
|
width: 18px;
|
|
@@ -358,3 +413,20 @@ export const getDcmtFormToolbarVisibility = (appModuleID) => {
|
|
|
358
413
|
};
|
|
359
414
|
}
|
|
360
415
|
};
|
|
416
|
+
// ---- Helper per file convertibili in PDF ----
|
|
417
|
+
export const isConvertibleToPdfExt = (ext) => {
|
|
418
|
+
if (!ext)
|
|
419
|
+
return false;
|
|
420
|
+
// Rimuove le estensioni di firma digitale (P7M, M7M, TSR, TSD, TS) prima di normalizzare
|
|
421
|
+
const normalized = ext.toString().trim().toUpperCase()
|
|
422
|
+
.replace(/\.P7M/g, '').replace(/\.M7M/g, '').replace(/\.TSR/g, '').replace(/\.TSD/g, '').replace(/\.TS/g, '')
|
|
423
|
+
.toLowerCase().replace(/^\./, '').split('.').pop() ?? '';
|
|
424
|
+
return [
|
|
425
|
+
'doc', 'docx', 'dot', 'dotx', 'docm', 'dotm', 'odt', 'rtf', 'txt',
|
|
426
|
+
'csv', 'xls', 'xlsx',
|
|
427
|
+
'ppt', 'pptx', 'ppsx',
|
|
428
|
+
'htm', 'html', 'xml',
|
|
429
|
+
'bmp', 'jpg', 'jpeg', 'tif', 'tiff',
|
|
430
|
+
'eml', 'msg'
|
|
431
|
+
].includes(normalized);
|
|
432
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** File da aggiungere allo ZIP */
|
|
2
|
+
export interface ZipFileEntry {
|
|
3
|
+
/** Nome/percorso nello ZIP (es. "docs/file.txt") */
|
|
4
|
+
filename: string;
|
|
5
|
+
/** Contenuto: string, File, Blob, ArrayBuffer o Uint8Array */
|
|
6
|
+
data: File | Blob | string | ArrayBuffer | Uint8Array;
|
|
7
|
+
/** Commento opzionale */
|
|
8
|
+
comment?: string;
|
|
9
|
+
/** Data modifica (default: ora) */
|
|
10
|
+
lastModDate?: Date;
|
|
11
|
+
}
|
|
12
|
+
/** Opzioni creazione ZIP */
|
|
13
|
+
export interface ZipCreateOptions {
|
|
14
|
+
/** Password AES (opzionale) */
|
|
15
|
+
password?: string;
|
|
16
|
+
/** Compressione 0-9 (default: 6) */
|
|
17
|
+
compressionLevel?: number;
|
|
18
|
+
/** Cifratura: 1=128bit, 2=192bit, 3=256bit (default: 3) */
|
|
19
|
+
encryptionStrength?: 1 | 2 | 3;
|
|
20
|
+
/** Commento globale ZIP */
|
|
21
|
+
comment?: string;
|
|
22
|
+
/** Callback progresso: (indice, totale, nomeFile) */
|
|
23
|
+
onProgress?: (index: number, total: number, filename: string) => void;
|
|
24
|
+
/** Callback progresso singolo file: (bytesElaborati, bytesTotali) */
|
|
25
|
+
onEntryProgress?: (progress: number, total: number) => void;
|
|
26
|
+
/** AbortSignal per annullare */
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Utility per creare file ZIP con password opzionale (AES-256).
|
|
31
|
+
* Tutti i metodi sono statici.
|
|
32
|
+
*/
|
|
33
|
+
export declare class ZipManager {
|
|
34
|
+
/** Configura zip.js (useWebWorkers, maxWorkers) */
|
|
35
|
+
static configure(options: {
|
|
36
|
+
useWebWorkers?: boolean;
|
|
37
|
+
maxWorkers?: number;
|
|
38
|
+
}): Promise<void>;
|
|
39
|
+
/** Crea ZIP da array di file */
|
|
40
|
+
static createZip(files: ZipFileEntry[], options?: ZipCreateOptions): Promise<Blob>;
|
|
41
|
+
/** Crea ZIP da singolo file */
|
|
42
|
+
static createZipFromFile(filename: string, data: File | Blob | string | ArrayBuffer | Uint8Array, options?: ZipCreateOptions): Promise<Blob>;
|
|
43
|
+
/** Crea ZIP da oggetto { nomeFile: contenuto } */
|
|
44
|
+
static createZipFromMap(filesMap: Record<string, File | Blob | string | ArrayBuffer | Uint8Array>, options?: ZipCreateOptions): Promise<Blob>;
|
|
45
|
+
/** Crea ZIP e avvia download */
|
|
46
|
+
static createAndDownload(files: ZipFileEntry[], downloadFilename: string, options?: ZipCreateOptions): Promise<void>;
|
|
47
|
+
/** Scarica un Blob come file */
|
|
48
|
+
static downloadBlob(blob: Blob, filename: string): void;
|
|
49
|
+
/** Crea URL temporaneo per Blob (ricordarsi revokeObjectURL!) */
|
|
50
|
+
static createObjectURL(blob: Blob): string;
|
|
51
|
+
/** Rilascia URL creato con createObjectURL */
|
|
52
|
+
static revokeObjectURL(url: string): void;
|
|
53
|
+
/** Converte data nel reader appropriato per zip.js */
|
|
54
|
+
private static createReader;
|
|
55
|
+
}
|
|
56
|
+
export default ZipManager;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// LAZY LOADING
|
|
3
|
+
// ============================================================================
|
|
4
|
+
/** Flag per tracciare se la libreria è stata caricata */
|
|
5
|
+
let zipJsLoaded = false;
|
|
6
|
+
/** Carica @zip.js/zip.js on-demand */
|
|
7
|
+
const loadZipJs = async () => {
|
|
8
|
+
// if (!zipJsLoaded) {
|
|
9
|
+
// console.log('[ZipManager] 📦 Caricamento lazy di @zip.js/zip.js...');
|
|
10
|
+
// console.time('[ZipManager] Tempo caricamento');
|
|
11
|
+
// }
|
|
12
|
+
const module = await import("@zip.js/zip.js");
|
|
13
|
+
// if (!zipJsLoaded) {
|
|
14
|
+
// console.timeEnd('[ZipManager] Tempo caricamento');
|
|
15
|
+
// console.log('[ZipManager] ✅ Libreria caricata!');
|
|
16
|
+
// zipJsLoaded = true;
|
|
17
|
+
// }
|
|
18
|
+
zipJsLoaded = true;
|
|
19
|
+
return module;
|
|
20
|
+
};
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// ZIP MANAGER CLASS
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Utility per creare file ZIP con password opzionale (AES-256).
|
|
26
|
+
* Tutti i metodi sono statici.
|
|
27
|
+
*/
|
|
28
|
+
export class ZipManager {
|
|
29
|
+
/** Configura zip.js (useWebWorkers, maxWorkers) */
|
|
30
|
+
static async configure(options) {
|
|
31
|
+
const { configure } = await loadZipJs();
|
|
32
|
+
configure(options);
|
|
33
|
+
}
|
|
34
|
+
// ========================================================================
|
|
35
|
+
// CREAZIONE ZIP
|
|
36
|
+
// ========================================================================
|
|
37
|
+
/** Crea ZIP da array di file */
|
|
38
|
+
static async createZip(files, options = {}) {
|
|
39
|
+
const { password, compressionLevel = 6, encryptionStrength = 3, comment, onProgress, onEntryProgress, signal } = options;
|
|
40
|
+
// Validazione password: stringa vuota = nessuna cifratura
|
|
41
|
+
const usePassword = typeof password === "string" && password.length > 0 ? password : undefined;
|
|
42
|
+
// Lazy load della libreria
|
|
43
|
+
const { BlobWriter, ZipWriter, BlobReader, TextReader, Uint8ArrayReader } = await loadZipJs();
|
|
44
|
+
const blobWriter = new BlobWriter("application/zip");
|
|
45
|
+
const zipWriter = new ZipWriter(blobWriter, { password: usePassword, zipCrypto: true });
|
|
46
|
+
try {
|
|
47
|
+
const total = files.length;
|
|
48
|
+
for (let i = 0; i < files.length; i++) {
|
|
49
|
+
if (signal?.aborted) {
|
|
50
|
+
throw new DOMException("Operazione annullata", "AbortError");
|
|
51
|
+
}
|
|
52
|
+
const file = files[i];
|
|
53
|
+
onProgress?.(i + 1, total, file.filename);
|
|
54
|
+
const reader = this.createReader(file.data, { BlobReader, TextReader, Uint8ArrayReader });
|
|
55
|
+
await zipWriter.add(file.filename, reader, {
|
|
56
|
+
comment: file.comment,
|
|
57
|
+
lastModDate: file.lastModDate,
|
|
58
|
+
signal,
|
|
59
|
+
password: usePassword,
|
|
60
|
+
encryptionStrength,
|
|
61
|
+
onprogress: onEntryProgress ? (progress, total) => onEntryProgress(progress, total) : undefined
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const commentBytes = comment ? new TextEncoder().encode(comment) : undefined;
|
|
65
|
+
return await zipWriter.close(commentBytes);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
try {
|
|
69
|
+
await zipWriter.close();
|
|
70
|
+
}
|
|
71
|
+
catch { /* ignora */ }
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Crea ZIP da singolo file */
|
|
76
|
+
static async createZipFromFile(filename, data, options = {}) {
|
|
77
|
+
return this.createZip([{ filename, data }], options);
|
|
78
|
+
}
|
|
79
|
+
/** Crea ZIP da oggetto { nomeFile: contenuto } */
|
|
80
|
+
static async createZipFromMap(filesMap, options = {}) {
|
|
81
|
+
const files = Object.entries(filesMap).map(([filename, data]) => ({ filename, data }));
|
|
82
|
+
return this.createZip(files, options);
|
|
83
|
+
}
|
|
84
|
+
// ========================================================================
|
|
85
|
+
// DOWNLOAD
|
|
86
|
+
// ========================================================================
|
|
87
|
+
/** Crea ZIP e avvia download */
|
|
88
|
+
static async createAndDownload(files, downloadFilename, options = {}) {
|
|
89
|
+
const blob = await this.createZip(files, options);
|
|
90
|
+
this.downloadBlob(blob, downloadFilename);
|
|
91
|
+
}
|
|
92
|
+
/** Scarica un Blob come file */
|
|
93
|
+
static downloadBlob(blob, filename) {
|
|
94
|
+
const url = URL.createObjectURL(blob);
|
|
95
|
+
const link = document.createElement("a");
|
|
96
|
+
link.href = url;
|
|
97
|
+
link.download = filename;
|
|
98
|
+
link.style.display = "none";
|
|
99
|
+
document.body.appendChild(link);
|
|
100
|
+
link.click();
|
|
101
|
+
document.body.removeChild(link);
|
|
102
|
+
setTimeout(() => URL.revokeObjectURL(url), 100);
|
|
103
|
+
}
|
|
104
|
+
/** Crea URL temporaneo per Blob (ricordarsi revokeObjectURL!) */
|
|
105
|
+
static createObjectURL(blob) {
|
|
106
|
+
return URL.createObjectURL(blob);
|
|
107
|
+
}
|
|
108
|
+
/** Rilascia URL creato con createObjectURL */
|
|
109
|
+
static revokeObjectURL(url) {
|
|
110
|
+
URL.revokeObjectURL(url);
|
|
111
|
+
}
|
|
112
|
+
// ========================================================================
|
|
113
|
+
// PRIVATE
|
|
114
|
+
// ========================================================================
|
|
115
|
+
/** Converte data nel reader appropriato per zip.js */
|
|
116
|
+
static createReader(data, readers) {
|
|
117
|
+
const { BlobReader, TextReader, Uint8ArrayReader } = readers;
|
|
118
|
+
if (typeof data === "string")
|
|
119
|
+
return new TextReader(data);
|
|
120
|
+
if (data instanceof Uint8Array)
|
|
121
|
+
return new Uint8ArrayReader(data);
|
|
122
|
+
if (data instanceof ArrayBuffer)
|
|
123
|
+
return new Uint8ArrayReader(new Uint8Array(data));
|
|
124
|
+
return new BlobReader(data);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export default ZipManager;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { AccessLevels, DcmtTypeDescriptor,
|
|
3
|
-
import { DcmtInfo
|
|
2
|
+
import { AccessLevels, DcmtTypeDescriptor, UserDescriptor } from "@topconsultnpm/sdk-ts";
|
|
3
|
+
import { DcmtInfo } from "../ts/types";
|
|
4
4
|
import { FileItem } from "../components";
|
|
5
|
+
import { DownloadDcmtsAsyncParams } from "../hooks/useDcmtOperations";
|
|
5
6
|
/**
|
|
6
7
|
* Check-in/Check-out Manager
|
|
7
8
|
* Questo modulo gestisce tutte le operazioni di check-in e check-out
|
|
@@ -42,7 +43,7 @@ export type DownloadSource = {
|
|
|
42
43
|
originalFileName: string;
|
|
43
44
|
};
|
|
44
45
|
export declare const getCicoDownloadFileName: (source: DownloadSource, checkout: boolean, withTimestampAndExt: boolean) => string;
|
|
45
|
-
export declare const cicoDownloadFilesCallback: (sources: Array<DownloadSource>, checkout: boolean, downloadDcmtsAsync: (
|
|
46
|
+
export declare const cicoDownloadFilesCallback: (sources: Array<DownloadSource>, checkout: boolean, downloadDcmtsAsync: (params: DownloadDcmtsAsyncParams) => Promise<void>) => Promise<void>;
|
|
46
47
|
export declare const updateCicoCheckoutStorageItem: (item: CheckoutInfo, type: "fileItem" | "dcmtInfo", action?: "addOrUpdate" | "remove") => void;
|
|
47
48
|
export declare const validateCicoFileName: (source: DownloadSource, fileName: string, checkoutDate?: string | null) => FileNameValidation;
|
|
48
49
|
type ValidationResult = {
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { AccessLevels, CICO_MetadataNames, SDK_Globals, SystemMIDsAsNumber } from "@topconsultnpm/sdk-ts";
|
|
3
3
|
import TMTooltip from "../components/base/TMTooltip";
|
|
4
4
|
import { dcmtsFileCachePreview, Globalization, removeDcmtsFileCache, SDKUI_Globals, SDKUI_Localizator } from "./index";
|
|
5
|
+
import { getBaseExtension, getFullFileExtension } from "./TMUtils";
|
|
5
6
|
import { DownloadTypes } from "../ts/types";
|
|
6
7
|
const findCheckOutUserName = (users, checkoutUserId) => {
|
|
7
8
|
let checkOutUser = users.find(user => user.id === checkoutUserId);
|
|
@@ -74,7 +75,7 @@ export const cicoDownloadFilesCallback = async (sources, checkout, downloadDcmts
|
|
|
74
75
|
}
|
|
75
76
|
});
|
|
76
77
|
if (files.length > 0) {
|
|
77
|
-
await downloadDcmtsAsync(files, DownloadTypes.Dcmt, "download");
|
|
78
|
+
await downloadDcmtsAsync({ inputDcmts: files, downloadType: DownloadTypes.Dcmt, downloadMode: "download", skipConfirmation: true, useInputFileName: true });
|
|
78
79
|
}
|
|
79
80
|
};
|
|
80
81
|
export const updateCicoCheckoutStorageItem = (item, type, action = "addOrUpdate") => {
|
|
@@ -128,13 +129,22 @@ export const validateCicoFileName = (source, fileName, checkoutDate) => {
|
|
|
128
129
|
did = DID;
|
|
129
130
|
ext = FILEEXT;
|
|
130
131
|
}
|
|
131
|
-
// Ensure originalName has the extension
|
|
132
|
-
const
|
|
133
|
-
const name = baseName.toLowerCase().endsWith(`.${
|
|
132
|
+
// Ensure originalName has the extension (use base extension for comparison)
|
|
133
|
+
const sourceBaseExt = getBaseExtension(ext ?? '');
|
|
134
|
+
const name = baseName.toLowerCase().endsWith(`.${sourceBaseExt}`) ? baseName : `${baseName}.${sourceBaseExt}`;
|
|
134
135
|
let fileNameToValidate = fileName;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
// Estrai l'estensione completa (incluse eventuali firme digitali ricorsive es. pdf.p7m.tsd)
|
|
137
|
+
const fullExtension = getFullFileExtension(fileNameToValidate);
|
|
138
|
+
let fileExtensionCheck;
|
|
139
|
+
if (fullExtension) {
|
|
140
|
+
// Rimuovi l'estensione completa dal nome
|
|
141
|
+
fileNameToValidate = fileNameToValidate.slice(0, -fullExtension.length);
|
|
142
|
+
// L'estensione base è la prima parte (es. da ".pdf.p7m.tsd" prendi "pdf")
|
|
143
|
+
fileExtensionCheck = fullExtension.substring(1).split('.')[0];
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
fileExtensionCheck = '';
|
|
147
|
+
}
|
|
138
148
|
// Check and remove 'checkout~' prefix if present
|
|
139
149
|
const hasCheckoutPrefix = fileNameToValidate.startsWith('checkout~');
|
|
140
150
|
if (hasCheckoutPrefix) {
|
|
@@ -159,7 +169,7 @@ export const validateCicoFileName = (source, fileName, checkoutDate) => {
|
|
|
159
169
|
const isValidDid = didCheck ? did.toString() === parseInt(didCheck, 10).toString() : false;
|
|
160
170
|
const isValidTid = tidCheck ? tid.toString() === parseInt(tidCheck, 10).toString() : false;
|
|
161
171
|
const isValidArchive = archiveCheck ? archiveCheck === archiveID : false;
|
|
162
|
-
const isValidExt =
|
|
172
|
+
const isValidExt = sourceBaseExt ? sourceBaseExt === fileExtensionCheck.toLowerCase() : false;
|
|
163
173
|
// First phase validation result
|
|
164
174
|
const isFirstPhaseValid = !!(isValidName && isValidArchive && isValidDid && isValidTid && isValidExt);
|
|
165
175
|
// Second phase: validate checkoutDate timestamp (only if first phase passed and checkoutDate is a valid string)
|
|
@@ -177,11 +187,11 @@ export const validateCicoFileName = (source, fileName, checkoutDate) => {
|
|
|
177
187
|
else {
|
|
178
188
|
const pad = (n) => n.toString().padStart(2, '0');
|
|
179
189
|
const expectedTimestamp = `${dt.getFullYear()}${pad(dt.getMonth() + 1)}${pad(dt.getDate())}${pad(dt.getHours())}${pad(dt.getMinutes())}${pad(dt.getSeconds())}`;
|
|
180
|
-
isSecondPhaseValid = timestampCheck === expectedTimestamp;
|
|
181
190
|
// Format dates for display: readable date + (raw timestamp)
|
|
182
191
|
const expectedDisplayDate = Globalization.getDateTimeDisplayValue(dt);
|
|
183
192
|
// Parse timestampCheck to readable format (YYYYMMDDHHmmss -> Date)
|
|
184
193
|
let currentDisplayDate = timestampCheck;
|
|
194
|
+
let parsedDate = null;
|
|
185
195
|
if (timestampCheck && timestampCheck.length === 14) {
|
|
186
196
|
const year = parseInt(timestampCheck.substring(0, 4), 10);
|
|
187
197
|
const month = parseInt(timestampCheck.substring(4, 6), 10) - 1;
|
|
@@ -189,9 +199,17 @@ export const validateCicoFileName = (source, fileName, checkoutDate) => {
|
|
|
189
199
|
const hours = parseInt(timestampCheck.substring(8, 10), 10);
|
|
190
200
|
const minutes = parseInt(timestampCheck.substring(10, 12), 10);
|
|
191
201
|
const seconds = parseInt(timestampCheck.substring(12, 14), 10);
|
|
192
|
-
|
|
202
|
+
parsedDate = new Date(year, month, day, hours, minutes, seconds);
|
|
193
203
|
currentDisplayDate = Globalization.getDateTimeDisplayValue(parsedDate);
|
|
194
204
|
}
|
|
205
|
+
// Validate with ±10 seconds tolerance
|
|
206
|
+
if (parsedDate && !isNaN(parsedDate.getTime())) {
|
|
207
|
+
const diffInSeconds = Math.abs((dt.getTime() - parsedDate.getTime()) / 1000);
|
|
208
|
+
isSecondPhaseValid = diffInSeconds <= 10;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
isSecondPhaseValid = timestampCheck === expectedTimestamp;
|
|
212
|
+
}
|
|
195
213
|
checkoutDateValidation = {
|
|
196
214
|
expected: `${expectedDisplayDate} (${expectedTimestamp})`,
|
|
197
215
|
current: `${currentDisplayDate} (${timestampCheck})`,
|
|
@@ -229,7 +247,7 @@ export const validateCicoFileName = (source, fileName, checkoutDate) => {
|
|
|
229
247
|
isValid: isValidTid
|
|
230
248
|
},
|
|
231
249
|
fileExtension: {
|
|
232
|
-
expected:
|
|
250
|
+
expected: sourceBaseExt,
|
|
233
251
|
current: fileExtensionCheck.toLowerCase(),
|
|
234
252
|
isValid: isValidExt
|
|
235
253
|
},
|
package/lib/helper/index.d.ts
CHANGED
package/lib/helper/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { DcmtInfo
|
|
2
|
-
import {
|
|
1
|
+
import { DcmtInfo } from '../ts';
|
|
2
|
+
import { SearchResultDescriptor } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { DownloadDcmtsAsyncParams } from './useDcmtOperations';
|
|
3
4
|
export interface UseCheckInOutOperationsProps {
|
|
4
5
|
onRefreshPreview: () => Promise<void>;
|
|
5
6
|
}
|
|
@@ -17,7 +18,7 @@ export interface UseCheckInOutOperationsReturn {
|
|
|
17
18
|
};
|
|
18
19
|
hideCommentFormCallback: () => void;
|
|
19
20
|
copyCheckoutPathToClipboardCallback: (dcmt: DcmtInfo, filename: string) => void;
|
|
20
|
-
handleCheckOutCallback: (dcmt: DcmtInfo, checkout: boolean, filename: string, downloadDcmtsAsync: (
|
|
21
|
+
handleCheckOutCallback: (dcmt: DcmtInfo, checkout: boolean, filename: string, downloadDcmtsAsync: (params: DownloadDcmtsAsyncParams) => Promise<void>, onRefreshAsync?: (tid: number | undefined, did: number | undefined, refreshUI?: boolean, metadataResult?: SearchResultDescriptor | null) => Promise<void>) => Promise<void>;
|
|
21
22
|
handleCheckInCallback: (dcmt: DcmtInfo, checkoutDate?: string | null, onRefreshAsync?: (tid: number | undefined, did: number | undefined, refreshUI?: boolean, metadataResult?: SearchResultDescriptor | null) => Promise<void>) => Promise<void>;
|
|
22
23
|
showCicoWaitPanel: boolean;
|
|
23
24
|
cicoWaitPanelTitle: string;
|
|
@@ -15,7 +15,7 @@ export const useDataUserIdItem = () => {
|
|
|
15
15
|
if (userIDs.size === 0)
|
|
16
16
|
return;
|
|
17
17
|
try {
|
|
18
|
-
const results = await Promise.all(Array.from(userIDs).map(id => UserListCacheService.GetAsync(id).then(user => ({ id, user }))
|
|
18
|
+
const results = await Promise.all(Array.from(userIDs).filter(id => id > 0).map(id => UserListCacheService.GetAsync(id).then(user => ({ id, user }))
|
|
19
19
|
.catch(() => ({ id, user: undefined }))));
|
|
20
20
|
const newCache = new Map();
|
|
21
21
|
results.forEach(({ id, user }) => {
|
|
@@ -70,17 +70,19 @@ export const useDataUserIdItem = () => {
|
|
|
70
70
|
* @returns Elemento React per visualizzare l'utente
|
|
71
71
|
*/
|
|
72
72
|
const renderUserIdViewer = useCallback((userId, showIcon = false, showTitile = true) => {
|
|
73
|
-
const ud = userId && userId > 0 ? getUserItem(userId) : undefined;
|
|
73
|
+
const ud = userId !== undefined && userId > 0 ? getUserItem(userId) : undefined;
|
|
74
74
|
const getIcon = () => {
|
|
75
75
|
if (!showIcon)
|
|
76
76
|
return null;
|
|
77
|
-
if (
|
|
77
|
+
if (userId === undefined)
|
|
78
78
|
return null;
|
|
79
79
|
return ud ? _jsx(TMUserIcon, { ud: ud }) : _jsx("span", { title: showTitile ? SDKUI_Localizator.ValueNotPresent : undefined, style: { display: 'inline-flex', alignItems: 'center' }, children: _jsx(IconWarning, { color: TMColors.warning }) });
|
|
80
80
|
};
|
|
81
81
|
const getDescription = () => {
|
|
82
|
-
if (
|
|
82
|
+
if (userId == null)
|
|
83
83
|
return undefined;
|
|
84
|
+
if (userId === 0)
|
|
85
|
+
return SDKUI_Localizator.SystemUser;
|
|
84
86
|
return ud ? getCompleteUserName(ud.domain, ud.name) : userId.toString() ?? SDKUI_Localizator.NoneSelection;
|
|
85
87
|
};
|
|
86
88
|
return (_jsxs("span", { style: { display: 'inline-flex', alignItems: 'center', gap: '4px', lineHeight: 1 }, children: [getIcon(), _jsx("span", { style: { lineHeight: 'normal' }, children: getDescription() })] }));
|
|
@@ -1,5 +1,29 @@
|
|
|
1
|
-
import { RetrieveFileOptions, FileDescriptor } from '@topconsultnpm/sdk-ts';
|
|
1
|
+
import { RetrieveFileOptions, DcmtOpers, FileDescriptor, GeneralRetrieveFormats, InvoiceRetrieveFormats, OrderRetrieveFormats, FileFormats } from '@topconsultnpm/sdk-ts';
|
|
2
2
|
import { DcmtInfo, DcmtOperationTypes, DownloadModes, DownloadTypes } from '../ts';
|
|
3
|
+
export interface RetrieveFormatOptions {
|
|
4
|
+
retrieveReason?: DcmtOpers;
|
|
5
|
+
cvtFormat?: FileFormats;
|
|
6
|
+
generalRetrieveFormat?: GeneralRetrieveFormats;
|
|
7
|
+
invoiceRetrieveFormat?: InvoiceRetrieveFormats;
|
|
8
|
+
orderRetrieveFormat?: OrderRetrieveFormats;
|
|
9
|
+
}
|
|
10
|
+
export interface DownloadDcmtsAsyncParams {
|
|
11
|
+
inputDcmts: DcmtInfo[] | undefined;
|
|
12
|
+
downloadType?: DownloadTypes;
|
|
13
|
+
downloadMode?: DownloadModes;
|
|
14
|
+
onFileDownloaded?: (dcmtFile: File, dcmtInfo: DcmtInfo) => void | Promise<void>;
|
|
15
|
+
confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>;
|
|
16
|
+
skipConfirmation?: boolean;
|
|
17
|
+
retrieveOptions?: RetrieveFormatOptions;
|
|
18
|
+
useCache?: boolean;
|
|
19
|
+
showSuccessAlert?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Controlla la priorità del nome file per il download:
|
|
22
|
+
* - true: usa il fileName da inputDcmts (dcmtInfo.fileName) come priorità
|
|
23
|
+
* - false (default): usa il nome file recuperato dal backend (file.name) come priorità
|
|
24
|
+
*/
|
|
25
|
+
useInputFileName?: boolean;
|
|
26
|
+
}
|
|
3
27
|
export interface UseDcmtOperationsReturn {
|
|
4
28
|
abortController: AbortController;
|
|
5
29
|
showWaitPanel: boolean;
|
|
@@ -12,7 +36,7 @@ export interface UseDcmtOperationsReturn {
|
|
|
12
36
|
waitPanelTextSecondary: string;
|
|
13
37
|
waitPanelValueSecondary: number;
|
|
14
38
|
waitPanelMaxValueSecondary: number;
|
|
15
|
-
downloadDcmtsAsync: (
|
|
39
|
+
downloadDcmtsAsync: (params: DownloadDcmtsAsyncParams) => Promise<void>;
|
|
16
40
|
getDcmtFileAsync: (inputDcmt: DcmtInfo | undefined, rfo: RetrieveFileOptions, operationTitle: string, keepWaitPanelPrimary: boolean, bypassCache?: boolean) => Promise<{
|
|
17
41
|
file: File | undefined;
|
|
18
42
|
isFromCache: boolean;
|