@topconsultnpm/sdkui-react 6.22.0-dev3.24 → 6.22.0-dev3.25

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 (47) hide show
  1. package/lib/components/base/TMAlert.js +6 -8
  2. package/lib/components/base/TMAreaManager.js +53 -55
  3. package/lib/components/base/TMCustomButton.js +39 -48
  4. package/lib/components/base/TMTreeView.js +14 -0
  5. package/lib/components/base/waitPanel/TMWaitPanelConfirm.d.ts +12 -0
  6. package/lib/components/base/waitPanel/TMWaitPanelConfirm.js +185 -0
  7. package/lib/components/base/waitPanel/TMWaitPanelManager.d.ts +169 -0
  8. package/lib/components/base/waitPanel/TMWaitPanelManager.js +320 -0
  9. package/lib/components/base/waitPanel/TMWaitPanelView.d.ts +53 -0
  10. package/lib/components/base/waitPanel/TMWaitPanelView.js +274 -0
  11. package/lib/components/base/waitPanel/index.d.ts +1 -0
  12. package/lib/components/base/waitPanel/index.js +1 -0
  13. package/lib/components/choosers/TMPathChooser.js +17 -34
  14. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +2 -2
  15. package/lib/components/features/documents/TMBatchUpdateForm.js +3 -4
  16. package/lib/components/features/documents/TMCopyToFolderForm.js +32 -35
  17. package/lib/components/features/documents/TMDcmtForm.js +48 -60
  18. package/lib/components/features/documents/TMDcmtIcon.d.ts +1 -3
  19. package/lib/components/features/documents/TMDcmtIcon.js +3 -5
  20. package/lib/components/features/documents/TMDcmtPreview.js +5 -3
  21. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
  22. package/lib/components/features/documents/TMMasterDetailDcmts.js +45 -147
  23. package/lib/components/features/documents/TMMergeToPdfForm.js +48 -47
  24. package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +14 -15
  25. package/lib/components/features/documents/TMRelationViewer.d.ts +3 -14
  26. package/lib/components/features/documents/TMRelationViewer.js +115 -79
  27. package/lib/components/features/search/TMSearchResult.js +6 -8
  28. package/lib/components/features/search/TMViewHistoryDcmt.js +14 -25
  29. package/lib/components/features/tasks/TMTasksView.js +91 -90
  30. package/lib/components/features/wg/TMWGsCopyMoveForm.js +91 -91
  31. package/lib/components/grids/TMBlogsPost.js +92 -96
  32. package/lib/components/index.d.ts +2 -0
  33. package/lib/components/index.js +2 -0
  34. package/lib/components/pages/TMPage.js +29 -31
  35. package/lib/helper/SDKUI_Localizator.d.ts +7 -0
  36. package/lib/helper/SDKUI_Localizator.js +70 -0
  37. package/lib/helper/ZipManager.d.ts +1 -1
  38. package/lib/helper/ZipManager.js +2 -1
  39. package/lib/hooks/useCheckInOutOperations.d.ts +0 -6
  40. package/lib/hooks/useCheckInOutOperations.js +14 -34
  41. package/lib/hooks/useDcmtOperations.d.ts +3 -12
  42. package/lib/hooks/useDcmtOperations.js +130 -160
  43. package/lib/hooks/useDocumentOperations.js +12 -23
  44. package/lib/hooks/useMultiMasterDetailDcmts.d.ts +0 -15
  45. package/lib/hooks/useMultiMasterDetailDcmts.js +62 -65
  46. package/lib/hooks/useWorkflowApprove.js +33 -17
  47. package/package.json +1 -1
@@ -13,7 +13,8 @@ import ShowAlert from '../../base/TMAlert';
13
13
  import TMButton from '../../base/TMButton';
14
14
  import { TMExceptionBoxManager, TMMessageBoxManager, ButtonNames } from '../../base/TMPopUp';
15
15
  import TMSpinner, { Spinner } from '../../base/TMSpinner';
16
- import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
16
+ import TMLayoutContainer from '../../base/TMLayout';
17
+ import TMWaitPanelManager from '../../base/waitPanel/TMWaitPanelManager';
17
18
  import TMDistinctValues from '../../choosers/TMDistinctValues';
18
19
  import TMFormulaEditor, { FormulaDescriptor, FormulaHelper, FormulaTargets } from '../../editors/TMFormulaEditor';
19
20
  import TMMetadataValues, { AdvancedMenuButtons } from '../../editors/TMMetadataValues';
@@ -64,17 +65,6 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
64
65
  const { onRefreshSearchAsyncDatagrid, onRefreshBlogDatagrid, onRefreshPreviewDatagrid } = datagridUtility || {};
65
66
  const floatingBarContainerRef = useRef(null);
66
67
  const [id, setID] = useState('');
67
- const [showWaitPanelLocal, setShowWaitPanelLocal] = useState(false);
68
- const [waitPanelTitleLocal, setWaitPanelTitleLocal] = useState('');
69
- const [showPrimaryLocal, setShowPrimaryLocal] = useState(false);
70
- const [waitPanelTextPrimaryLocal, setWaitPanelTextPrimaryLocal] = useState('');
71
- const [waitPanelValuePrimaryLocal, setWaitPanelValuePrimaryLocal] = useState(0);
72
- const [waitPanelMaxValuePrimaryLocal, setWaitPanelMaxValuePrimaryLocal] = useState(0);
73
- const [showSecondaryLocal, setShowSecondaryLocal] = useState(false);
74
- const [waitPanelTextSecondaryLocal, setWaitPanelTextSecondaryLocal] = useState('');
75
- const [waitPanelValueSecondaryLocal, setWaitPanelValueSecondaryLocal] = useState(0);
76
- const [waitPanelMaxValueSecondaryLocal, setWaitPanelMaxValueSecondaryLocal] = useState(0);
77
- const [useWaitPanelLocalState, setUseWaitPanelLocalState] = useState(false);
78
68
  const [formData, setFormData] = useState([]);
79
69
  const [formDataOrig, setFormDataOrig] = useState([]);
80
70
  const [validationItems, setValidationItems] = useState([]);
@@ -469,7 +459,7 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
469
459
  openTaskFormHandler,
470
460
  },
471
461
  });
472
- const { handleSignApprove, checkoutInfo: { showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, }, dcmtOperations: { abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, }, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, canArchiveDetailRelation, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
462
+ const { handleSignApprove, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, canArchiveDetailRelation, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
473
463
  useEffect(() => {
474
464
  const fetchAllUsers = async () => {
475
465
  const users = await UserListCacheService.GetAllAsync();
@@ -970,15 +960,15 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
970
960
  }
971
961
  }, [DID, TID, getSpecificChangedKeysWithValues, refreshMetadataAsync, onSavedAsyncCallback, onClose]);
972
962
  const handleArchiveCompleted = useCallback(async () => {
973
- let firstBlock = true;
974
- let maxFileSize = 0;
975
963
  let operationTitle = SDKUI_Localizator.Archiving;
976
- setUseWaitPanelLocalState(true);
977
- setShowWaitPanelLocal(true);
978
- setShowPrimaryLocal(false);
979
- setShowSecondaryLocal(true);
980
- setWaitPanelTitleLocal(operationTitle);
981
964
  abortControllerLocal = new AbortController();
965
+ // Interrompi solo sopra il megabyte: sotto, l'upload finisce prima che serva.
966
+ const panel = TMWaitPanelManager.show({
967
+ title: operationTitle,
968
+ showCounters: false,
969
+ cancelable: (dcmtFileRef.current?.size ?? 0) >= 1000000,
970
+ onAbort: () => abortControllerLocal.abort(),
971
+ });
982
972
  const ae = new ArchiveEngineByID(SDK_Globals.tmSession);
983
973
  ae.TID = TID;
984
974
  ae.Metadata_ClearAll();
@@ -1014,42 +1004,41 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
1014
1004
  sharedDcmt.did = sharedSourceDID;
1015
1005
  ae.SharedDcmt = sharedDcmt;
1016
1006
  }
1007
+ // Fase 1: upload del file, la barra segue i byte.
1017
1008
  let newDID = await ae.ArchiveAsync(abortControllerLocal.signal, (pd) => {
1018
- if (firstBlock) {
1019
- maxFileSize = pd.ProgressBarMaximum ?? 0;
1020
- setWaitPanelMaxValueSecondaryLocal(maxFileSize);
1021
- firstBlock = false;
1022
- }
1023
- setWaitPanelValueSecondaryLocal(pd.ProgressBarValue);
1024
- setWaitPanelTextSecondaryLocal(`${SDKUI_Localizator.Archiving}... ${Globalization.getNumberDisplayValue(pd.ProgressBarValue, true)} / ${Globalization.getNumberDisplayValue(maxFileSize, true)}`);
1009
+ const maxFileSize = pd.ProgressBarMaximum ?? 0;
1025
1010
  if (pd.ProgressBarValue === pd.ProgressBarMaximum) {
1026
- // Cambia subito il titolo alla fase 2 quando l'upload termina
1027
- // e mostra la progress bar primaria con valore iniziale 20%
1028
- setWaitPanelTitleLocal(SDKUI_Localizator.ArchivingCompletionInProgress);
1029
- setShowSecondaryLocal(false);
1030
- setShowPrimaryLocal(true);
1031
- setWaitPanelMaxValuePrimaryLocal(3);
1032
- setWaitPanelValuePrimaryLocal(0.6); // 20% di 3
1033
- setWaitPanelTextPrimaryLocal(SDKUI_Localizator.ArchivingCompletionInProgress);
1034
- firstBlock = true;
1011
+ // Upload finito: fase 2 sulla stessa barra, tre passi, gia' al 20%.
1012
+ panel.update({
1013
+ title: SDKUI_Localizator.ArchivingCompletionInProgress,
1014
+ subtitle: SDKUI_Localizator.ArchivingCompletionInProgress,
1015
+ value: 0.6,
1016
+ max: 3,
1017
+ });
1018
+ return;
1035
1019
  }
1020
+ panel.update({
1021
+ value: pd.ProgressBarValue,
1022
+ max: maxFileSize,
1023
+ subtitle: `${SDKUI_Localizator.Archiving}... ${Globalization.getNumberDisplayValue(pd.ProgressBarValue, true)} / ${Globalization.getNumberDisplayValue(maxFileSize, true)}`,
1024
+ });
1036
1025
  });
1037
1026
  // Aggiorna lo stato locale immediatamente dopo il salvataggio riuscito
1038
1027
  // Questo garantisce che isModified diventi false anche se il reload fallisce
1039
1028
  const savedFormData = structuredClone(formDataRef.current);
1040
1029
  setFormDataOrig(savedFormData);
1041
1030
  formDataOrigRef.current = savedFormData;
1042
- // Fase 2: Completamento archiviazione (la progress bar primaria è già visibile dal callback)
1031
+ // Fase 2: Completamento archiviazione (la barra a tre passi è già visibile dal callback)
1043
1032
  // Imposta il titolo anche qui per sicurezza, nel caso il callback non venga eseguito
1044
- setWaitPanelTitleLocal(SDKUI_Localizator.ArchivingCompletionInProgress);
1033
+ panel.update({ title: SDKUI_Localizator.ArchivingCompletionInProgress, max: 3 });
1045
1034
  // Step 1/3: Aggiornamento griglia di ricerca
1046
- setWaitPanelValuePrimaryLocal(1);
1035
+ panel.setValue(1);
1047
1036
  await onRefreshSearchAsyncDatagrid?.();
1048
1037
  // Step 2/3: Callback di salvataggio
1049
- setWaitPanelValuePrimaryLocal(2);
1038
+ panel.setValue(2);
1050
1039
  await onSavedAsyncCallback?.(ae.TID, newDID);
1051
1040
  // Step 3/3: Aggiornamento lista metadati
1052
- setWaitPanelValuePrimaryLocal(3);
1041
+ panel.setValue(3);
1053
1042
  // Usa fromDTDRef.current invece di fromDTD per evitare stale closure,
1054
1043
  // garantendo di avere il descrittore del tipo documento corrente.
1055
1044
  await setMetadataList(fromDTDRef.current?.metadata ?? [], undefined, true, newDID);
@@ -1072,8 +1061,7 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
1072
1061
  return undefined;
1073
1062
  }
1074
1063
  finally {
1075
- setShowWaitPanelLocal(false);
1076
- setUseWaitPanelLocalState(false);
1064
+ panel.close();
1077
1065
  }
1078
1066
  }, [TID, connectorFileSave, onSavedAsyncCallback, onSaveRecents, onClose, DID, setMetadataList, handleReset, layoutMode, isSharedDcmt]);
1079
1067
  // Messaggio di conferma dell'archiviazione in base al vincolo del tipo documento (ArchiveConstraints).
@@ -1678,23 +1666,23 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
1678
1666
  height: '100%',
1679
1667
  position: 'relative',
1680
1668
  overflow: 'hidden'
1681
- }, children: [_jsxs("div", { style: { width: '100%', height: '100%', display: isOpenDetails || isOpenMaster ? 'none' : 'flex' }, children: [isNavigating && _jsx(Spinner, { description: SDKUI_Localizator.Loading, flat: false }), (fromDTD) && _jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: useWaitPanelLocalState ? showWaitPanelLocal : showWaitPanel, showWaitPanelPrimary: useWaitPanelLocalState ? showPrimaryLocal : showPrimary, showWaitPanelSecondary: useWaitPanelLocalState ? showSecondaryLocal : showSecondary, waitPanelTitle: useWaitPanelLocalState ? waitPanelTitleLocal : waitPanelTitle, waitPanelTextPrimary: useWaitPanelLocalState ? waitPanelTextPrimaryLocal : waitPanelTextPrimary, waitPanelValuePrimary: useWaitPanelLocalState ? waitPanelValuePrimaryLocal : waitPanelValuePrimary, waitPanelMaxValuePrimary: useWaitPanelLocalState ? waitPanelMaxValuePrimaryLocal : waitPanelMaxValuePrimary, waitPanelTextSecondary: useWaitPanelLocalState ? waitPanelTextSecondaryLocal : waitPanelTextSecondary, waitPanelValueSecondary: useWaitPanelLocalState ? waitPanelValueSecondaryLocal : waitPanelValueSecondary, waitPanelMaxValueSecondary: useWaitPanelLocalState ? waitPanelMaxValueSecondaryLocal : waitPanelMaxValueSecondary, isCancelable: useWaitPanelLocalState ? dcmtFile ? dcmtFile.size >= 1000000 : false : true, abortController: useWaitPanelLocalState ? abortControllerLocal : abortController, children: _jsxs(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showCicoWaitPanel, showWaitPanelPrimary: showCicoPrimaryProgress, waitPanelTitle: cicoWaitPanelTitle, waitPanelTextPrimary: cicoPrimaryProgressText, waitPanelValuePrimary: cicoPrimaryProgressValue, waitPanelMaxValuePrimary: cicoPrimaryProgressMax, isCancelable: true, abortController: abortControllerLocal, children: [(groupId && groupId.length > 0)
1682
- ? _jsxs(_Fragment, { children: [_jsx(PanelDisabledStateHandler, { isWFDisabled: isWFDisabled, isSysMetadataDisabled: isSysMetadataDisabled, isBoardDisabled: isBoardDisabled, isDcmtTasksDisabled: isDcmtTasksDisabled, isPreviewDisabled: isPreviewDisabled }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })] })
1683
- : _jsxs(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: defaultPanelDimensions, initialDimensions: defaultPanelDimensions, initialMobilePanelId: 'tmDcmtForm', isPersistenceEnabled: !isMobile && layoutMode !== LayoutModes.Ark ? hasSavedLayout() : false, persistPanelStates: !isMobile && layoutMode !== LayoutModes.Ark ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: layoutMode !== LayoutModes.Ark ? getPersistedPanelStates() : undefined, children: [_jsx(PanelDisabledStateHandler, { isWFDisabled: isWFDisabled, isSysMetadataDisabled: isSysMetadataDisabled, isBoardDisabled: isBoardDisabled, isDcmtTasksDisabled: isDcmtTasksDisabled, isPreviewDisabled: isPreviewDisabled, persistedWFVisible: persistedWFVisibleRef.current }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })] }), isOpenDistinctValues &&
1684
- _jsx(TMDistinctValues, { tid: TID, mid: focusedMetadataValue?.mid, isModal: true, showHeader: false, layoutMode: layoutMode, onClosePanelCallback: () => setIsOpenDistinctValues(false), onSelectionChanged: (e) => {
1685
- if (!e)
1686
- return;
1687
- setFormData((prevItems) => prevItems.map((item) => item.tid == e.tid && item.mid === e.mid ? { ...item, value: e.newValue } : item));
1688
- } }), isOpenFormulaEditor &&
1689
- _jsx(TMFormulaEditor, { isModal: true, formMode: FormModes.Update, inputData: getFormula(), showBack: false, onClose: () => setIsOpenFormulaEditor(false), onApplied: (newFormula) => {
1690
- setFormData((prevItems) => prevItems.map((item) => item.tid == newFormula.tid && item.mid === newFormula.mid ? { ...item, value: FormulaHelper.addFormulaTag(newFormula.expression), isSelected: true, isEditable: true } : item));
1691
- setFocusedMetadataValue(prevState => ({
1692
- ...prevState,
1693
- isSelected: true,
1694
- isEditable: true,
1695
- value: FormulaHelper.addFormulaTag(newFormula.expression)
1696
- }));
1697
- } }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }) }), _jsx(TMToppyDraggableHelpCenter, { isVisible: isToppyVisible, content: _jsx(TMDcmtFormActionButtons, { showToppyForApprove: showToppyForApprove, workItems: workItems, caseFlowWorkItems: showToppyForCaseFlow ? caseFlowWorkItems : [], onCompleteCaseFlowWorkItem: completeCaseFlowWorkItem, onRejectCaseFlowWorkItem: rejectCaseFlowWorkItem, deviceType: deviceType, isMobile: isMobile, handleSignApprove: handleSignApprove, updateShowApprovePopup: updateShowApprovePopup, updateShowRejectPopup: updateShowRejectPopup, updateShowReAssignPopup: updateShowReAssignPopup, updateShowMoreInfoPopup: updateShowMoreInfoPopup, fromDTD: fromDTD, showToppyForCompleteMoreInfo: showToppyForCompleteMoreInfo, moreInfoTasks: moreInfoTasks, setShowCommentForm: setShowCommentForm, showToppyForReferences: showToppyForReferences, dcmtReferences: dcmtReferences, referenceActionMap: referenceActionMap, handleNavigateToReference: handleNavigateToReference, setShowMoreInfoTaskPopup: setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask: setShowMoreInfoTaskTask }) })] }), (showCommentForm && TID && DID) &&
1669
+ }, children: [_jsxs("div", { style: { width: '100%', height: '100%', display: isOpenDetails || isOpenMaster ? 'none' : 'flex' }, children: [isNavigating && _jsx(Spinner, { description: SDKUI_Localizator.Loading, flat: false }), (fromDTD) && _jsxs(TMLayoutContainer, { direction: 'vertical', children: [(groupId && groupId.length > 0)
1670
+ ? _jsxs(_Fragment, { children: [_jsx(PanelDisabledStateHandler, { isWFDisabled: isWFDisabled, isSysMetadataDisabled: isSysMetadataDisabled, isBoardDisabled: isBoardDisabled, isDcmtTasksDisabled: isDcmtTasksDisabled, isPreviewDisabled: isPreviewDisabled }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })] })
1671
+ : _jsxs(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: defaultPanelDimensions, initialDimensions: defaultPanelDimensions, initialMobilePanelId: 'tmDcmtForm', isPersistenceEnabled: !isMobile && layoutMode !== LayoutModes.Ark ? hasSavedLayout() : false, persistPanelStates: !isMobile && layoutMode !== LayoutModes.Ark ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: layoutMode !== LayoutModes.Ark ? getPersistedPanelStates() : undefined, children: [_jsx(PanelDisabledStateHandler, { isWFDisabled: isWFDisabled, isSysMetadataDisabled: isSysMetadataDisabled, isBoardDisabled: isBoardDisabled, isDcmtTasksDisabled: isDcmtTasksDisabled, isPreviewDisabled: isPreviewDisabled, persistedWFVisible: persistedWFVisibleRef.current }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })] }), isOpenDistinctValues &&
1672
+ _jsx(TMDistinctValues, { tid: TID, mid: focusedMetadataValue?.mid, isModal: true, showHeader: false, layoutMode: layoutMode, onClosePanelCallback: () => setIsOpenDistinctValues(false), onSelectionChanged: (e) => {
1673
+ if (!e)
1674
+ return;
1675
+ setFormData((prevItems) => prevItems.map((item) => item.tid == e.tid && item.mid === e.mid ? { ...item, value: e.newValue } : item));
1676
+ } }), isOpenFormulaEditor &&
1677
+ _jsx(TMFormulaEditor, { isModal: true, formMode: FormModes.Update, inputData: getFormula(), showBack: false, onClose: () => setIsOpenFormulaEditor(false), onApplied: (newFormula) => {
1678
+ setFormData((prevItems) => prevItems.map((item) => item.tid == newFormula.tid && item.mid === newFormula.mid ? { ...item, value: FormulaHelper.addFormulaTag(newFormula.expression), isSelected: true, isEditable: true } : item));
1679
+ setFocusedMetadataValue(prevState => ({
1680
+ ...prevState,
1681
+ isSelected: true,
1682
+ isEditable: true,
1683
+ value: FormulaHelper.addFormulaTag(newFormula.expression)
1684
+ }));
1685
+ } }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }), _jsx(TMToppyDraggableHelpCenter, { isVisible: isToppyVisible, content: _jsx(TMDcmtFormActionButtons, { showToppyForApprove: showToppyForApprove, workItems: workItems, caseFlowWorkItems: showToppyForCaseFlow ? caseFlowWorkItems : [], onCompleteCaseFlowWorkItem: completeCaseFlowWorkItem, onRejectCaseFlowWorkItem: rejectCaseFlowWorkItem, deviceType: deviceType, isMobile: isMobile, handleSignApprove: handleSignApprove, updateShowApprovePopup: updateShowApprovePopup, updateShowRejectPopup: updateShowRejectPopup, updateShowReAssignPopup: updateShowReAssignPopup, updateShowMoreInfoPopup: updateShowMoreInfoPopup, fromDTD: fromDTD, showToppyForCompleteMoreInfo: showToppyForCompleteMoreInfo, moreInfoTasks: moreInfoTasks, setShowCommentForm: setShowCommentForm, showToppyForReferences: showToppyForReferences, dcmtReferences: dcmtReferences, referenceActionMap: referenceActionMap, handleNavigateToReference: handleNavigateToReference, setShowMoreInfoTaskPopup: setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask: setShowMoreInfoTaskTask }) })] }), (showCommentForm && TID && DID) &&
1698
1686
  _jsx(TMBlogCommentForm, { maxLength: 500, context: blogCommentFormContext, onClose: handleBlogCommentFormClose, onCustomSave: onBlogCommentFormCustomSave, participants: emptyParticipants, showAttachmentsSection: false, allArchivedDocumentsFileItems: emptyArchivedDocumentsFileItems })] }), renderDcmtOperations, renderFloatingBar] }));
1699
1687
  };
1700
1688
  return (_jsxs("div", { style: (isModal && onClose) ? { width: 0, height: 0 } : { width: '100%', height: '100%' }, children: [(isModal && onClose)
@@ -14,8 +14,6 @@ interface ITMDcmtIconProps {
14
14
  tooltipContent?: JSX.Element | string;
15
15
  openInOffice?: (selectedDcmtsOrFocused: Array<DcmtInfo>) => Promise<void>;
16
16
  onDownloadDcmtsAsync?: (inputDcmts: DcmtInfo[] | undefined, downloadType: DownloadTypes, downloadMode: DownloadModes, onFileDownloaded?: (dcmtFile: File | undefined) => void, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>) => Promise<void>;
17
- /** Se true, renderizza il wait panel nel body tramite Portal (centrato a schermo intero) */
18
- usePortal?: boolean;
19
17
  }
20
- declare const TMDcmtIcon: ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode, tooltipContent, openInOffice, onDownloadDcmtsAsync, usePortal }: ITMDcmtIconProps) => React.JSX.Element;
18
+ declare const TMDcmtIcon: ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode, tooltipContent, openInOffice, onDownloadDcmtsAsync }: ITMDcmtIconProps) => React.JSX.Element;
21
19
  export default TMDcmtIcon;
@@ -1,13 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useMemo } from 'react';
3
- import { createPortal } from 'react-dom';
4
3
  import styled from 'styled-components';
5
4
  import { getFileIcon } from '../../../helper';
6
5
  import TMTooltip from '../../base/TMTooltip';
7
6
  import { DownloadTypes } from '../../../ts';
8
7
  import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
9
8
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
10
- import { TMWaitPanel } from '../../base/TMWaitPanel';
11
9
  const StyledCellRenderDcmtIcon = styled.div `
12
10
  display: flex;
13
11
  flex-direction: row;
@@ -16,8 +14,8 @@ const StyledCellRenderDcmtIcon = styled.div `
16
14
  overflow: visible;
17
15
  position: relative;
18
16
  `;
19
- const TMDcmtIcon = ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode = "none", tooltipContent, openInOffice, onDownloadDcmtsAsync, usePortal = false }) => {
20
- const { downloadDcmtsAsync, showWaitPanel, waitPanelTitle, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, abortController } = useDcmtOperations();
17
+ const TMDcmtIcon = ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode = "none", tooltipContent, openInOffice, onDownloadDcmtsAsync }) => {
18
+ const { downloadDcmtsAsync } = useDcmtOperations();
21
19
  const deviceType = useDeviceType();
22
20
  let isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
23
21
  const icon = useMemo(() => {
@@ -59,7 +57,7 @@ const TMDcmtIcon = ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isS
59
57
  : deviceType === DeviceType.MOBILE
60
58
  ? { onClick: handleDownloadAction } // Su mobile, un singolo click sull'icona avvia il download
61
59
  : { onDoubleClick: handleDownloadAction } // Su desktop, un doppio click sull'icona avvia il download
62
- ), children: [icon, isLexProt == 1 && _jsx("div", { style: { position: 'absolute', left: '-7px', top: isShared ? undefined : '2px' }, children: _jsx(TMTooltip, { content: "Protezione LEX", children: _jsx(IconLexProtLock, { color: 'blue', fontSize: 13 }) }) }), isShared == 1 && _jsx("div", { style: { position: 'absolute', top: '-7px', left: '-5px' }, children: _jsx(TMTooltip, { content: "Documento condiviso", children: _jsx(IconShared, { fontSize: 16 }) }) }), isSigned == 1 && _jsx("div", { style: { position: 'absolute', bottom: '-4px', right: '-7px' }, children: _jsx(TMTooltip, { content: "Documento firmato", children: _jsx(IconSignature, { fontSize: 28 }) }) }), showWaitPanel && (usePortal ? createPortal(_jsx(TMWaitPanel, { title: waitPanelTitle, showSecondary: showSecondary, textSecondary: waitPanelTextSecondary, valueSecondary: waitPanelValueSecondary, maxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); }, useHighZIndex: true }), document.body) : (_jsx(TMWaitPanel, { title: waitPanelTitle, showSecondary: showSecondary, textSecondary: waitPanelTextSecondary, valueSecondary: waitPanelValueSecondary, maxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); } })))] }));
60
+ ), children: [icon, isLexProt == 1 && _jsx("div", { style: { position: 'absolute', left: '-7px', top: isShared ? undefined : '2px' }, children: _jsx(TMTooltip, { content: "Protezione LEX", children: _jsx(IconLexProtLock, { color: 'blue', fontSize: 13 }) }) }), isShared == 1 && _jsx("div", { style: { position: 'absolute', top: '-7px', left: '-5px' }, children: _jsx(TMTooltip, { content: "Documento condiviso", children: _jsx(IconShared, { fontSize: 16 }) }) }), isSigned == 1 && _jsx("div", { style: { position: 'absolute', bottom: '-4px', right: '-7px' }, children: _jsx(TMTooltip, { content: "Documento firmato", children: _jsx(IconSignature, { fontSize: 28 }) }) })] }));
63
61
  };
64
62
  export default TMDcmtIcon;
65
63
  function IconLexProtLock(props) {
@@ -9,7 +9,7 @@ import { TMColors } from '../../../utils/theme';
9
9
  import ShowAlert from '../../base/TMAlert';
10
10
  import TMButton from '../../base/TMButton';
11
11
  import { TMExceptionBoxManager } from '../../base/TMPopUp';
12
- import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
12
+ import TMLayoutContainer from '../../base/TMLayout';
13
13
  import { TMSaveFormButtonPrevious, TMSaveFormButtonNext } from '../../forms/TMSaveForm';
14
14
  import { StyledAnimatedComponentOpacity } from '../../base/Styled';
15
15
  import TMPanel from '../../base/TMPanel';
@@ -28,7 +28,7 @@ const TMDcmtPreview = ({ dcmtData, isResizingActive, isVisible, canNext, canPrev
28
28
  const [isFromCache, setIsFromCache] = useState(false);
29
29
  const [error, setError] = useState('');
30
30
  const [isAbortError, setIsAbortError] = useState(false);
31
- const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, getDcmtFileAsync, clearDcmtsFileCache, removeDcmtsFileCache, isDcmtFileInCache } = useDcmtOperations();
31
+ const { getDcmtFileAsync, clearDcmtsFileCache, removeDcmtsFileCache, isDcmtFileInCache } = useDcmtOperations();
32
32
  const isBasketMode = !!(dcmtData?.btid !== undefined && dcmtData?.bid !== undefined && dcmtData?.bfid !== undefined);
33
33
  const getCacheKey = () => {
34
34
  if (!dcmtData)
@@ -80,6 +80,8 @@ const TMDcmtPreview = ({ dcmtData, isResizingActive, isVisible, canNext, canPrev
80
80
  setLastLoadedDid(currentCacheKey);
81
81
  }, [dcmtData?.tid, dcmtData?.did, isVisible, hasLoadedDataOnce, lastLoadedDid]);
82
82
  const loadBasketFile = async () => {
83
+ // Il recupero dal basket non passa da useDcmtOperations: ha il suo AbortController.
84
+ const abortController = new AbortController();
83
85
  try {
84
86
  // Check cache first
85
87
  if (dcmtsFileCachePreview.has(cacheKey)) {
@@ -187,7 +189,7 @@ const TMDcmtPreview = ({ dcmtData, isResizingActive, isVisible, canNext, canPrev
187
189
  { icon: _jsx(IconCloseCircle, {}), name: SDKUI_Localizator.RemoveFromCache, onClick: () => { removeDcmtsFileCache(cacheKey); setIsFromCache(false); } },
188
190
  { icon: _jsx(IconClear, {}), name: SDKUI_Localizator.ClearCache, onClick: () => { clearDcmtsFileCache(); setIsFromCache(false); } },
189
191
  ], [cacheKey, removeDcmtsFileCache, clearDcmtsFileCache, setIsFromCache]);
190
- return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsx(TMPanel, { padding: '0', title: titleHandler(), onClose: onClosePanel, onBack: onBack, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, toolbar: _jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: '10px' }, children: [onPrev && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), onNext && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(StyledHeaderIcon, { $color: TMColors.primaryColor, children: _jsx(ContextMenu, { items: cacheMenuItems, trigger: "left", children: _jsx(IconMenuVertical, {}) }) }), _jsx(StyledHeaderIcon, { onClick: reOpenDcmt, $color: TMColors.primaryColor, children: _jsx(TMTooltip, { content: SDKUI_Localizator.ReopenDocument, children: _jsx(IconRefresh, {}) }) })] }), children: error
192
+ return (_jsx(TMLayoutContainer, { direction: 'vertical', children: _jsx(TMPanel, { padding: '0', title: titleHandler(), onClose: onClosePanel, onBack: onBack, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, toolbar: _jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: '10px' }, children: [onPrev && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), onNext && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(StyledHeaderIcon, { $color: TMColors.primaryColor, children: _jsx(ContextMenu, { items: cacheMenuItems, trigger: "left", children: _jsx(IconMenuVertical, {}) }) }), _jsx(StyledHeaderIcon, { onClick: reOpenDcmt, $color: TMColors.primaryColor, children: _jsx(TMTooltip, { content: SDKUI_Localizator.ReopenDocument, children: _jsx(IconRefresh, {}) }) })] }), children: error
191
193
  ? _jsx(ErrorContent, { error: error, isAbortError: isAbortError, onRetry: reOpenDcmt })
192
194
  : renderedPreview(dcmtData?.tid, dcmtData?.did, dcmtData?.fileExt, dcmtData?.fileSize, dcmtData?.fileCount, extensionHandler(dcmtData?.fileExt), showPreview, isResizingActive, () => { isBasketMode ? loadBasketFile() : loadDocumentWithCache(); setShowPreview(true); }, dcmtBlob, isBasketMode) }) }));
193
195
  };
@@ -22,6 +22,8 @@ interface ITMMasterDetailDcmtsProps extends DeviceContextProps {
22
22
  onNext?: () => void;
23
23
  onPrev?: () => void;
24
24
  onBack?: () => void;
25
+ /** Invocato quando il calcolo iniziale delle correlazioni è finito */
26
+ onFirstLoadCompleted?: () => void;
25
27
  appendMasterDcmts?: (tid: number | undefined, did: number | undefined) => void;
26
28
  onTaskCreateRequest?: (taskContext: TaskContext, onTaskCreated?: (task?: TaskDescriptor) => void) => void;
27
29
  onRefreshAfterAddDcmtToFavs?: () => void;
@@ -14,12 +14,13 @@ import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/p
14
14
  import TMSearchResult from '../search/TMSearchResult';
15
15
  import TMDcmtForm from './TMDcmtForm';
16
16
  import { TMNothingToShow } from './TMDcmtPreview';
17
- import { TMButton, TMLayoutWaitingContainer } from '../..';
17
+ import { TMButton } from '../..';
18
+ import TMLayoutContainer from '../../base/TMLayout';
18
19
  import { useDocumentOperations } from '../../../hooks/useDocumentOperations';
19
20
  import TMToppyMessage from '../../../helper/TMToppyMessage';
20
21
  import TMPanel from '../../base/TMPanel';
21
- import sixLogo from '../../../assets/six.png';
22
- const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, appendMasterDcmts, onTaskCreateRequest, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, datagridUtility, dcmtUtility, fetchRemoteCertificates }) => {
22
+ import TMSpinner from '../../base/TMSpinner';
23
+ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, onFirstLoadCompleted, appendMasterDcmts, onTaskCreateRequest, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, datagridUtility, dcmtUtility, fetchRemoteCertificates }) => {
23
24
  const floatingBarContainerRef = useRef(null);
24
25
  const [focusedItem, setFocusedItem] = useState();
25
26
  const [selectedItems, setSelectedItems] = useState([]);
@@ -71,6 +72,24 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
71
72
  setIsCheckingFirstLoad(false);
72
73
  }
73
74
  }, [isRelationViewerLoading, isCheckingFirstLoad]);
75
+ useEffect(() => {
76
+ if (!isCheckingFirstLoad)
77
+ onFirstLoadCompleted?.();
78
+ }, [isCheckingFirstLoad, onFirstLoadCompleted]);
79
+ // Dal montaggio fino all'apertura del wait panel del viewer (il tempo di caricare i
80
+ // tipi documento) la pagina resta nascosta: senza spinner non si vedrebbe nulla.
81
+ const [waitingFirstLoad, setWaitingFirstLoad] = useState(true);
82
+ useEffect(() => {
83
+ if (!waitingFirstLoad)
84
+ return;
85
+ // Da qui in avanti e' il wait panel a dare riscontro
86
+ if (isRelationViewerLoading) {
87
+ setWaitingFirstLoad(false);
88
+ return;
89
+ }
90
+ TMSpinner.show({ description: SDKUI_Localizator.Loading });
91
+ return () => TMSpinner.hide();
92
+ }, [waitingFirstLoad, isRelationViewerLoading]);
74
93
  // Increments trigger counter to force operationItems to re-calculate
75
94
  const onRefreshOperationsDatagrid = useCallback(async () => {
76
95
  setRefreshOperationsTrigger(prev => prev + 1);
@@ -79,12 +98,6 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
79
98
  const handleStopCalculationReady = useCallback((stopCalculation) => {
80
99
  stopRelationsCalculationRef.current = stopCalculation;
81
100
  }, []);
82
- // Interrompe il calcolo delle correlazioni: mostra subito quelle già calcolate
83
- // senza attendere le restanti chiamate GetMetadata
84
- const handleStopRelationsCalculation = useCallback(() => {
85
- stopRelationsCalculationRef.current?.();
86
- setIsCheckingFirstLoad(false); // Nasconde l'overlay e mostra l'albero (parziale)
87
- }, []);
88
101
  // Esce dalla maschera interrompendo anche le chiamate GetMetadata ancora in coda:
89
102
  // l'interruzione è invocata in modo sincrono perché onBack può smontare il componente
90
103
  // (un effect non farebbe in tempo a propagare l'interruzione)
@@ -93,25 +106,30 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
93
106
  stopRelationsCalculationRef.current?.();
94
107
  onBack?.();
95
108
  }, [onBack]);
96
- const handleCancelFirstLoad = useCallback(() => {
97
- setIsCheckingFirstLoad(false);
98
- handleBack();
99
- }, [handleBack]);
100
- // Avanzamento del calcolo correlazioni, mostrato nell'overlay di primo caricamento
101
- const [relationsProgress, setRelationsProgress] = useState({ value: 0, max: 0 });
102
- const handleRelationsProgress = useCallback((value, max) => {
103
- setRelationsProgress({ value, max });
104
- }, []);
105
- // Notifica all'utente che i dati mostrati sono parziali (non quando si sta uscendo)
109
+ // Letta da handleRelationsCalculationStopped, che deve restare stabile: arriva fino
110
+ // alle dipendenze di loadData nel viewer, dove un cambio farebbe ripartire il calcolo
111
+ const handleBackRef = useRef(handleBack);
112
+ handleBackRef.current = handleBack;
113
+ // Notifica all'utente che i dati mostrati sono parziali
106
114
  const handleRelationsCalculationStopped = useCallback((loadedCount, totalCount) => {
107
115
  if (isLeavingRef.current)
108
116
  return;
109
- // Con piu' documenti in input, indica quanti sono stati completati (es. "3/10")
110
- const progress = totalCount > 1 ? ` (${loadedCount}/${totalCount})` : '';
117
+ // Interrotto prima di calcolare qualcosa: non c'è nulla da mostrare, si torna indietro
118
+ if (loadedCount === 0) {
119
+ ShowAlert({
120
+ message: SDKUI_Localizator.RelationsCalculationStoppedEmpty,
121
+ title: SDKUI_Localizator.Attention,
122
+ duration: 6000,
123
+ mode: 'warning',
124
+ });
125
+ handleBackRef.current();
126
+ return;
127
+ }
128
+ // Testo breve: il box di ShowAlert ha altezza fissa e taglia oltre le due righe
111
129
  ShowAlert({
112
- message: `${SDKUI_Localizator.RelationsCalculationStopped}${progress}`,
130
+ message: SDKUI_Localizator.RelationsCalculationStoppedProgress.replaceParams(loadedCount.toString(), totalCount.toString()),
113
131
  title: SDKUI_Localizator.Attention,
114
- duration: 4000,
132
+ duration: 6000,
115
133
  mode: 'info',
116
134
  });
117
135
  }, []);
@@ -289,7 +307,6 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
289
307
  onRefreshAfterAddDcmtToFavs,
290
308
  },
291
309
  });
292
- const { dcmtOperations: { abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, }, } = features;
293
310
  // Nuovi documenti in input: il componente non sta più uscendo dalla maschera
294
311
  // (chiave stabile: l'array inputDcmts può essere ricreato a ogni render)
295
312
  const inputDcmtsKey = useMemo(() => (inputDcmts ?? []).map(d => `${d.TID}-${d.DID}`).join('|'), [inputDcmts]);
@@ -393,7 +410,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
393
410
  setContextMenuVisible(true);
394
411
  }, children: [_jsx(TMRelationViewerWrapper, { refreshKey: refreshKey, inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, showZeroDcmts: showZeroDcmts,
395
412
  // customItemRender={customItemRender}
396
- allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound, onItemContextMenu: isRelationViewerLoading ? undefined : onItemContextMenu, focusedItemFormData: focusedItemFormData, onLoadingStateChanged: setIsRelationViewerLoading, onLoadingProgress: handleRelationsProgress, onStopCalculationReady: handleStopCalculationReady, onCalculationStopped: handleRelationsCalculationStopped, initialTreeState: treeStateRef.current, onTreeStateChange: handleTreeStateChange }), _jsx(TMContextMenu, { items: operationItems, externalControl: {
413
+ allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound, onItemContextMenu: isRelationViewerLoading ? undefined : onItemContextMenu, onLoadingStateChanged: setIsRelationViewerLoading, onStopCalculationReady: handleStopCalculationReady, onCalculationStopped: handleRelationsCalculationStopped, initialTreeState: treeStateRef.current, onTreeStateChange: handleTreeStateChange }), _jsx(TMContextMenu, { items: operationItems, externalControl: {
397
414
  visible: contextMenuVisible,
398
415
  position: contextMenuPosition,
399
416
  onClose: () => setContextMenuVisible(false)
@@ -477,12 +494,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
477
494
  toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
478
495
  }
479
496
  ], [tmTreeView, tmFormOrResult, focusedItem?.isDcmt, dtdMaster]);
480
- return (_jsxs("div", { style: { width: '100%', height: '100%', position: 'relative' }, children: [isCheckingFirstLoad && (_jsx(TMLoadingOverlay, { onCancel: handleCancelFirstLoad, onStop: handleStopRelationsCalculation, description: relationsProgress.max > 1
481
- ? `${isForMaster ? SDKUI_Localizator.LoadingMasterDocuments : SDKUI_Localizator.LoadingDetailDocuments} (${relationsProgress.value}/${relationsProgress.max})`
482
- : undefined, progressValue: relationsProgress.value, progressMax: relationsProgress.max,
483
- // Con un solo documento in input la chiamata è unica: non ci sono
484
- // risultati parziali da mostrare, quindi il pulsante resta disabilitato
485
- stopDisabled: (inputDcmts?.length ?? 0) <= 1 })), _jsxs("div", { style: isCheckingFirstLoad ? { position: 'absolute', width: 0, height: 0, overflow: 'hidden', opacity: 0, pointerEvents: 'none' } : { width: '100%', height: '100%' }, children: [_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }), renderDcmtOperations, renderFloatingBar] })] }));
497
+ return (_jsx("div", { style: { width: '100%', height: '100%', position: 'relative' }, children: _jsxs("div", { style: isCheckingFirstLoad ? { position: 'absolute', width: 0, height: 0, overflow: 'hidden', opacity: 0, pointerEvents: 'none' } : { width: '100%', height: '100%' }, children: [_jsx(TMLayoutContainer, { direction: 'vertical', children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }), renderDcmtOperations, renderFloatingBar] }) }));
486
498
  };
487
499
  export default TMMasterDetailDcmts;
488
500
  /**
@@ -491,7 +503,7 @@ export default TMMasterDetailDcmts;
491
503
  * - Panel visibility toggling
492
504
  * - Focus delay handling
493
505
  */
494
- const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound, onItemContextMenu, focusedItemFormData, onLoadingStateChanged, onLoadingProgress, onStopCalculationReady, onCalculationStopped, initialTreeState, onTreeStateChange }) => {
506
+ const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound, onItemContextMenu, onLoadingStateChanged, onStopCalculationReady, onCalculationStopped, initialTreeState, onTreeStateChange }) => {
495
507
  const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
496
508
  // Monitor device type changes to restore panel visibility when switching from mobile to desktop
497
509
  const deviceType = useDeviceType();
@@ -551,7 +563,7 @@ const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurr
551
563
  onItemContextMenu?.(item, e);
552
564
  }, 100);
553
565
  }, [onItemContextMenu, handleFocusedItemChanged]);
554
- return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, showExpandAllButton: true, onNoRelationsFound: onNoRelationsFound, onItemContextMenu: onContextMenu, focusedItemFormData: focusedItemFormData, onLoadingStateChanged: onLoadingStateChanged, onLoadingProgress: onLoadingProgress, onStopCalculationReady: onStopCalculationReady, onCalculationStopped: onCalculationStopped, initialTreeState: initialTreeState, onTreeStateChange: onTreeStateChange }, refreshKey));
566
+ return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, showExpandAllButton: true, onNoRelationsFound: onNoRelationsFound, onItemContextMenu: onContextMenu, onLoadingStateChanged: onLoadingStateChanged, onStopCalculationReady: onStopCalculationReady, onCalculationStopped: onCalculationStopped, initialTreeState: initialTreeState, onTreeStateChange: onTreeStateChange }, refreshKey));
555
567
  };
556
568
  const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid, onRefreshSearchResults, handleNavigateToReference, fetchRemoteCertificates }) => {
557
569
  const { setPanelVisibilityById } = useTMPanelManagerContext();
@@ -561,117 +573,3 @@ const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCrea
561
573
  }, fetchRemoteCertificates: fetchRemoteCertificates }, refreshKey) :
562
574
  focusedItem?.searchResult === undefined ? (_jsx(TMPanel, { title: SDKUI_Localizator.SearchResult, children: _jsx(TMToppyMessage, { message: SDKUI_Localizator.SelectDocumentToViewSearchResults }) })) : (_jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, autoFocusFirstRow: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, enablePinIcons: false, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, showBackButton: false, onRefreshSearchAsyncDatagrid: onRefreshSearchResults, onReferenceClick: handleNavigateToReference, fetchRemoteCertificates: fetchRemoteCertificates }, refreshKey)) }));
563
575
  };
564
- const TMLoadingOverlay = ({ onCancel, onStop, description, cancelText, stopText, progressValue, progressMax, stopDisabled }) => {
565
- // Stesso calcolo di TMWaitPanel: 0 quando il massimo non è ancora noto
566
- const progressPercent = (progressMax ?? 0) > 0
567
- ? Math.min(100, ((progressValue ?? 0) / (progressMax ?? 1)) * 100)
568
- : 0;
569
- return (_jsx("div", { style: {
570
- position: 'absolute',
571
- top: 0,
572
- left: 0,
573
- width: '100%',
574
- height: '100%',
575
- backgroundColor: 'rgba(248, 250, 252, 0.92)',
576
- zIndex: 1000,
577
- display: 'flex',
578
- justifyContent: 'center',
579
- alignItems: 'center',
580
- }, children: _jsxs("div", { style: {
581
- display: 'flex',
582
- flexDirection: 'column',
583
- alignItems: 'center',
584
- gap: '16px',
585
- padding: '24px 32px',
586
- background: '#fcfcfc',
587
- borderRadius: '8px',
588
- boxShadow: '0 4px 16px rgba(0, 0, 0, 0.1)',
589
- }, children: [_jsxs("div", { style: { position: 'relative', width: '80px', height: '80px' }, children: [_jsx("img", { style: {
590
- position: 'absolute',
591
- top: '50%',
592
- left: '50%',
593
- transform: 'translate(-54%, -54%)'
594
- }, src: sixLogo, width: 35, alt: "" }), _jsx("style", { children: `
595
- @keyframes tmSpinnerRotate {
596
- 0% { transform: rotate(0deg); }
597
- 100% { transform: rotate(360deg); }
598
- }
599
- .tm-spinner-animation {
600
- display: inline-block;
601
- width: 80px;
602
- height: 80px;
603
- position: absolute;
604
- top: 50%;
605
- left: 50%;
606
- transform: translate(-50%, -50%);
607
- }
608
- .tm-spinner-animation div {
609
- animation: tmSpinnerRotate 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
610
- transform-origin: 40px 40px;
611
- }
612
- .tm-spinner-animation div:after {
613
- content: " ";
614
- display: block;
615
- position: absolute;
616
- width: 7px;
617
- height: 7px;
618
- border-radius: 50%;
619
- background: #0c448e;
620
- margin: -4px 0 0 -4px;
621
- }
622
- .tm-spinner-animation div:nth-child(1) { animation-delay: -0.036s; }
623
- .tm-spinner-animation div:nth-child(1):after { top: 63px; left: 63px; background: #f7a51f; }
624
- .tm-spinner-animation div:nth-child(2) { animation-delay: -0.072s; }
625
- .tm-spinner-animation div:nth-child(2):after { top: 68px; left: 56px; background: #f7a51f; }
626
- .tm-spinner-animation div:nth-child(3) { animation-delay: -0.108s; }
627
- .tm-spinner-animation div:nth-child(3):after { top: 71px; left: 48px; background: #d3237b; }
628
- .tm-spinner-animation div:nth-child(4) { animation-delay: -0.144s; }
629
- .tm-spinner-animation div:nth-child(4):after { top: 72px; left: 40px; background: #d3237b; }
630
- .tm-spinner-animation div:nth-child(5) { animation-delay: -0.18s; }
631
- .tm-spinner-animation div:nth-child(5):after { top: 71px; left: 32px; background: #d12a1c; }
632
- .tm-spinner-animation div:nth-child(6) { animation-delay: -0.216s; }
633
- .tm-spinner-animation div:nth-child(6):after { top: 68px; left: 24px; background: #d12a1c; }
634
- .tm-spinner-animation div:nth-child(7) { animation-delay: -0.252s; }
635
- .tm-spinner-animation div:nth-child(7):after { top: 63px; left: 17px; background: #782b7d; }
636
- .tm-spinner-animation div:nth-child(8) { animation-delay: -0.288s; }
637
- .tm-spinner-animation div:nth-child(8):after { top: 56px; left: 12px; background: #782b7d; }
638
- ` }), _jsxs("div", { className: "tm-spinner-animation", children: [_jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {})] })] }), _jsx("span", { style: { fontSize: '14px', color: '#334155', textAlign: 'center' }, children: description ?? SDKUI_Localizator.Loading }), (progressMax ?? 0) > 1 && (_jsxs("div", { style: { width: '260px' }, children: [_jsx("div", { style: { width: '100%', height: '20px', background: '#e0e0e0', borderRadius: '10px', overflow: 'hidden' }, children: _jsx("div", { style: { width: `${progressPercent.toFixed(2)}%`, height: '100%', background: '#4caf50', transition: 'width 0.3s ease' } }) }), _jsxs("p", { style: { fontWeight: 'bold', color: '#333', margin: '8px 0 0', textAlign: 'center' }, children: [progressPercent.toFixed(2), "%"] })] })), (onStop || onCancel) && (_jsxs("div", { style: { marginTop: '4px', display: 'flex', alignItems: 'center', justifyContent: 'center', flexWrap: 'wrap', gap: '10px' }, children: [onStop && (_jsx("button", { onClick: onStop, disabled: stopDisabled, title: SDKUI_Localizator.StopRelationsCalculation, style: {
639
- padding: '8px 24px',
640
- fontSize: '13px',
641
- fontWeight: 500,
642
- color: stopDisabled ? '#94a3b8' : 'white',
643
- background: stopDisabled ? '#e2e8f0' : '#0c448e',
644
- border: `1.5px solid ${stopDisabled ? '#e2e8f0' : '#0c448e'}`,
645
- borderRadius: '6px',
646
- cursor: stopDisabled ? 'not-allowed' : 'pointer',
647
- transition: 'all 0.2s ease',
648
- }, onMouseEnter: (e) => {
649
- if (stopDisabled)
650
- return;
651
- e.currentTarget.style.background = '#0a3872';
652
- e.currentTarget.style.borderColor = '#0a3872';
653
- }, onMouseLeave: (e) => {
654
- if (stopDisabled)
655
- return;
656
- e.currentTarget.style.background = '#0c448e';
657
- e.currentTarget.style.borderColor = '#0c448e';
658
- }, children: stopText ?? SDKUI_Localizator.ShowPartialResults })), onCancel && (_jsx("button", { onClick: onCancel, style: {
659
- padding: '8px 24px',
660
- fontSize: '13px',
661
- fontWeight: 500,
662
- color: '#64748b',
663
- background: 'transparent',
664
- border: '1.5px solid #cbd5e1',
665
- borderRadius: '6px',
666
- cursor: 'pointer',
667
- transition: 'all 0.2s ease',
668
- }, onMouseEnter: (e) => {
669
- e.currentTarget.style.background = '#f1f5f9';
670
- e.currentTarget.style.borderColor = '#94a3b8';
671
- e.currentTarget.style.color = '#475569';
672
- }, onMouseLeave: (e) => {
673
- e.currentTarget.style.background = 'transparent';
674
- e.currentTarget.style.borderColor = '#cbd5e1';
675
- e.currentTarget.style.color = '#64748b';
676
- }, children: cancelText ?? SDKUI_Localizator.Back }))] }))] }) }));
677
- };