@topconsultnpm/sdkui-react 6.21.0-dev1.3 → 6.21.0-dev1.30

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.
Files changed (40) hide show
  1. package/lib/components/base/TMAreaManager.js +18 -3
  2. package/lib/components/base/TMPanel.js +1 -0
  3. package/lib/components/choosers/TMUserChooser.js +3 -1
  4. package/lib/components/editors/TMFormulaEditor.js +15 -3
  5. package/lib/components/features/archive/TMArchive.js +1 -1
  6. package/lib/components/features/documents/TMDcmtForm.js +12 -8
  7. package/lib/components/features/documents/TMFileUploader.d.ts +1 -1
  8. package/lib/components/features/documents/TMFileUploader.js +3 -3
  9. package/lib/components/features/documents/TMMasterDetailDcmts.js +74 -21
  10. package/lib/components/features/documents/TMRelationViewer.d.ts +6 -1
  11. package/lib/components/features/documents/TMRelationViewer.js +44 -7
  12. package/lib/components/features/search/TMSavedQuerySelector.js +1 -1
  13. package/lib/components/features/search/TMSearch.d.ts +1 -0
  14. package/lib/components/features/search/TMSearch.js +2 -2
  15. package/lib/components/features/search/TMSearchResult.d.ts +1 -0
  16. package/lib/components/features/search/TMSearchResult.js +18 -4
  17. package/lib/components/features/search/TMViewHistoryDcmt.js +6 -0
  18. package/lib/components/features/workflow/diagram/DiagramItemForm.js +5 -1
  19. package/lib/components/features/workflow/diagram/WFDiagram.js +7 -1
  20. package/lib/components/features/workflow/diagram/xmlParser.js +13 -14
  21. package/lib/components/forms/Login/TMLoginForm.js +15 -5
  22. package/lib/components/index.d.ts +1 -0
  23. package/lib/components/index.js +1 -0
  24. package/lib/components/pages/TMPage.js +4 -2
  25. package/lib/components/query/TMQueryCountButton.d.ts +11 -0
  26. package/lib/components/query/TMQueryCountButton.js +32 -0
  27. package/lib/components/query/TMQueryEditor.js +41 -4
  28. package/lib/components/query/TMQuerySummary.js +3 -2
  29. package/lib/helper/SDKUI_Globals.d.ts +2 -0
  30. package/lib/helper/checkinCheckoutManager.d.ts +1 -1
  31. package/lib/helper/checkinCheckoutManager.js +18 -4
  32. package/lib/hooks/useDcmtOperations.d.ts +1 -0
  33. package/lib/hooks/useDcmtOperations.js +75 -4
  34. package/lib/hooks/useDocumentOperations.d.ts +1 -0
  35. package/lib/hooks/useDocumentOperations.js +15 -10
  36. package/lib/hooks/useForm.js +20 -14
  37. package/lib/hooks/useInputDialog.d.ts +2 -0
  38. package/lib/hooks/useInputDialog.js +34 -0
  39. package/lib/hooks/useQueryParametersDialog.js +5 -5
  40. package/package.json +55 -55
@@ -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
  };
@@ -86,6 +86,7 @@ export interface OperationCallbacks {
86
86
  openWGsCopyMoveForm?: (mode: "copyToWgDraft" | "copyToWgArchivedDoc", dcmtTypeDescriptor: DcmtTypeDescriptor, documents: Array<DcmtInfo>) => void;
87
87
  onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: () => Promise<void>) => void;
88
88
  onOpenPdfEditorRequest?: (dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: () => Promise<void>) => void;
89
+ openFileUploaderPdfEditor?: (fromDTD?: DcmtTypeDescriptor, file?: File | null, handleFile?: (file: File) => void) => void;
89
90
  onTaskCreateRequest?: (taskContext: TaskContext, onTaskCreated?: (task?: TaskDescriptor) => void) => void;
90
91
  openTaskFormHandler?: (onTaskCreated?: (task?: TaskDescriptor) => void) => void;
91
92
  }
@@ -93,7 +93,7 @@ export const useDocumentOperations = (props) => {
93
93
  // Navigation
94
94
  canNavigateHandler, onNavigateHandler, handleNavigateToWGs, handleNavigateToDossiers, onReferenceClick,
95
95
  // Document forms/operations
96
- openAddDocumentForm, openCommentFormCallback, onFileOpened, passToArchiveCallback, openWGsCopyMoveForm, onOpenS4TViewerRequest, onOpenPdfEditorRequest,
96
+ openAddDocumentForm, openCommentFormCallback, onFileOpened, passToArchiveCallback, openWGsCopyMoveForm, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor,
97
97
  // Task related
98
98
  onTaskCreateRequest, openTaskFormHandler, } = callbacks;
99
99
  // Force recalculation of selectedDcmtInfos when refreshOperationsTrigger changes (e.g., after file substitution where FILEEXT may change)
@@ -105,10 +105,11 @@ export const useDocumentOperations = (props) => {
105
105
  }, [refreshOperationsTrigger]);
106
106
  // Context helpers
107
107
  const isDcmtFormContext = context === SearchResultContext.DCMT_FORM;
108
+ const isMasterDetailContext = context === SearchResultContext.MASTER_DETAIL;
108
109
  const { showHistory, showHistoryCallback, hideHistoryCallback, showCheckoutInformationForm, commentFormState, hideCommentFormCallback, showCheckoutInformationFormCallback, hideCheckoutInformationFormCallback, copyCheckoutPathToClipboardCallback, handleCheckOutCallback, handleCheckInCallback, showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, } = useCheckInOutOperations({
109
110
  onRefreshPreview: onRefreshPreviewCallback
110
111
  });
111
- 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();
112
113
  const {
113
114
  // Data
114
115
  relatedDcmts, pairedSearchResults, manyToManyRelations, selectedManyToManyRelation, manyToManyChooserDataSource, relatedDcmtsChooserDataSource,
@@ -632,7 +633,7 @@ export const useDocumentOperations = (props) => {
632
633
  const checkinMenuItem = () => {
633
634
  // Take the first document (used for validation checks)
634
635
  let dcmt = focusedItem;
635
- if (isDcmtFormContext) {
636
+ if (isDcmtFormContext || isMasterDetailContext) {
636
637
  dcmt = dcmtDataRowForCicoStatus;
637
638
  }
638
639
  const { cicoEnabled, checkoutStatus } = getDcmtCicoStatus(dcmt, allUsers, dtd);
@@ -1059,9 +1060,13 @@ export const useDocumentOperations = (props) => {
1059
1060
  disabled: isDisabledForSingleRow() && isDisabledForMultiRow(),
1060
1061
  submenu: [
1061
1062
  addToFavoriteOperation(),
1062
- openFormOperation(),
1063
+ addReplaceFileOperation(),
1064
+ fileCheckMenuItem(),
1065
+ fileConversionsMenuItem(),
1066
+ ...(SDK_Globals.tmSession?.SessionDescr?.appModuleID === AppModules.SURFER ? [createContextualTaskMenuItem()] : []),
1063
1067
  downloadFileMenuItem(),
1064
1068
  downloadXMLAttachmentsMenuItem(),
1069
+ ...(selectedDcmtInfos.length > 0 && isPdfEditorAvailable(dtd, selectedDcmtInfos[0]?.FILEEXT) && onOpenPdfEditorRequest ? [pdfEditorMenuItem(onOpenPdfEditorRequest)] : []),
1065
1070
  ]
1066
1071
  },
1067
1072
  signatureMenuItem(),
@@ -1081,6 +1086,7 @@ export const useDocumentOperations = (props) => {
1081
1086
  ...(inputDcmtFormLayoutMode === LayoutModes.Update ? [addToFavoriteOperation()] : []),
1082
1087
  addReplaceFileOperation(),
1083
1088
  openFormOperation(),
1089
+ deletetionMenuItem(),
1084
1090
  fileCheckMenuItem(),
1085
1091
  fileConversionsMenuItem(),
1086
1092
  ...(SDK_Globals.tmSession?.SessionDescr?.appModuleID === AppModules.SURFER ? [createContextualTaskMenuItem()] : []),
@@ -1090,6 +1096,7 @@ export const useDocumentOperations = (props) => {
1090
1096
  ]
1091
1097
  },
1092
1098
  signatureMenuItem(),
1099
+ checkinMenuItem(),
1093
1100
  ...((inputDcmtFormLayoutMode === LayoutModes.Update) ? [fullTextSearchMenuItem()] : []),
1094
1101
  ];
1095
1102
  };
@@ -1115,10 +1122,7 @@ export const useDocumentOperations = (props) => {
1115
1122
  };
1116
1123
  const renderFloatingBar = (floatingBarContainerRef && floatingBarContainerRef.current && allowFloatingBar && showFloatingBar && deviceType !== DeviceType.MOBILE) ? (_jsx(TMFloatingMenuBar, { containerRef: floatingBarContainerRef, contextMenuItems: operationItems(), isConstrained: true, defaultPosition: { x: 1, y: 88 }, defaultPinnedItems: ['rel-det', 'rel-mst', 'dl'], defaultOrientation: 'horizontal', hasContextMenu: false, pinnedItemIds: pinnedItemIds, onPinChange: setPinnedItemIds })) : null;
1117
1124
  const renderDcmtOperations = (_jsxs(_Fragment, { children: [(showExportForm && searchResult && dataColumns && dataSource && selectedRowKeys) && (_jsx(TMDataGridExportForm, { dataColumns: dataColumns, dataSource: dataSource, selectedRowKeys: selectedRowKeys, onCloseExportForm: () => setShowExportForm(false), searchResult: searchResult })), _jsx(StyledMultiViewPanel, { "$isVisible": isOpenDcmtForm, children: ((isOpenDcmtForm && focusedItem?.TID !== undefined && focusedItem?.DID !== undefined) &&
1118
- _jsx(TMDcmtForm, { isModal: openDcmtFormAsModal || (dcmtFormLayoutMode === LayoutModes.Ark && focusedItem?.DID !== undefined), titleModal: dtd?.name ?? '', TID: focusedItem.TID, DID: focusedItem.DID, allowButtonsRefs: true, layoutMode: dcmtFormLayoutMode, count: visibleItems?.length, itemIndex: visibleItems ? visibleItems.findIndex(o => o.rowIndex === focusedItem?.rowIndex) + 1 : undefined, canNext: canNavigateHandler ? canNavigateHandler('next') : false, canPrev: canNavigateHandler ? canNavigateHandler('prev') : false, onNext: () => onNavigateHandler && onNavigateHandler('next'), onPrev: () => onNavigateHandler && onNavigateHandler('prev'), onClose: () => {
1119
- (false);
1120
- onDcmtFormOpenChange(false, LayoutModes.Update);
1121
- }, onWFOperationCompleted: onWFOperationCompleted, onTaskCreateRequest: onTaskCreateRequest, onSavedAsyncCallback: onSavedAsyncCallback, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, focusedItem?.TID, focusedItem?.DID), showDcmtFormSidebar: showDcmtFormSidebar, datagridUtility: {
1125
+ _jsx(TMDcmtForm, { isModal: openDcmtFormAsModal || (dcmtFormLayoutMode === LayoutModes.Ark && focusedItem?.DID !== undefined), titleModal: dtd?.name ?? '', TID: focusedItem.TID, DID: focusedItem.DID, allowButtonsRefs: true, layoutMode: dcmtFormLayoutMode, count: visibleItems?.length, itemIndex: visibleItems ? visibleItems.findIndex(o => o.rowIndex === focusedItem?.rowIndex) + 1 : undefined, canNext: canNavigateHandler ? canNavigateHandler('next') : false, canPrev: canNavigateHandler ? canNavigateHandler('prev') : false, onNext: () => onNavigateHandler && onNavigateHandler('next'), onPrev: () => onNavigateHandler && onNavigateHandler('prev'), onClose: () => { (false); onDcmtFormOpenChange(false, LayoutModes.Update); }, onWFOperationCompleted: onWFOperationCompleted, onTaskCreateRequest: onTaskCreateRequest, onSavedAsyncCallback: onSavedAsyncCallback, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openFileUploaderPdfEditor: openFileUploaderPdfEditor, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, focusedItem?.TID, focusedItem?.DID), showDcmtFormSidebar: showDcmtFormSidebar, datagridUtility: {
1122
1126
  onRefreshSearchAsyncDatagrid,
1123
1127
  onRefreshDataRowsAsync,
1124
1128
  refreshFocusedDataRowAsync,
@@ -1138,7 +1142,7 @@ export const useDocumentOperations = (props) => {
1138
1142
  setArchiveRelatedDcmtFormTID(undefined);
1139
1143
  setArchiveRelatedDcmtFormMids([]);
1140
1144
  await onRefreshSearchAsyncDatagrid?.();
1141
- }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, showDcmtFormSidebar: showDcmtFormSidebar }), showRelatedDcmtsChooser &&
1145
+ }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, showDcmtFormSidebar: showDcmtFormSidebar, openFileUploaderPdfEditor: openFileUploaderPdfEditor }), showRelatedDcmtsChooser &&
1142
1146
  _jsx(TMChooserForm, { dataSource: relatedDcmtsChooserDataSource, onChoose: async (selectedRelation) => {
1143
1147
  try {
1144
1148
  setShowRelatedDcmtsChooser(false);
@@ -1184,7 +1188,7 @@ export const useDocumentOperations = (props) => {
1184
1188
  updateBatchUpdateForm(false);
1185
1189
  setIsModifiedBatchUpdate(false);
1186
1190
  await onRefreshDataRowsAsync?.();
1187
- }, 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) })] }));
1191
+ }, 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) })] }));
1188
1192
  return {
1189
1193
  operationItems: operationItems(),
1190
1194
  renderFloatingBar,
@@ -1237,6 +1241,7 @@ export const useDocumentOperations = (props) => {
1237
1241
  removeDcmtsFileCache,
1238
1242
  isDcmtFileInCache,
1239
1243
  runOperationAsync,
1244
+ FileSourceDialog,
1240
1245
  },
1241
1246
  relatedDocumentsInfo: {
1242
1247
  // Data
@@ -94,21 +94,27 @@ export function useSaveForm(formMode, id, sfo, validator, onSaved, onStatusChang
94
94
  const saveDataAsync = async (...args) => {
95
95
  if (!formData)
96
96
  return;
97
- let newId = -1;
98
- if (saveCustomAsync)
99
- newId = await saveCustomAsync();
100
- else
101
- newId = await setDataAsync?.(formMode, formData, ...args);
102
- let newData;
103
- if (sfo.loadDataAfterSave)
104
- newData = await loadDataAsync(newId, FormModes.Update);
105
- else {
106
- newData = formData;
107
- newData.id = newId;
108
- setFormData(newData);
109
- setFormDataOrig(newData);
97
+ try {
98
+ TMSpinner.show({ description: `${SDKUI_Localizator.SavingInProgress}...`, backgroundColor: 'transparent' });
99
+ let newId = -1;
100
+ if (saveCustomAsync)
101
+ newId = await saveCustomAsync();
102
+ else
103
+ newId = await setDataAsync?.(formMode, formData, ...args);
104
+ let newData;
105
+ if (sfo.loadDataAfterSave)
106
+ newData = await loadDataAsync(newId, FormModes.Update);
107
+ else {
108
+ newData = formData;
109
+ newData.id = newId;
110
+ setFormData(newData);
111
+ setFormDataOrig(newData);
112
+ }
113
+ onSaved?.(newData);
114
+ }
115
+ finally {
116
+ TMSpinner.hide();
110
117
  }
111
- onSaved?.(newData);
112
118
  };
113
119
  useEffect(() => { id && loadDataAsync(id, formMode); }, [id, formMode]);
114
120
  useEffect(() => {
@@ -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
+ };
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
3
  import { QueryParameterDescriptor } from '@topconsultnpm/sdk-ts';
4
- import { TMModal, TMTextBox, TMButton } from "../components";
4
+ import { TMModal, TMTextBox, TMButton, TMCard, StyledDivHorizontal } from "../components";
5
5
  import { IconApply, IconCloseOutline, SDKUI_Localizator } from "../helper";
6
- import { TMColors } from "../utils/theme";
6
+ import { TMColors, TMMargin } from "../utils/theme";
7
7
  const paramPrefix = "{@QueryParam";
8
8
  export const useQueryParametersDialog = () => {
9
9
  const [promise, setPromise] = useState(null);
@@ -56,15 +56,15 @@ export const useQueryParametersDialog = () => {
56
56
  };
57
57
  const ConfirmQueryParamsDialog = () => {
58
58
  return (open ?
59
- _jsx(TMModal, { title: SDKUI_Localizator.QueryParamBind, height: "max-content", width: "400px", onClose: handleClose, children: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '5px', padding: '10px', height: '100%' }, children: [qdParams.map((qdp, index) => {
60
- return (_jsx(TMTextBox, { placeHolder: `${SDKUI_Localizator.EnterValue} ...`, label: qdp.name, autoFocus: index == 0, value: qdp.value ?? '', onValueChanged: (e) => {
59
+ _jsx(TMModal, { title: SDKUI_Localizator.QueryParamBind, height: `${qdParams.length > 0 ? (qdParams.length * 73) + 73 : 100}px`, width: "400px", onClose: handleClose, children: _jsxs(TMCard, { scrollX: true, height: "100%", children: [qdParams.map((qdp, index) => {
60
+ return (_jsx(TMTextBox, { elementStyle: { marginBottom: TMMargin.smallMargin }, placeHolder: `${SDKUI_Localizator.EnterValue} ...`, label: qdp.name, autoFocus: index == 0, value: qdp.value ?? '', onValueChanged: (e) => {
61
61
  let newQdp = qdParamsOut.find(o => o.id == qdp.id);
62
62
  if (newQdp)
63
63
  newQdp.value = e.target.value;
64
64
  else
65
65
  qdParamsOut.push({ id: qdp.id, name: qdp.name, value: e.target.value });
66
66
  } }, qdp.id));
67
- }), _jsxs("div", { style: { display: 'flex', flexDirection: 'row', gap: '5px', paddingTop: '10px', justifyContent: 'flex-end', alignItems: 'center', height: '50px' }, children: [_jsx(TMButton, { btnStyle: "advanced", showTooltip: false, icon: _jsx(IconApply, {}), caption: "OK", advancedColor: TMColors.tertiary, onClick: handleConfirm }), _jsx(TMButton, { btnStyle: "advanced", showTooltip: false, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Cancel, onClick: handleCancel })] })] }) })
67
+ }), _jsxs(StyledDivHorizontal, { style: { gap: 10, marginBottom: TMMargin.smallMargin, width: '100%', alignItems: 'center' }, children: [_jsx(TMButton, { btnStyle: "advanced", showTooltip: false, icon: _jsx(IconApply, {}), caption: "OK", advancedColor: TMColors.tertiary, onClick: handleConfirm }), _jsx(TMButton, { btnStyle: "advanced", showTooltip: false, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Cancel, onClick: handleCancel })] })] }) })
68
68
  : _jsx(_Fragment, {}));
69
69
  };
70
70
  return [confirmQueryParams, ConfirmQueryParamsDialog];
package/package.json CHANGED
@@ -1,57 +1,57 @@
1
1
  {
2
- "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.21.0-dev1.3",
4
- "description": "",
5
- "scripts": {
6
- "test": "echo \"Error: no test specified\" \u0026\u0026 exit 1",
7
- "clean": "powershell Remove-Item lib/ -recurse",
8
- "copy-files": "copyfiles -u 1 src/assets/*.* src/assets/ImageLibrary/*.* src/assets/thumbnails/*.* src/assets/IconsS4t/*.* src/assets/Metadata/*.* src/css/tm-sdkui.css lib/",
9
- "tm-build": "npm run clean \u0026\u0026 tsc \u0026\u0026 npm run copy-files",
10
- "tm-watch": "tsc -w",
11
- "tm-publish": "npm publish --tag latest",
12
- "tm-publish_wl": "npm publish",
13
- "storybook": "storybook dev -p 6006",
14
- "build-storybook": "storybook build"
15
- },
16
- "author": "TopConsult",
17
- "license": "ISC",
18
- "devDependencies": {
19
- "@chromatic-com/storybook": "^4.1.3",
20
- "@storybook/addon-docs": "^10.1.0",
21
- "@storybook/addon-onboarding": "^10.1.0",
22
- "@storybook/react-vite": "^10.1.0",
23
- "@types/htmlparser2": "^3.10.7",
24
- "@types/node": "^20.2.5",
25
- "@types/react": "^18.3.3",
26
- "@types/react-dom": "^18.3.3",
27
- "copyfiles": "^2.4.1",
28
- "esbuild": "^0.25.0",
29
- "react": "^18.3.1",
30
- "react-dom": "^18.3.1",
31
- "storybook": "^10.1.0",
32
- "typescript": "^5.9.3",
33
- "vite": "^6.1.1"
34
- },
35
- "main": "dist/cjs/index.js",
36
- "types": "./index.d.ts",
37
- "module": "lib/esm/index.js",
38
- "files": [
39
- "dist",
40
- "lib"
41
- ],
42
- "dependencies": {
43
- "react-router-dom": "^6.15.0",
44
- "react-pdf": "^10.3.0",
45
- "htmlparser2": "^10.0.0",
46
- "buffer": "^6.0.3",
47
- "@topconsultnpm/sdk-ts": "6.20.0",
48
- "exceljs": "^4.4.0",
49
- "devextreme": "25.2.4",
50
- "styled-components": "^6.1.1",
51
- "pdfjs-dist": "5.4.296",
52
- "devextreme-react": "25.2.4"
53
- },
54
- "overrides": {
55
- "esbuild": "^0.25.0"
56
- }
2
+ "name": "@topconsultnpm/sdkui-react",
3
+ "version": "6.21.0-dev1.30",
4
+ "description": "",
5
+ "scripts": {
6
+ "test": "echo \"Error: no test specified\" && exit 1",
7
+ "clean": "powershell Remove-Item lib/ -recurse",
8
+ "copy-files": "copyfiles -u 1 src/assets/*.* src/assets/ImageLibrary/*.* src/assets/thumbnails/*.* src/assets/IconsS4t/*.* src/assets/Metadata/*.* src/css/tm-sdkui.css lib/",
9
+ "tm-build": "npm run clean && tsc && npm run copy-files",
10
+ "tm-watch": "tsc -w",
11
+ "tm-publish": "npm publish --tag latest",
12
+ "tm-publish_wl": "npm publish",
13
+ "storybook": "storybook dev -p 6006",
14
+ "build-storybook": "storybook build"
15
+ },
16
+ "author": "TopConsult",
17
+ "license": "ISC",
18
+ "devDependencies": {
19
+ "@chromatic-com/storybook": "^4.1.3",
20
+ "@storybook/addon-docs": "^10.1.0",
21
+ "@storybook/addon-onboarding": "^10.1.0",
22
+ "@storybook/react-vite": "^10.1.0",
23
+ "@types/htmlparser2": "^3.10.7",
24
+ "@types/node": "^20.2.5",
25
+ "@types/react": "^18.3.3",
26
+ "@types/react-dom": "^18.3.3",
27
+ "copyfiles": "^2.4.1",
28
+ "esbuild": "^0.25.0",
29
+ "react": "^18.3.1",
30
+ "react-dom": "^18.3.1",
31
+ "storybook": "^10.1.0",
32
+ "typescript": "^5.9.3",
33
+ "vite": "^6.1.1"
34
+ },
35
+ "main": "dist/cjs/index.js",
36
+ "types": "./index.d.ts",
37
+ "module": "lib/esm/index.js",
38
+ "files": [
39
+ "dist",
40
+ "lib"
41
+ ],
42
+ "dependencies": {
43
+ "@topconsultnpm/sdk-ts": "6.21.0-dev1.4",
44
+ "buffer": "^6.0.3",
45
+ "devextreme": "^25.2.6",
46
+ "devextreme-react": "^25.2.6",
47
+ "exceljs": "^4.4.0",
48
+ "htmlparser2": "^10.0.0",
49
+ "pdfjs-dist": "5.4.296",
50
+ "react-pdf": "^10.3.0",
51
+ "react-router-dom": "^6.15.0",
52
+ "styled-components": "^6.1.1"
53
+ },
54
+ "overrides": {
55
+ "esbuild": "^0.25.0"
56
+ }
57
57
  }