@topconsultnpm/sdkui-react 6.21.0-dev2.53 → 6.21.0-dev2.54

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.
@@ -18,16 +18,17 @@ export declare const isDirectoryPickerSupported: () => boolean;
18
18
  export declare const isPdfExt: (ext: string | null | undefined) => boolean;
19
19
  /**
20
20
  * Estrae l'estensione completa da un nome file, gestendo estensioni composite
21
- * come .PDF.P7M, .DOCX.p7m, .xml.p7m, etc.
21
+ * a più livelli come .PDF.P7M, .XML.P7M.TS, etc.
22
22
  *
23
23
  * Esempi:
24
24
  * - "documento.pdf" -> ".pdf"
25
25
  * - "DCMT_123.PDF.P7M" -> ".PDF.P7M"
26
26
  * - "fattura.xml.p7m" -> ".xml.p7m"
27
+ * - "example.XML.P7M.TS" -> ".XML.P7M.TS"
27
28
  * - "file.tar.gz" -> ".gz" (tar.gz non è gestito come firma)
28
29
  * - "file" -> ""
29
30
  */
30
- export declare const getFullFileExtension: (fileName: string) => string;
31
+ export declare const getFullFileExtension: (fileName: string, depth?: number) => string;
31
32
  /**
32
33
  * Estrae il nome base del file (senza estensione completa).
33
34
  * Gestisce estensioni composite come .PDF.P7M
@@ -60,37 +60,40 @@ export const isPdfExt = (ext) => {
60
60
  };
61
61
  /**
62
62
  * Estensioni di firma/marca temporale note che possono avvolgere altre estensioni.
63
- * Es: file.pdf.p7m, file.xml.p7m, file.docx.p7m
63
+ * Es: file.pdf.p7m, file.xml.p7m, file.docx.p7m, file.xml.p7m.ts
64
64
  */
65
- const SIGNATURE_EXTENSIONS = new Set(['p7m', 'p7s', 'm7m', 'tsd', 'tsr']);
65
+ const SIGNATURE_EXTENSIONS = new Set(['p7m', 'p7s', 'm7m', 'tsd', 'tsr', 'ts']);
66
+ /** Profondità massima di ricorsione per la ricerca di estensioni composite */
67
+ const MAX_EXTENSION_DEPTH = 5;
66
68
  /**
67
69
  * Estrae l'estensione completa da un nome file, gestendo estensioni composite
68
- * come .PDF.P7M, .DOCX.p7m, .xml.p7m, etc.
70
+ * a più livelli come .PDF.P7M, .XML.P7M.TS, etc.
69
71
  *
70
72
  * Esempi:
71
73
  * - "documento.pdf" -> ".pdf"
72
74
  * - "DCMT_123.PDF.P7M" -> ".PDF.P7M"
73
75
  * - "fattura.xml.p7m" -> ".xml.p7m"
76
+ * - "example.XML.P7M.TS" -> ".XML.P7M.TS"
74
77
  * - "file.tar.gz" -> ".gz" (tar.gz non è gestito come firma)
75
78
  * - "file" -> ""
76
79
  */
77
- export const getFullFileExtension = (fileName) => {
78
- if (!fileName)
80
+ export const getFullFileExtension = (fileName, depth = 0) => {
81
+ if (!fileName || depth > MAX_EXTENSION_DEPTH)
79
82
  return '';
80
83
  const lastDotIndex = fileName.lastIndexOf('.');
81
84
  if (lastDotIndex <= 0)
82
85
  return '';
83
86
  const lastExtension = fileName.substring(lastDotIndex + 1).toLowerCase();
84
- // Se l'ultima estensione è una firma/marca, cerca anche l'estensione precedente
87
+ // Se l'ultima estensione è una firma/marca, cerca ricorsivamente le estensioni precedenti
85
88
  if (SIGNATURE_EXTENSIONS.has(lastExtension)) {
86
- const nameWithoutSignature = fileName.substring(0, lastDotIndex);
87
- const secondLastDotIndex = nameWithoutSignature.lastIndexOf('.');
88
- if (secondLastDotIndex > 0) {
89
- // Restituisce entrambe le estensioni: .PDF.P7M
90
- return fileName.substring(secondLastDotIndex);
89
+ const nameWithoutLastExt = fileName.substring(0, lastDotIndex);
90
+ const innerExtension = getFullFileExtension(nameWithoutLastExt, depth + 1);
91
+ if (innerExtension) {
92
+ // Concatena l'estensione interna con quella corrente
93
+ return innerExtension + fileName.substring(lastDotIndex);
91
94
  }
92
95
  }
93
- // Estensione singola
96
+ // Estensione singola (o estensione base dopo le firme)
94
97
  return fileName.substring(lastDotIndex);
95
98
  };
96
99
  /**
@@ -16,5 +16,5 @@ interface ITMResultDialogProps {
16
16
  declare const TMResultDialog: React.FC<ITMResultDialogProps>;
17
17
  export default TMResultDialog;
18
18
  export declare class TMResultManager {
19
- static show(result: ResultInfo[], title: string, id1Caption: string | undefined, id2Caption: string | undefined, customMsg?: string, customDuration?: number): void;
19
+ static show(result: ResultInfo[], title: string, id1Caption: string | undefined, id2Caption: string | undefined, customMsg?: string, customDuration?: number, showSuccessAlert?: boolean): void;
20
20
  }
@@ -29,11 +29,13 @@ const TMResultDialog = ({ title, result, id1Caption, id2Caption }) => {
29
29
  };
30
30
  export default TMResultDialog;
31
31
  export class TMResultManager {
32
- static show(result, title, id1Caption, id2Caption, customMsg, customDuration) {
32
+ static show(result, title, id1Caption, id2Caption, customMsg, customDuration, showSuccessAlert = true) {
33
33
  const warningsCount = result.filter(o => o.resultType == ResultTypes.WARNING).length;
34
34
  const errorsCount = result.filter(o => o.resultType == ResultTypes.ERROR).length;
35
35
  if (warningsCount <= 0 && errorsCount <= 0) {
36
- ShowAlert({ message: customMsg && customMsg.length > 0 ? customMsg : SDKUI_Localizator.OperationSuccess, mode: 'success', duration: customDuration && customDuration > 0 ? customDuration : 3000, title: title });
36
+ if (showSuccessAlert) {
37
+ ShowAlert({ message: customMsg && customMsg.length > 0 ? customMsg : SDKUI_Localizator.OperationSuccess, mode: 'success', duration: customDuration && customDuration > 0 ? customDuration : 3000, title: title });
38
+ }
37
39
  return;
38
40
  }
39
41
  let container = document.createElement('div');
@@ -19,7 +19,7 @@ export interface UseDcmtOperationsReturn {
19
19
  waitPanelTextSecondary: string;
20
20
  waitPanelValueSecondary: number;
21
21
  waitPanelMaxValueSecondary: number;
22
- downloadDcmtsAsync: (inputDcmts: DcmtInfo[] | undefined, downloadType?: DownloadTypes, downloadMode?: DownloadModes, onFileDownloaded?: (dcmtFile: File, dcmtInfo: DcmtInfo) => void | Promise<void>, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>, skipConfirmation?: boolean, retrieveOptions?: RetrieveFormatOptions, useCache?: boolean) => Promise<void>;
22
+ downloadDcmtsAsync: (inputDcmts: DcmtInfo[] | undefined, downloadType?: DownloadTypes, downloadMode?: DownloadModes, onFileDownloaded?: (dcmtFile: File, dcmtInfo: DcmtInfo) => void | Promise<void>, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>, skipConfirmation?: boolean, retrieveOptions?: RetrieveFormatOptions, useCache?: boolean, showSuccessAlert?: boolean) => Promise<void>;
23
23
  getDcmtFileAsync: (inputDcmt: DcmtInfo | undefined, rfo: RetrieveFileOptions, operationTitle: string, keepWaitPanelPrimary: boolean, bypassCache?: boolean) => Promise<{
24
24
  file: File | undefined;
25
25
  isFromCache: boolean;
@@ -75,7 +75,7 @@ export const useDcmtOperations = () => {
75
75
  const [waitPanelMaxValueSecondary, setWaitPanelMaxValueSecondary] = useState(0);
76
76
  const { OpenFileDialog } = useFileDialog();
77
77
  const [selectFileSource, FileSourceDialog] = useFileSourceDialog();
78
- const _downloadDcmtsAsync = async (inputDcmts, downloadMode = "download", onFileDownloaded, skipConfirmation = false, retrieveOptions, useCache = true) => {
78
+ const _downloadDcmtsAsync = async (inputDcmts, downloadMode = "download", onFileDownloaded, skipConfirmation = false, retrieveOptions, useCache = true, showSuccessAlert = true) => {
79
79
  if (inputDcmts === undefined)
80
80
  return;
81
81
  if (inputDcmts.length <= 0)
@@ -189,9 +189,9 @@ export const useDcmtOperations = () => {
189
189
  setWaitPanelMaxValueSecondary(0);
190
190
  setWaitPanelValueSecondary(0);
191
191
  setShowWaitPanel(false);
192
- TMResultManager.show(result, operationTitle, "TID", "DID");
192
+ TMResultManager.show(result, operationTitle, "TID", "DID", undefined, undefined, showSuccessAlert);
193
193
  };
194
- const _downloadAttachmentsAsync = async (inputDcmts, confirmAttachments) => {
194
+ const _downloadAttachmentsAsync = async (inputDcmts, confirmAttachments, showSuccessAlert = true) => {
195
195
  if (inputDcmts === undefined)
196
196
  return;
197
197
  if (inputDcmts.length !== 1)
@@ -239,7 +239,7 @@ export const useDcmtOperations = () => {
239
239
  }
240
240
  }
241
241
  }
242
- TMResultManager.show(result, operationTitle, "TID", "DID");
242
+ TMResultManager.show(result, operationTitle, "TID", "DID", undefined, undefined, showSuccessAlert);
243
243
  }
244
244
  catch (ex) {
245
245
  TMSpinner.hide();
@@ -251,11 +251,11 @@ export const useDcmtOperations = () => {
251
251
  TMExceptionBoxManager.show({ exception: err });
252
252
  }
253
253
  };
254
- const downloadDcmtsAsync = async (inputDcmts, downloadType = DownloadTypes.Attachment, downloadMode = "download", onFileDownloaded, confirmAttachments, skipConfirmation = false, retrieveOptions, useCache = true) => {
254
+ const downloadDcmtsAsync = async (inputDcmts, downloadType = DownloadTypes.Attachment, downloadMode = "download", onFileDownloaded, confirmAttachments, skipConfirmation = false, retrieveOptions, useCache = true, showSuccessAlert = true) => {
255
255
  switch (downloadType) {
256
- case DownloadTypes.Dcmt: return await _downloadDcmtsAsync(inputDcmts, downloadMode, onFileDownloaded, skipConfirmation, retrieveOptions, useCache);
257
- case DownloadTypes.Attachment: return await _downloadAttachmentsAsync(inputDcmts, confirmAttachments);
258
- default: return await _downloadDcmtsAsync(inputDcmts, undefined, undefined, skipConfirmation, retrieveOptions, useCache);
256
+ case DownloadTypes.Dcmt: return await _downloadDcmtsAsync(inputDcmts, downloadMode, onFileDownloaded, skipConfirmation, retrieveOptions, useCache, showSuccessAlert);
257
+ case DownloadTypes.Attachment: return await _downloadAttachmentsAsync(inputDcmts, confirmAttachments, showSuccessAlert);
258
+ default: return await _downloadDcmtsAsync(inputDcmts, undefined, undefined, skipConfirmation, retrieveOptions, useCache, showSuccessAlert);
259
259
  }
260
260
  };
261
261
  const uploadDcmtsAsync = async (inputDcmts, operationTitle, operType, actionAfterOperationAsync) => {
@@ -23,7 +23,6 @@ import { useInputAttachmentsDialog, useInputCvtFormatDialog } from "./useInputDi
23
23
  import { useRelatedDocuments } from "./useRelatedDocuments";
24
24
  import { convertSearchResultDescriptorToFileItems, dcmtsFileCachePreview, getDcmtCicoStatus, getMoreInfoTasksForDocument, IconActivity, IconArchiveDetail, IconArchiveDoc, IconArchiveMaster, IconBatchUpdate, IconCheck, IconCheckFile, IconCheckIn, IconCircleInfo, IconCloseCircle, IconConvertFilePdf, IconCopy, IconCustom, IconDelete, IconDetailDcmts, IconDotsVerticalCircleOutline, IconDownload, IconEdit, IconExportTo, IconFileDots, IconHide, IconInfo, IconMenuCAArchive, IconMoveToFolder, IconPair, IconPin, IconPlatform, IconPreview, IconRelation, IconSearch, IconShare, IconSharedDcmt, IconShow, IconSignaturePencil, IconStar, IconSubstFile, IconUndo, IconUnpair, IconUserGroupOutline, isPdfEditorAvailable, SDKUI_Localizator, searchResultToMetadataValues, TMImageLibrary } from '../helper';
25
25
  import { isXMLFileExt } from "../helper/dcmtsHelper";
26
- import { isPdfExt } from "../components/features/documents/copyAndMergeDcmtsShared";
27
26
  import TMCopyToFolderForm from "../components/features/documents/TMCopyToFolderForm";
28
27
  import TMMergeToPdfForm from "../components/features/documents/TMMergeToPdfForm";
29
28
  export const getSelectedDcmtsOrFocused = (selectedItems, focusedItem, fileFormat) => {
@@ -569,7 +568,10 @@ export const useDocumentOperations = (props) => {
569
568
  };
570
569
  };
571
570
  const printMenuItem = () => {
572
- const isPdf = isPdfExt(selectedDcmtInfos?.[0]?.FILEEXT);
571
+ // Take the first document (used for validation checks)
572
+ const firstDoc = selectedDcmtInfos?.[0];
573
+ // Check if the selected document is a PDF
574
+ const isPdf = firstDoc?.FILEEXT?.toLowerCase() === "pdf";
573
575
  return {
574
576
  id: 'print',
575
577
  icon: _jsx("i", { className: "dx-icon-print", style: { fontSize: '20px' } }),
@@ -579,27 +581,36 @@ export const useDocumentOperations = (props) => {
579
581
  onClick: isPdf ? async () => {
580
582
  const handlePrint = async (file, _dcmtInfo) => {
581
583
  const fileURL = window.URL.createObjectURL(file);
582
- // Usa un iframe nascosto per stampare senza aprire un nuovo tab
583
- const iframe = document.createElement('iframe');
584
- iframe.style.position = 'fixed';
585
- iframe.style.right = '0';
586
- iframe.style.bottom = '0';
587
- iframe.style.width = '0';
588
- iframe.style.height = '0';
589
- iframe.style.border = 'none';
590
- iframe.src = fileURL;
591
- document.body.appendChild(iframe);
592
- iframe.onload = () => {
593
- iframe.contentWindow?.focus();
594
- iframe.contentWindow?.print();
595
- // Rimuovi l'iframe dopo un breve delay per permettere la stampa
584
+ // Usa un iframe nascosto con sandbox per:
585
+ // 1. Bloccare l'esecuzione di JavaScript nel PDF
586
+ // 2. Non aprire un nuovo tab
587
+ const printFrame = document.createElement('iframe');
588
+ printFrame.style.position = 'fixed';
589
+ printFrame.style.right = '0';
590
+ printFrame.style.bottom = '0';
591
+ printFrame.style.width = '0';
592
+ printFrame.style.height = '0';
593
+ printFrame.style.border = 'none';
594
+ // sandbox senza 'allow-scripts' blocca l'esecuzione di JS
595
+ /* printFrame.sandbox.add('allow-same-origin'); */
596
+ printFrame.src = fileURL;
597
+ document.body.appendChild(printFrame);
598
+ printFrame.onload = () => {
599
+ try {
600
+ printFrame.contentWindow?.focus();
601
+ printFrame.contentWindow?.print();
602
+ }
603
+ catch (e) {
604
+ console.error('Errore durante la stampa:', e);
605
+ }
606
+ // Cleanup dopo un delay per permettere la stampa
596
607
  setTimeout(() => {
597
- document.body.removeChild(iframe);
608
+ document.body.removeChild(printFrame);
598
609
  window.URL.revokeObjectURL(fileURL);
599
- }, 1000);
610
+ }, 60000);
600
611
  };
601
612
  };
602
- await downloadDcmtsAsync(selectedDcmtInfos, DownloadTypes.Dcmt, "download", handlePrint, undefined, true);
613
+ await downloadDcmtsAsync(selectedDcmtInfos, DownloadTypes.Dcmt, "download", handlePrint, undefined, true, undefined, true, false);
603
614
  } : undefined,
604
615
  };
605
616
  };
@@ -1118,7 +1129,7 @@ export const useDocumentOperations = (props) => {
1118
1129
  batchUpdateMenuItem(),
1119
1130
  passToArchive(),
1120
1131
  ...(selectedDcmtInfos.length > 0 && isPdfEditorAvailable(dtd, selectedDcmtInfos[0]?.FILEEXT) && onOpenPdfEditorRequest ? [pdfEditorMenuItem(onOpenPdfEditorRequest)] : []),
1121
- printMenuItem()
1132
+ ...(!isMobile ? [printMenuItem()] : [])
1122
1133
  ]
1123
1134
  },
1124
1135
  signatureMenuItem(),
@@ -1162,7 +1173,7 @@ export const useDocumentOperations = (props) => {
1162
1173
  commentFromWgMenuItem(false),
1163
1174
  relationsMenuItem(true),
1164
1175
  removeFromWgMenuItem(SDKUI_Localizator.RemoveFromWorkgroup),
1165
- printMenuItem()
1176
+ ...(!isMobile ? [printMenuItem()] : [])
1166
1177
  ].sort((a, b) => a.name.localeCompare(b.name));
1167
1178
  return [
1168
1179
  ...sortedItems,
@@ -1186,7 +1197,7 @@ export const useDocumentOperations = (props) => {
1186
1197
  downloadFileMenuItem(),
1187
1198
  downloadXMLAttachmentsMenuItem(),
1188
1199
  ...(selectedDcmtInfos.length > 0 && isPdfEditorAvailable(dtd, selectedDcmtInfos[0]?.FILEEXT) && onOpenPdfEditorRequest ? [pdfEditorMenuItem(onOpenPdfEditorRequest)] : []),
1189
- printMenuItem()
1200
+ ...(!isMobile ? [printMenuItem()] : [])
1190
1201
  ]
1191
1202
  },
1192
1203
  signatureMenuItem(),
@@ -1213,7 +1224,7 @@ export const useDocumentOperations = (props) => {
1213
1224
  downloadFileMenuItem(),
1214
1225
  downloadXMLAttachmentsMenuItem(),
1215
1226
  ...(selectedDcmtInfos.length > 0 && isPdfEditorAvailable(dtd, selectedDcmtInfos[0]?.FILEEXT) && onOpenPdfEditorRequest ? [pdfEditorMenuItem(onOpenPdfEditorRequest)] : []),
1216
- printMenuItem()
1227
+ ...(!isMobile ? [printMenuItem()] : [])
1217
1228
  ]
1218
1229
  },
1219
1230
  signatureMenuItem(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.21.0-dev2.53",
3
+ "version": "6.21.0-dev2.54",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",