@topconsultnpm/sdkui-react 6.21.0-dev1.13 → 6.21.0-dev1.14

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.
@@ -352,7 +352,7 @@ handleNavigateToWGs, handleNavigateToDossiers, }) => {
352
352
  openTaskFormHandler,
353
353
  },
354
354
  });
355
- const { isOpenDcmtForm, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid, showExportForm, isOpenBatchUpdate, isModifiedBatchUpdate, updateBatchUpdateForm, 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;
355
+ const { isOpenDcmtForm, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid, showExportForm, isOpenBatchUpdate, isModifiedBatchUpdate, updateBatchUpdateForm, handleSignApprove, checkoutInfo: { showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, }, dcmtOperations: { abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, FileSourceDialog, }, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
356
356
  const deviceType = useDeviceType();
357
357
  const isMobile = deviceType === DeviceType.MOBILE;
358
358
  const selectedDocs = getSelectedDcmtsOrFocused(selectedItems, focusedItem);
@@ -123,4 +123,6 @@ export declare class DcmtFormSettings {
123
123
  }
124
124
  export declare class SDKUI_Globals {
125
125
  static userSettings: UserSettings;
126
+ /** Global handler for scanner requests. Set by the host app (e.g. surfer) to open the scanner UI. */
127
+ static scanRequestHandler?: (mode: 'new' | 'edit', onFileScanned: (file: File) => void, onCancel: () => void, existingFile?: File) => void;
126
128
  }
@@ -21,5 +21,6 @@ export interface UseDcmtOperationsReturn {
21
21
  removeDcmtsFileCache: (key: string) => void;
22
22
  isDcmtFileInCache: (key: string) => boolean;
23
23
  runOperationAsync: (inputDcmts: DcmtInfo[] | undefined, dcmtOperationType: DcmtOperationTypes, actionAfterOperationAsync?: () => Promise<void>) => Promise<void>;
24
+ FileSourceDialog: () => JSX.Element;
24
25
  }
25
26
  export declare const useDcmtOperations: () => UseDcmtOperationsReturn;
@@ -4,9 +4,19 @@ import { SDK_Globals, RetrieveFileOptions, DcmtOpers, ResultTypes, RecentCategor
4
4
  import { ShowAlert, TMResultManager, FormulaHelper, TMExceptionBoxManager, TMSpinner } from '../components';
5
5
  import { Globalization, getExceptionMessage, dialogConfirmOperation, extensionHandler, downloadBase64File, SDKUI_Globals, dcmtsFileCacheDownload, CACHE_SIZE_LIMIT, clearDcmtsFileCache, dcmtsFileCachePreview, isDcmtFileInCache, removeDcmtsFileCache, SDKUI_Localizator } from '../helper';
6
6
  import { DcmtOperationTypes, DownloadTypes, FileExtensionHandler } from '../ts';
7
- import { useFileDialog } from './useInputDialog';
7
+ import { useFileDialog, useFileSourceDialog } from './useInputDialog';
8
8
  import { isXMLFileExt } from '../helper/dcmtsHelper';
9
9
  import { ShowConfirm } from '../components/base/TMConfirm';
10
+ import { useBetaFeatures } from './useBetaFeatures';
11
+ const isScannerLicenseConfigured = () => {
12
+ try {
13
+ const scannerLicense = SDKUI_Globals.userSettings.advancedSettings.scannerLicense;
14
+ return scannerLicense && scannerLicense.trim() !== '';
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ };
10
20
  let abortController = new AbortController();
11
21
  const downloadCountMap = new Map();
12
22
  const getDownloadFileName = (fileName) => {
@@ -32,6 +42,8 @@ export const useDcmtOperations = () => {
32
42
  const [waitPanelValueSecondary, setWaitPanelValueSecondary] = useState(0);
33
43
  const [waitPanelMaxValueSecondary, setWaitPanelMaxValueSecondary] = useState(0);
34
44
  const { OpenFileDialog } = useFileDialog();
45
+ const isBetaFeaturesEnabled = useBetaFeatures();
46
+ const [selectFileSource, FileSourceDialog] = useFileSourceDialog();
35
47
  const _downloadDcmtsAsync = async (inputDcmts, downloadMode = "download", onFileDownloaded, skipConfirmation = false) => {
36
48
  if (inputDcmts === undefined)
37
49
  return;
@@ -210,7 +222,60 @@ export const useDcmtOperations = () => {
210
222
  return;
211
223
  if (inputDcmts.length <= 0)
212
224
  return;
213
- let file = inputDcmts[0].FILE ?? await OpenFileDialog();
225
+ let file = inputDcmts[0].FILE;
226
+ if (!file) {
227
+ if (isBetaFeaturesEnabled && isScannerLicenseConfigured()) {
228
+ const source = await selectFileSource();
229
+ if (!source)
230
+ return;
231
+ switch (source) {
232
+ case 'filesystem':
233
+ file = await OpenFileDialog();
234
+ break;
235
+ case 'scanner-new':
236
+ if (SDKUI_Globals.scanRequestHandler) {
237
+ file = await new Promise((resolve) => {
238
+ SDKUI_Globals.scanRequestHandler('new', (scannedFile) => resolve(scannedFile), () => resolve(undefined));
239
+ });
240
+ }
241
+ else {
242
+ ShowAlert({ message: 'Funzionalità scanner non disponibile in questo contesto.', mode: 'info', duration: 3000, title: 'Scanner' });
243
+ return;
244
+ }
245
+ break;
246
+ case 'scanner-edit':
247
+ if (SDKUI_Globals.scanRequestHandler) {
248
+ // Download the existing file from the document
249
+ let existingFile;
250
+ try {
251
+ const rfo = new RetrieveFileOptions();
252
+ rfo.retrieveReason = DcmtOpers.None;
253
+ const retrievedFile = await SDK_Globals.tmSession?.NewSearchEngine().RetrieveFileAsync(inputDcmts[0].TID, inputDcmts[0].DID, rfo);
254
+ existingFile = retrievedFile;
255
+ }
256
+ catch (ex) {
257
+ TMExceptionBoxManager.show({ exception: getExceptionMessage(ex) });
258
+ return;
259
+ }
260
+ if (!existingFile) {
261
+ ShowAlert({ message: 'Impossibile recuperare il file del documento.', mode: 'warning', duration: 3000, title: 'Scanner' });
262
+ return;
263
+ }
264
+ file = await new Promise((resolve) => {
265
+ SDKUI_Globals.scanRequestHandler('edit', (scannedFile) => resolve(scannedFile), () => resolve(undefined), existingFile);
266
+ });
267
+ }
268
+ else {
269
+ ShowAlert({ message: 'Funzionalità scanner non disponibile in questo contesto.', mode: 'info', duration: 3000, title: 'Scanner' });
270
+ return;
271
+ }
272
+ break;
273
+ }
274
+ }
275
+ else {
276
+ file = await OpenFileDialog();
277
+ }
278
+ }
214
279
  if (!file)
215
280
  return;
216
281
  setShowWaitPanel(true);
@@ -489,10 +554,16 @@ export const useDcmtOperations = () => {
489
554
  actionAfterOperationAsync?.();
490
555
  TMResultManager.show(result, operationTitle, "TID", "DID");
491
556
  };
492
- dialogConfirmOperation(operationTitle, msg, doOperationAsync);
557
+ // Per SubstituteFile con beta features e scanner, non mostrare conferma
558
+ if (dcmtOperationType === DcmtOperationTypes.SubstituteFile && isBetaFeaturesEnabled && isScannerLicenseConfigured()) {
559
+ await doOperationAsync();
560
+ }
561
+ else {
562
+ dialogConfirmOperation(operationTitle, msg, doOperationAsync);
563
+ }
493
564
  };
494
565
  return {
495
566
  abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary,
496
- downloadDcmtsAsync, getDcmtFileAsync, clearDcmtsFileCache, removeDcmtsFileCache, isDcmtFileInCache, runOperationAsync
567
+ downloadDcmtsAsync, getDcmtFileAsync, clearDcmtsFileCache, removeDcmtsFileCache, isDcmtFileInCache, runOperationAsync, FileSourceDialog
497
568
  };
498
569
  };
@@ -109,7 +109,7 @@ export const useDocumentOperations = (props) => {
109
109
  const { showHistory, showHistoryCallback, hideHistoryCallback, showCheckoutInformationForm, commentFormState, hideCommentFormCallback, showCheckoutInformationFormCallback, hideCheckoutInformationFormCallback, copyCheckoutPathToClipboardCallback, handleCheckOutCallback, handleCheckInCallback, showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, } = useCheckInOutOperations({
110
110
  onRefreshPreview: onRefreshPreviewCallback
111
111
  });
112
- const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, getDcmtFileAsync, clearDcmtsFileCache, removeDcmtsFileCache, isDcmtFileInCache } = useDcmtOperations();
112
+ const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, getDcmtFileAsync, clearDcmtsFileCache, removeDcmtsFileCache, isDcmtFileInCache, FileSourceDialog } = useDcmtOperations();
113
113
  const {
114
114
  // Data
115
115
  relatedDcmts, pairedSearchResults, manyToManyRelations, selectedManyToManyRelation, manyToManyChooserDataSource, relatedDcmtsChooserDataSource,
@@ -1183,7 +1183,7 @@ export const useDocumentOperations = (props) => {
1183
1183
  updateBatchUpdateForm(false);
1184
1184
  setIsModifiedBatchUpdate(false);
1185
1185
  await onRefreshDataRowsAsync?.();
1186
- }, onStatusChanged: (isModified) => { setIsModifiedBatchUpdate(isModified); } }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: selectedDcmtInfos, isReject: 0, onClose: () => updateShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: selectedDcmtInfos, isReject: 1, onClose: () => updateShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: selectedDcmtInfos, onClose: () => updateShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { fromDTD: dtd, TID: contextConfig.approvalTID, DID: focusedItem?.DID, deviceType: deviceType, onCompleted: handleWFOperationCompleted, onClose: () => updateShowMoreInfoPopup(false), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, triggerBlogRefresh: onRefreshBlogDatagrid }), _jsx(ConfirmFormatDialog, {}), _jsx(ConfirmAttachmentsDialog, {}), taskFormDialogComponent, s4TViewerDialogComponent, currentCustomButton && _jsx(TMCustomButton, { button: currentCustomButton, formData: currentMetadataValues, selectedItems: selectedItemsFull, onClose: () => setCurrentCustomButton(undefined) })] }));
1186
+ }, onStatusChanged: (isModified) => { setIsModifiedBatchUpdate(isModified); } }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: selectedDcmtInfos, isReject: 0, onClose: () => updateShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: selectedDcmtInfos, isReject: 1, onClose: () => updateShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, selectedItems: selectedDcmtInfos, onClose: () => updateShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { fromDTD: dtd, TID: contextConfig.approvalTID, DID: focusedItem?.DID, deviceType: deviceType, onCompleted: handleWFOperationCompleted, onClose: () => updateShowMoreInfoPopup(false), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, triggerBlogRefresh: onRefreshBlogDatagrid }), _jsx(ConfirmFormatDialog, {}), _jsx(ConfirmAttachmentsDialog, {}), _jsx(FileSourceDialog, {}), taskFormDialogComponent, s4TViewerDialogComponent, currentCustomButton && _jsx(TMCustomButton, { button: currentCustomButton, formData: currentMetadataValues, selectedItems: selectedItemsFull, onClose: () => setCurrentCustomButton(undefined) })] }));
1187
1187
  return {
1188
1188
  operationItems: operationItems(),
1189
1189
  renderFloatingBar,
@@ -1236,6 +1236,7 @@ export const useDocumentOperations = (props) => {
1236
1236
  removeDcmtsFileCache,
1237
1237
  isDcmtFileInCache,
1238
1238
  runOperationAsync,
1239
+ FileSourceDialog,
1239
1240
  },
1240
1241
  relatedDocumentsInfo: {
1241
1242
  // Data
@@ -7,3 +7,5 @@ export declare const useInputAttachmentsDialog: () => {
7
7
  openConfirmAttachmentsDialog: (list: FileDescriptor[]) => Promise<string[] | undefined>;
8
8
  ConfirmAttachmentsDialog: () => import("react/jsx-runtime").JSX.Element | null;
9
9
  };
10
+ export type FileSourceType = 'filesystem' | 'scanner-new' | 'scanner-edit' | undefined;
11
+ export declare const useFileSourceDialog: () => [() => Promise<FileSourceType>, () => JSX.Element];
@@ -103,3 +103,37 @@ export const useInputAttachmentsDialog = () => {
103
103
  };
104
104
  return { openConfirmAttachmentsDialog, ConfirmAttachmentsDialog };
105
105
  };
106
+ const fileSourceOptions = [
107
+ { value: 'filesystem', display: 'Da file system' },
108
+ { value: 'scanner-new', display: 'Da scanner (nuova scansione)' },
109
+ { value: 'scanner-edit', display: 'Da scanner (modifica scansione)' },
110
+ ];
111
+ export const useFileSourceDialog = () => {
112
+ const [promise, setPromise] = useState(null);
113
+ const [open, setOpen] = useState(false);
114
+ const handleClose = () => {
115
+ setOpen(false);
116
+ setPromise(null);
117
+ };
118
+ const handleConfirm = (source) => {
119
+ promise?.resolve(source);
120
+ handleClose();
121
+ };
122
+ const handleCancel = () => {
123
+ promise?.resolve(undefined);
124
+ handleClose();
125
+ };
126
+ const FileSourceDialog = () => {
127
+ const [source, setSource] = useState('filesystem');
128
+ return (open ?
129
+ _jsx(TMModal, { title: SDKUI_Localizator.AddOrSubstFile, height: "max-content", width: "320px", onClose: handleCancel, children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '5px', padding: '10px', height: '100%' }, children: [_jsx(TMRadioButton, { dataSource: fileSourceOptions, direction: 'column', value: source, onValueChanged: (newValue) => { setSource(newValue); } }), _jsxs("div", { style: { display: 'flex', flexDirection: 'row', gap: '5px', paddingTop: '10px', justifyContent: 'center', alignItems: 'center', height: '50px' }, children: [_jsx(TMButton, { btnStyle: "advanced", showTooltip: false, icon: _jsx(IconApply, {}), caption: "OK", advancedColor: TMColors.tertiary, onClick: () => handleConfirm(source) }), _jsx(TMButton, { btnStyle: "advanced", showTooltip: false, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Cancel, onClick: handleCancel })] })] }) })
130
+ : _jsx(_Fragment, {}));
131
+ };
132
+ const selectFileSource = () => {
133
+ return new Promise((resolve) => {
134
+ setOpen(true);
135
+ setPromise({ resolve });
136
+ });
137
+ };
138
+ return [selectFileSource, FileSourceDialog];
139
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.21.0-dev1.13",
3
+ "version": "6.21.0-dev1.14",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",