@topconsultnpm/sdkui-react 6.21.0-dev2.32 → 6.21.0-dev2.34
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/editors/TMTextBox.d.ts +2 -0
- package/lib/components/editors/TMTextBox.js +3 -3
- package/lib/components/features/documents/TMCopyToFolderForm.d.ts +16 -0
- package/lib/components/features/documents/TMCopyToFolderForm.js +306 -0
- package/lib/components/features/documents/TMDownloadRelationViewerSection.d.ts +15 -0
- package/lib/components/features/documents/TMDownloadRelationViewerSection.js +155 -0
- package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +4 -0
- package/lib/components/features/documents/TMMasterDetailDcmts.js +6 -5
- package/lib/components/features/documents/TMMergeToPdfForm.d.ts +18 -0
- package/lib/components/features/documents/TMMergeToPdfForm.js +164 -0
- package/lib/components/features/documents/TMRelationViewer.d.ts +13 -0
- package/lib/components/features/documents/TMRelationViewer.js +75 -6
- package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +53 -0
- package/lib/components/features/documents/copyAndMergeDcmtsShared.js +263 -0
- package/lib/components/features/search/TMSearch.d.ts +2 -0
- package/lib/components/features/search/TMSearch.js +2 -2
- package/lib/components/features/search/TMSearchResult.d.ts +2 -0
- package/lib/components/features/search/TMSearchResult.js +3 -2
- package/lib/components/forms/Login/TMLoginForm.d.ts +9 -0
- package/lib/components/forms/Login/TMLoginForm.js +44 -0
- package/lib/helper/SDKUI_Globals.d.ts +16 -0
- package/lib/helper/SDKUI_Globals.js +16 -1
- package/lib/helper/TMUtils.d.ts +19 -0
- package/lib/helper/ZipManager.d.ts +56 -0
- package/lib/helper/ZipManager.js +104 -0
- package/lib/helper/index.d.ts +1 -0
- package/lib/helper/index.js +1 -0
- package/lib/hooks/useDcmtOperations.d.ts +8 -2
- package/lib/hooks/useDcmtOperations.js +29 -20
- package/lib/hooks/useDocumentOperations.d.ts +4 -0
- package/lib/hooks/useDocumentOperations.js +75 -7
- package/package.json +2 -1
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { DcmtTypeListCacheService, LayoutModes, SDK_Globals } from '@topconsultnpm/sdk-ts';
|
|
2
|
+
import { searchResultToMetadataValues, DocumentDownloadSettings } from '../../../helper';
|
|
3
|
+
import { TMColors } from '../../../utils/theme';
|
|
4
|
+
// ============================================================
|
|
5
|
+
// Costanti condivise tra TMCopyToFolderForm e TMMergeToPdfForm
|
|
6
|
+
// ============================================================
|
|
7
|
+
export const SPLITTER_MIN = ['50', '50'];
|
|
8
|
+
export const SPLITTER_START_HALF = ['50%', '50%'];
|
|
9
|
+
export const SPLITTER_START_65_35 = ['65%', '35%'];
|
|
10
|
+
/** Numero minimo di file PDF necessari per poterli unire in un unico documento. */
|
|
11
|
+
export const MIN_PDF_FOR_MERGE = 2;
|
|
12
|
+
// ============================================================
|
|
13
|
+
// Stili comuni
|
|
14
|
+
// ============================================================
|
|
15
|
+
/** Stile per le etichette "floating" posizionate sopra i bordi dei container */
|
|
16
|
+
export const getFloatingLabelStyle = () => ({
|
|
17
|
+
position: 'absolute',
|
|
18
|
+
top: '-10px',
|
|
19
|
+
left: '12px',
|
|
20
|
+
maxWidth: 'calc(100% - 24px)',
|
|
21
|
+
fontSize: '0.85rem',
|
|
22
|
+
fontWeight: 600,
|
|
23
|
+
color: TMColors.primary,
|
|
24
|
+
padding: '0 8px',
|
|
25
|
+
backgroundColor: 'white',
|
|
26
|
+
zIndex: 1,
|
|
27
|
+
whiteSpace: 'nowrap',
|
|
28
|
+
overflow: 'hidden',
|
|
29
|
+
textOverflow: 'ellipsis',
|
|
30
|
+
display: 'inline-block',
|
|
31
|
+
width: 'fit-content',
|
|
32
|
+
lineHeight: '20px',
|
|
33
|
+
letterSpacing: '0.2px',
|
|
34
|
+
boxSizing: 'border-box'
|
|
35
|
+
});
|
|
36
|
+
// ============================================================
|
|
37
|
+
// Helper su IRelatedDcmt
|
|
38
|
+
// ============================================================
|
|
39
|
+
/** Chiave univoca per un IRelatedDcmt basata sulla coppia tid+did */
|
|
40
|
+
export const getDcmtKey = (item) => `${item.tid ?? ''}_${item.did ?? ''}`;
|
|
41
|
+
/** Deduplica gli IRelatedDcmt in base alla coppia tid+did (mantiene la prima occorrenza) */
|
|
42
|
+
export const dedupeByTidDid = (items) => {
|
|
43
|
+
const map = new Map();
|
|
44
|
+
for (const item of items) {
|
|
45
|
+
const key = getDcmtKey(item);
|
|
46
|
+
if (!map.has(key))
|
|
47
|
+
map.set(key, item);
|
|
48
|
+
}
|
|
49
|
+
return Array.from(map.values());
|
|
50
|
+
};
|
|
51
|
+
// ============================================================
|
|
52
|
+
// Feature detection / Estensioni file
|
|
53
|
+
// ============================================================
|
|
54
|
+
/** Verifica se showDirectoryPicker è supportato (Chrome, Edge) */
|
|
55
|
+
export const isDirectoryPickerSupported = () => {
|
|
56
|
+
return 'showDirectoryPicker' in window;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Verifica se un'estensione (con o senza punto iniziale, case-insensitive) è "pdf".
|
|
60
|
+
*/
|
|
61
|
+
export const isPdfExt = (ext) => {
|
|
62
|
+
if (!ext)
|
|
63
|
+
return false;
|
|
64
|
+
const normalized = ext.trim().toLowerCase().replace(/^\./, '');
|
|
65
|
+
return normalized === 'pdf';
|
|
66
|
+
};
|
|
67
|
+
// ============================================================
|
|
68
|
+
// Sanitizzazione e gestione nomi file
|
|
69
|
+
// ============================================================
|
|
70
|
+
/** Sanitizza il nome file per Windows (rimuove caratteri illegali e limita la lunghezza) */
|
|
71
|
+
export const sanitizeFileName = (fileName, fallbackName, maxLength = 255) => {
|
|
72
|
+
try {
|
|
73
|
+
const illegalCharsRegex = /[<>:"/\\|?*]/g;
|
|
74
|
+
const controlCharsRegex = /[\x00-\x1F\x7F]/g;
|
|
75
|
+
let sanitized = fileName
|
|
76
|
+
.replace(illegalCharsRegex, '_')
|
|
77
|
+
.replace(controlCharsRegex, '')
|
|
78
|
+
.trim();
|
|
79
|
+
sanitized = sanitized.replace(/[. ]+$/, '');
|
|
80
|
+
if (sanitized.length > maxLength) {
|
|
81
|
+
const lastDotIndex = sanitized.lastIndexOf('.');
|
|
82
|
+
if (lastDotIndex > 0) {
|
|
83
|
+
const extension = sanitized.substring(lastDotIndex);
|
|
84
|
+
const baseName = sanitized.substring(0, lastDotIndex);
|
|
85
|
+
const maxBaseLength = maxLength - extension.length;
|
|
86
|
+
sanitized = baseName.substring(0, maxBaseLength) + extension;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
sanitized = sanitized.substring(0, maxLength);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return sanitized || fallbackName;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return fallbackName;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
/** Verifica se un file esiste nella cartella (FileSystemDirectoryHandle) */
|
|
99
|
+
export const fileExists = async (dirHandle, fileName) => {
|
|
100
|
+
try {
|
|
101
|
+
await dirHandle.getFileHandle(fileName, { create: false });
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
/** Genera un nome file univoco aggiungendo un suffisso numerico se già esistente */
|
|
109
|
+
export const generateUniqueFileName = async (dirHandle, originalName) => {
|
|
110
|
+
const splitName = (name) => {
|
|
111
|
+
const lastDotIndex = name.lastIndexOf('.');
|
|
112
|
+
const baseName = lastDotIndex > 0 ? name.substring(0, lastDotIndex) : name;
|
|
113
|
+
const extension = lastDotIndex > 0 ? name.substring(lastDotIndex) : '';
|
|
114
|
+
return { baseName, extension };
|
|
115
|
+
};
|
|
116
|
+
try {
|
|
117
|
+
const { baseName, extension } = splitName(originalName);
|
|
118
|
+
const MAX_ATTEMPTS = 1000;
|
|
119
|
+
for (let counter = 1; counter <= MAX_ATTEMPTS; counter++) {
|
|
120
|
+
const candidateName = counter === 1 ? originalName : `${baseName} (${counter - 1})${extension}`;
|
|
121
|
+
try {
|
|
122
|
+
await dirHandle.getFileHandle(candidateName, { create: false });
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return candidateName;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return `${baseName}_${Date.now()}${extension}`;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
const { baseName, extension } = splitName(originalName);
|
|
132
|
+
return `${baseName}_${Date.now()}${extension}`;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
// ============================================================
|
|
136
|
+
// Helper per la generazione del nome di destinazione del file
|
|
137
|
+
// (in base alle impostazioni utente: tipo, metadati, separatore...)
|
|
138
|
+
// ============================================================
|
|
139
|
+
/** Recupera il nome leggibile del tipo documento (cache) */
|
|
140
|
+
export const getTypeName = async (tid) => {
|
|
141
|
+
const typeList = await DcmtTypeListCacheService.GetAllWithoutMetadataAsync();
|
|
142
|
+
const foundDtd = typeList.find(dtd => dtd.id?.toString() === tid?.toString());
|
|
143
|
+
return foundDtd?.name ?? String(tid);
|
|
144
|
+
};
|
|
145
|
+
/** Formatta un valore convertendo le date in formato dd-MM-yyyy [HH-mm-ss] */
|
|
146
|
+
export const formatMetadataValue = (value) => {
|
|
147
|
+
const date = new Date(value);
|
|
148
|
+
if (!isNaN(date.getTime())) {
|
|
149
|
+
const day = date.getDate().toString().padStart(2, '0');
|
|
150
|
+
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
151
|
+
const year = date.getFullYear();
|
|
152
|
+
const hours = date.getHours();
|
|
153
|
+
const minutes = date.getMinutes();
|
|
154
|
+
const seconds = date.getSeconds();
|
|
155
|
+
if (hours !== 0 || minutes !== 0 || seconds !== 0) {
|
|
156
|
+
const hh = hours.toString().padStart(2, '0');
|
|
157
|
+
const mm = minutes.toString().padStart(2, '0');
|
|
158
|
+
const ss = seconds.toString().padStart(2, '0');
|
|
159
|
+
return `${day}-${month}-${year} ${hh}-${mm}-${ss}`;
|
|
160
|
+
}
|
|
161
|
+
return `${day}-${month}-${year}`;
|
|
162
|
+
}
|
|
163
|
+
return value;
|
|
164
|
+
};
|
|
165
|
+
/** Recupera i metadati filtrati (primi 5 con mid > 100 e valore presente), concatenati con separatorChar */
|
|
166
|
+
export const getFilteredMetadata = async (tid, did, separatorChar) => {
|
|
167
|
+
const metadata = await SDK_Globals.tmSession?.NewSearchEngine().GetMetadataAsync(tid, did, true);
|
|
168
|
+
if (!metadata)
|
|
169
|
+
return null;
|
|
170
|
+
const dtdResult = metadata.dtdResult;
|
|
171
|
+
const rows = dtdResult?.rows?.[0] ?? [];
|
|
172
|
+
const mids = metadata.selectMIDs;
|
|
173
|
+
const dtdWithMetadata = await DcmtTypeListCacheService.GetWithNotGrantedAsync(tid, did, metadata);
|
|
174
|
+
const mdList = dtdWithMetadata?.metadata ?? [];
|
|
175
|
+
const metadataList = searchResultToMetadataValues(tid, dtdResult, rows, mids, mdList, LayoutModes.Update);
|
|
176
|
+
return metadataList
|
|
177
|
+
.reduce((acc, md) => acc.length < 5 && md.mid && md.mid > 100 && md.value ? [...acc, formatMetadataValue(md.value)] : acc, [])
|
|
178
|
+
.join(separatorChar);
|
|
179
|
+
};
|
|
180
|
+
/** Genera il nome file di destinazione in base alle impostazioni di naming */
|
|
181
|
+
export const generateTargetFileName = async (file, dcmtInfo, options) => {
|
|
182
|
+
const { fileNamingMode, separatorChar } = options;
|
|
183
|
+
const lastDotIndex = file.name.lastIndexOf('.');
|
|
184
|
+
const fileExtension = lastDotIndex > 0 ? file.name.substring(lastDotIndex) : '';
|
|
185
|
+
const fallbackName = dcmtInfo.DID + fileExtension;
|
|
186
|
+
let targetFileName = file.name;
|
|
187
|
+
switch (fileNamingMode) {
|
|
188
|
+
case 'onlyDid':
|
|
189
|
+
targetFileName = fallbackName;
|
|
190
|
+
break;
|
|
191
|
+
case 'documentTypeAndDid': {
|
|
192
|
+
const typeName = await getTypeName(dcmtInfo.TID);
|
|
193
|
+
targetFileName = `${typeName}${separatorChar}${dcmtInfo.DID}${fileExtension}`;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case 'documentTypeAndCustomMetadata':
|
|
197
|
+
case 'onlyCustomMetadata': {
|
|
198
|
+
try {
|
|
199
|
+
const filteredMetadata = await getFilteredMetadata(dcmtInfo.TID, dcmtInfo.DID, separatorChar);
|
|
200
|
+
if (filteredMetadata) {
|
|
201
|
+
if (fileNamingMode === 'documentTypeAndCustomMetadata') {
|
|
202
|
+
const typeName = await getTypeName(dcmtInfo.TID);
|
|
203
|
+
targetFileName = `${typeName}${separatorChar}${filteredMetadata}${fileExtension}`;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
targetFileName = `${filteredMetadata}${fileExtension}`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
targetFileName = fallbackName;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
targetFileName = fallbackName;
|
|
215
|
+
}
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
default:
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
return sanitizeFileName(targetFileName, fallbackName);
|
|
222
|
+
};
|
|
223
|
+
// ============================================================
|
|
224
|
+
// Build della lista di DcmtInfo effettivi da scaricare
|
|
225
|
+
// ============================================================
|
|
226
|
+
/**
|
|
227
|
+
* Restituisce i documenti da scaricare:
|
|
228
|
+
* - se è visibile il TMRelationViewer, usa gli isDcmt selezionati al suo interno
|
|
229
|
+
* - altrimenti restituisce i selectedDcmtInfos passati come prop
|
|
230
|
+
*/
|
|
231
|
+
export const getDcmtInfosToDownload = (selectedDcmtInfos, selectedItemsRelationViewer, showTMRelationViewer) => {
|
|
232
|
+
if (showTMRelationViewer) {
|
|
233
|
+
return selectedItemsRelationViewer
|
|
234
|
+
.filter(i => i.isDcmt && i.tid != null && i.did != null)
|
|
235
|
+
.map(i => ({ TID: i.tid, DID: i.did }));
|
|
236
|
+
}
|
|
237
|
+
return selectedDcmtInfos;
|
|
238
|
+
};
|
|
239
|
+
// ============================================================
|
|
240
|
+
// Stato iniziale settings (con valori salvati o default)
|
|
241
|
+
// ============================================================
|
|
242
|
+
/**
|
|
243
|
+
* Costruisce lo stato iniziale di DocumentDownloadSettings combinando:
|
|
244
|
+
* - i valori salvati in userSettings (se presenti)
|
|
245
|
+
* - i default della classe
|
|
246
|
+
* Nota: destinationFolder e zipPassword vengono sempre resettati per sicurezza.
|
|
247
|
+
*/
|
|
248
|
+
export const buildInitialDownloadSettings = (saved, defaultInvoiceFormat, defaultOrderFormat) => {
|
|
249
|
+
const defaults = new DocumentDownloadSettings();
|
|
250
|
+
return {
|
|
251
|
+
exportMode: saved?.exportMode ?? defaults.exportMode,
|
|
252
|
+
destinationFolder: 'Download',
|
|
253
|
+
zipFileName: saved?.zipFileName ?? defaults.zipFileName,
|
|
254
|
+
zipPassword: '',
|
|
255
|
+
fileNamingMode: saved?.fileNamingMode ?? defaults.fileNamingMode,
|
|
256
|
+
separatorChar: saved?.separatorChar ?? defaults.separatorChar,
|
|
257
|
+
invoiceFormat: saved?.invoiceFormat ?? defaultInvoiceFormat,
|
|
258
|
+
orderFormat: saved?.orderFormat ?? defaultOrderFormat,
|
|
259
|
+
fileExistsMode: saved?.fileExistsMode ?? defaults.fileExistsMode,
|
|
260
|
+
removeSignature: saved?.removeSignature ?? defaults.removeSignature,
|
|
261
|
+
pdfFileName: saved?.pdfFileName ?? defaults.pdfFileName,
|
|
262
|
+
};
|
|
263
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { SavedQueryDescriptor, DcmtTypeDescriptor, TaskDescriptor, ObjectRef, HomeBlogPost } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { MergePdfManagerType } from '../../../helper';
|
|
3
4
|
import { DcmtInfo, TaskContext } from '../../../ts';
|
|
4
5
|
import { TMSearchResultFloatingActionConfig } from './TMSearchResultFloatingActionButton';
|
|
5
6
|
interface ITMSearchProps {
|
|
@@ -40,6 +41,7 @@ interface ITMSearchProps {
|
|
|
40
41
|
onCurrentTIDChangedCallback?: (tid: number | undefined) => void;
|
|
41
42
|
onlyShowSearchQueryPanel?: boolean;
|
|
42
43
|
onReferenceClick?: (ref: ObjectRef) => void;
|
|
44
|
+
mergePdfManager?: MergePdfManagerType;
|
|
43
45
|
}
|
|
44
46
|
declare const TMSearch: React.FunctionComponent<ITMSearchProps>;
|
|
45
47
|
export default TMSearch;
|
|
@@ -20,7 +20,7 @@ var TMSearchViews;
|
|
|
20
20
|
TMSearchViews[TMSearchViews["Search"] = 0] = "Search";
|
|
21
21
|
TMSearchViews[TMSearchViews["Result"] = 1] = "Result";
|
|
22
22
|
})(TMSearchViews || (TMSearchViews = {}));
|
|
23
|
-
const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, editPdfForm = false, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, showTodoDcmtForm, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel, onReferenceClick, refreshFavoriteSavedQueries }) => {
|
|
23
|
+
const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, editPdfForm = false, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, showTodoDcmtForm, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel, onReferenceClick, refreshFavoriteSavedQueries, mergePdfManager }) => {
|
|
24
24
|
const [allSQDs, setAllSQDs] = useState([]);
|
|
25
25
|
const [filteredByTIDSQDs, setFilteredByTIDSQDs] = useState([]);
|
|
26
26
|
const [currentSQD, setCurrentSQD] = useState();
|
|
@@ -266,7 +266,7 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
266
266
|
toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
|
|
267
267
|
}
|
|
268
268
|
], [tmTreeSelectorElement, showSearchResults, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
|
|
269
|
-
return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', isPersistenceEnabled: !isMobile ? hasSavedLayout() : false, persistPanelStates: !isMobile ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: getPersistedPanelStates(), children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true, minPanelSizePx: !isMobile ? 250 : 150 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsyncDatagrid: onRefreshSearchAsyncDatagrid, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, openFileUploaderPdfEditor: openFileUploaderPdfEditor, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, showToppyDraggableHelpCenter: showToppyDraggableHelpCenter, toppyHelpCenterUsePortal: toppyHelpCenterUsePortal, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers })] }));
|
|
269
|
+
return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', isPersistenceEnabled: !isMobile ? hasSavedLayout() : false, persistPanelStates: !isMobile ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: getPersistedPanelStates(), children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true, minPanelSizePx: !isMobile ? 250 : 150 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsyncDatagrid: onRefreshSearchAsyncDatagrid, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, openFileUploaderPdfEditor: openFileUploaderPdfEditor, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, showToppyDraggableHelpCenter: showToppyDraggableHelpCenter, toppyHelpCenterUsePortal: toppyHelpCenterUsePortal, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, mergePdfManager: mergePdfManager })] }));
|
|
270
270
|
};
|
|
271
271
|
export default TMSearch;
|
|
272
272
|
const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { DcmtTypeDescriptor, HomeBlogPost, ObjectRef, SearchResultDescriptor, TaskDescriptor, WorkingGroupDescriptor } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { MergePdfManagerType } from '../../../helper';
|
|
3
4
|
import { DcmtInfo, SearchResultContext, TaskContext } from '../../../ts';
|
|
4
5
|
import { TMSearchResultFloatingActionConfig } from './TMSearchResultFloatingActionButton';
|
|
5
6
|
export declare const getSearchResultCountersSingleCategory: (searchResults: SearchResultDescriptor[]) => string;
|
|
@@ -29,6 +30,7 @@ interface ITMSearchResultProps {
|
|
|
29
30
|
showToppyDraggableHelpCenter?: boolean;
|
|
30
31
|
toppyHelpCenterUsePortal?: boolean;
|
|
31
32
|
showNoDcmtFoundMessage?: boolean;
|
|
33
|
+
mergePdfManager?: MergePdfManagerType;
|
|
32
34
|
onClose?: () => void;
|
|
33
35
|
openInOffice?: (selectedDcmtsOrFocused: Array<DcmtInfo>) => Promise<void>;
|
|
34
36
|
onWFOperationCompleted?: () => Promise<void>;
|
|
@@ -54,7 +54,7 @@ const TMSearchResult = ({
|
|
|
54
54
|
// Data
|
|
55
55
|
groupId, searchResults = [], context = SearchResultContext.METADATA_SEARCH, title, selectedSearchResultTID, floatingActionConfig, workingGroupContext = undefined,
|
|
56
56
|
// Boolean flags to enable/disable features
|
|
57
|
-
isVisible = true, allowRelations = true, openDcmtFormAsModal = false, showSearchResultSidebar = true, showDcmtFormSidebar = true, showSelector = false, isClosable = false, allowFloatingBar = true, showToolbarHeader = true, showBackButton = true, disableAccordionIfSingleCategory = false, editPdfForm = false, openS4TViewer = false, showTodoDcmtForm = false, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, showNoDcmtFoundMessage = true, enablePinIcons = true,
|
|
57
|
+
isVisible = true, allowRelations = true, openDcmtFormAsModal = false, showSearchResultSidebar = true, showDcmtFormSidebar = true, showSelector = false, isClosable = false, allowFloatingBar = true, showToolbarHeader = true, showBackButton = true, disableAccordionIfSingleCategory = false, editPdfForm = false, openS4TViewer = false, showTodoDcmtForm = false, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, showNoDcmtFoundMessage = true, enablePinIcons = true, mergePdfManager,
|
|
58
58
|
// Callbacks (optional)
|
|
59
59
|
openInOffice, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsyncDatagrid, onSelectedTIDChanged, onWFOperationCompleted, onClose, onFileOpened, onTaskCreateRequest, openWGsCopyMoveForm, openCommentFormCallback, openAddDocumentForm, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, passToArchiveCallback, onReferenceClick,
|
|
60
60
|
// Tasks
|
|
@@ -291,7 +291,7 @@ handleNavigateToWGs, handleNavigateToDossiers, }) => {
|
|
|
291
291
|
createTaskFromDocumentOrWorkItem();
|
|
292
292
|
}
|
|
293
293
|
};
|
|
294
|
-
const { operationItems, renderFloatingBar, renderDcmtOperations, features } = useDocumentOperations({
|
|
294
|
+
const { operationItems, renderFloatingBar, renderDcmtOperations, features, } = useDocumentOperations({
|
|
295
295
|
context: context,
|
|
296
296
|
documentData: {
|
|
297
297
|
dtd: fromDTD,
|
|
@@ -361,6 +361,7 @@ handleNavigateToWGs, handleNavigateToDossiers, }) => {
|
|
|
361
361
|
onTaskCreateRequest,
|
|
362
362
|
openTaskFormHandler,
|
|
363
363
|
},
|
|
364
|
+
mergePdfManager,
|
|
364
365
|
});
|
|
365
366
|
const { isOpenDcmtForm, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid, showExportForm, isOpenBatchUpdate, isModifiedBatchUpdate, updateBatchUpdateForm, closeDcmtFormHandler, handleSignApprove, checkoutInfo: { showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, }, dcmtOperations: { abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, }, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
|
|
366
367
|
const deviceType = useDeviceType();
|
|
@@ -31,6 +31,14 @@ export declare const cultureIDsDataSource: {
|
|
|
31
31
|
value: CultureIDs;
|
|
32
32
|
display: string;
|
|
33
33
|
}[];
|
|
34
|
+
export interface ITMLoginDefaultValues {
|
|
35
|
+
endpoint: string;
|
|
36
|
+
archiveId?: string;
|
|
37
|
+
authenticationMode?: AuthenticationModes;
|
|
38
|
+
username?: string;
|
|
39
|
+
behalfUsername?: string;
|
|
40
|
+
domain?: string;
|
|
41
|
+
}
|
|
34
42
|
interface ITMLoginFormProps {
|
|
35
43
|
isConnector?: boolean;
|
|
36
44
|
sdInput?: SessionDescriptor;
|
|
@@ -39,6 +47,7 @@ interface ITMLoginFormProps {
|
|
|
39
47
|
onLogged: (tmSession: ITopMediaSession) => void;
|
|
40
48
|
onChangeLanguage?: (e: CultureIDs) => void;
|
|
41
49
|
cultureID?: CultureIDs;
|
|
50
|
+
defaultLoginValues?: ITMLoginDefaultValues;
|
|
42
51
|
}
|
|
43
52
|
declare const TMLoginForm: React.FunctionComponent<ITMLoginFormProps>;
|
|
44
53
|
export default TMLoginForm;
|
|
@@ -106,6 +106,7 @@ const TMLoginForm = (props) => {
|
|
|
106
106
|
const passwordRef = useRef(null);
|
|
107
107
|
const usernameOnBehalfOfRef = useRef(null);
|
|
108
108
|
const passwordOnBehalfOfRRef = useRef(null);
|
|
109
|
+
const defaultLoginAppliedRef = useRef(false);
|
|
109
110
|
const [loginStep, setLoginStep] = useState(1);
|
|
110
111
|
const [tmServer, setTmServer] = useState();
|
|
111
112
|
const [tmSession, setTmSession] = useState();
|
|
@@ -201,6 +202,23 @@ const TMLoginForm = (props) => {
|
|
|
201
202
|
setUsername(props.sdInput.userName);
|
|
202
203
|
}
|
|
203
204
|
}, []);
|
|
205
|
+
useEffect(() => {
|
|
206
|
+
if (!props.defaultLoginValues)
|
|
207
|
+
return;
|
|
208
|
+
const matchingEndpoint = props.endpoints.find(ep => ep.URL === props.defaultLoginValues.endpoint);
|
|
209
|
+
if (!matchingEndpoint)
|
|
210
|
+
return;
|
|
211
|
+
setEndpoint(matchingEndpoint);
|
|
212
|
+
if (props.defaultLoginValues.archiveId)
|
|
213
|
+
setManualArchiveID(props.defaultLoginValues.archiveId);
|
|
214
|
+
setAuthMode(props.defaultLoginValues.authenticationMode ?? AuthenticationModes.TopMedia);
|
|
215
|
+
if (props.defaultLoginValues.username)
|
|
216
|
+
setUsername(props.defaultLoginValues.username);
|
|
217
|
+
if (props.defaultLoginValues.domain)
|
|
218
|
+
setAuthDomain(props.defaultLoginValues.domain);
|
|
219
|
+
if (props.defaultLoginValues.behalfUsername)
|
|
220
|
+
setUsernameOnBehalf(props.defaultLoginValues.behalfUsername);
|
|
221
|
+
}, [props.defaultLoginValues, props.endpoints]);
|
|
204
222
|
useEffect(() => {
|
|
205
223
|
if (!hasSingleOption)
|
|
206
224
|
return;
|
|
@@ -216,6 +234,9 @@ const TMLoginForm = (props) => {
|
|
|
216
234
|
setDcmtArchive(undefined);
|
|
217
235
|
}, [isSuccess]);
|
|
218
236
|
useEffect(() => {
|
|
237
|
+
// Skip default endpoint
|
|
238
|
+
if (props.defaultLoginValues && props.endpoints.some(ep => ep.URL === props.defaultLoginValues.endpoint))
|
|
239
|
+
return;
|
|
219
240
|
let preferredRapidAccess = localRa?.find(ar => ar.preferred === true);
|
|
220
241
|
if (preferredRapidAccess) {
|
|
221
242
|
handleRapidAccessSelection(preferredRapidAccess);
|
|
@@ -240,6 +261,29 @@ const TMLoginForm = (props) => {
|
|
|
240
261
|
useEffect(() => {
|
|
241
262
|
getArchivesAsync();
|
|
242
263
|
}, [tmSession]);
|
|
264
|
+
// Default values and step management
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
if (!props.defaultLoginValues || !props.defaultLoginValues.archiveId || defaultLoginAppliedRef.current || !tmSession || !tmSession.TopMediaServer?.BaseAddress)
|
|
267
|
+
return;
|
|
268
|
+
defaultLoginAppliedRef.current = true;
|
|
269
|
+
const archiveId = props.defaultLoginValues.archiveId;
|
|
270
|
+
const validateAndAdvance = async () => {
|
|
271
|
+
try {
|
|
272
|
+
TMSpinner.show({ description: '' });
|
|
273
|
+
const archiveEngine = tmSession.NewArchiveEngine();
|
|
274
|
+
const result = await archiveEngine.RetrieveAsync(archiveId);
|
|
275
|
+
setDcmtArchive(result);
|
|
276
|
+
setLoginStep(2);
|
|
277
|
+
}
|
|
278
|
+
catch (e) {
|
|
279
|
+
TMExceptionBoxManager.show({ exception: e });
|
|
280
|
+
}
|
|
281
|
+
finally {
|
|
282
|
+
TMSpinner.hide();
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
validateAndAdvance();
|
|
286
|
+
}, [tmSession, props.defaultLoginValues]);
|
|
243
287
|
useEffect(() => {
|
|
244
288
|
if (!saveLoginEnable || !dcmtArchive)
|
|
245
289
|
return;
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import { InvoiceRetrieveFormats, ObjectClasses, OrderRetrieveFormats } from "@topconsultnpm/sdk-ts";
|
|
2
2
|
import { CheckoutInfo } from "./checkinCheckoutManager";
|
|
3
|
+
export type FileNamingMode = 'onlyDid' | 'documentTypeAndDid' | 'documentTypeAndCustomMetadata' | 'onlyCustomMetadata';
|
|
4
|
+
export type FileExistsMode = 'overwrite' | 'skip' | 'rename';
|
|
5
|
+
export declare class DocumentDownloadSettings {
|
|
6
|
+
exportMode: 'copy' | 'zip';
|
|
7
|
+
destinationFolder: string;
|
|
8
|
+
zipFileName: string;
|
|
9
|
+
zipPassword: string;
|
|
10
|
+
fileNamingMode: FileNamingMode;
|
|
11
|
+
separatorChar: string;
|
|
12
|
+
invoiceFormat: InvoiceRetrieveFormats;
|
|
13
|
+
orderFormat: OrderRetrieveFormats;
|
|
14
|
+
fileExistsMode: FileExistsMode;
|
|
15
|
+
removeSignature: boolean;
|
|
16
|
+
pdfFileName: string;
|
|
17
|
+
}
|
|
3
18
|
export declare const dcmtsFileCacheDownload: Map<string, File>;
|
|
4
19
|
export declare const dcmtsFileCachePreview: Map<string, File>;
|
|
5
20
|
export declare const CACHE_SIZE_LIMIT = 10;
|
|
@@ -22,6 +37,7 @@ export declare class UserSettings {
|
|
|
22
37
|
wgDraftCheckoutInfo: CheckoutInfo[];
|
|
23
38
|
dcmtCheckoutInfo: CheckoutInfo[];
|
|
24
39
|
defaultCheckInOutFolder: string;
|
|
40
|
+
documentDownloadSettings: DocumentDownloadSettings;
|
|
25
41
|
constructor(skipCssUpdate?: boolean);
|
|
26
42
|
/** Load settings from local storage or other sources */
|
|
27
43
|
static LoadSettings(userID: number | undefined, archiveID: string | undefined): UserSettings;
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { InvoiceRetrieveFormats, LocalStorageService, OrderRetrieveFormats } from "@topconsultnpm/sdk-ts";
|
|
2
2
|
import { FontSize } from "../utils/theme";
|
|
3
|
-
|
|
3
|
+
export class DocumentDownloadSettings {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.exportMode = 'copy';
|
|
6
|
+
this.destinationFolder = 'Download';
|
|
7
|
+
this.zipFileName = '';
|
|
8
|
+
this.zipPassword = '';
|
|
9
|
+
this.fileNamingMode = 'documentTypeAndDid';
|
|
10
|
+
this.separatorChar = '_';
|
|
11
|
+
this.invoiceFormat = InvoiceRetrieveFormats.ASW_HTML;
|
|
12
|
+
this.orderFormat = OrderRetrieveFormats.NSO_HTML;
|
|
13
|
+
this.fileExistsMode = 'overwrite';
|
|
14
|
+
this.removeSignature = false;
|
|
15
|
+
this.pdfFileName = '';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
4
18
|
export const dcmtsFileCacheDownload = new Map();
|
|
5
19
|
export const dcmtsFileCachePreview = new Map();
|
|
6
20
|
export const CACHE_SIZE_LIMIT = 10;
|
|
@@ -24,6 +38,7 @@ export class UserSettings {
|
|
|
24
38
|
this.wgDraftCheckoutInfo = [];
|
|
25
39
|
this.dcmtCheckoutInfo = [];
|
|
26
40
|
this.defaultCheckInOutFolder = DEFAULT_CHECK_IN_OUT_FOLDER;
|
|
41
|
+
this.documentDownloadSettings = new DocumentDownloadSettings();
|
|
27
42
|
this.themeSettings = new ThemeSettings(skipCssUpdate);
|
|
28
43
|
}
|
|
29
44
|
/** Load settings from local storage or other sources */
|
package/lib/helper/TMUtils.d.ts
CHANGED
|
@@ -53,4 +53,23 @@ type DcmtFormToolbarVisibility = {
|
|
|
53
53
|
tmDcmtTasks: boolean;
|
|
54
54
|
};
|
|
55
55
|
export declare const getDcmtFormToolbarVisibility: (appModuleID: AppModules) => DcmtFormToolbarVisibility;
|
|
56
|
+
export type MergePdfManagerType = {
|
|
57
|
+
merge: (files: File[], options?: {
|
|
58
|
+
onProgress?: (current: number, total: number, file: File) => void;
|
|
59
|
+
}) => Promise<{
|
|
60
|
+
bytes: Uint8Array;
|
|
61
|
+
blob: Blob;
|
|
62
|
+
pageCount: number;
|
|
63
|
+
}>;
|
|
64
|
+
mergeToFile: (files: File[], fileName?: string, options?: {
|
|
65
|
+
onProgress?: (current: number, total: number, file: File) => void;
|
|
66
|
+
}) => Promise<File>;
|
|
67
|
+
mergeAndDownload: (files: File[], fileName?: string, options?: {
|
|
68
|
+
onProgress?: (current: number, total: number, file: File) => void;
|
|
69
|
+
}) => Promise<{
|
|
70
|
+
bytes: Uint8Array;
|
|
71
|
+
blob: Blob;
|
|
72
|
+
pageCount: number;
|
|
73
|
+
}>;
|
|
74
|
+
};
|
|
56
75
|
export {};
|
|
@@ -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
|
+
}): 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;
|