@topconsultnpm/sdkui-react 6.22.0-dev3.8 → 6.22.0-dev4.2

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 (96) 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/TMButton.js +4 -2
  4. package/lib/components/base/TMCustomButton.js +40 -48
  5. package/lib/components/base/TMDataGrid.js +219 -219
  6. package/lib/components/base/TMPanel.js +173 -170
  7. package/lib/components/base/TMSpinner.d.ts +2 -1
  8. package/lib/components/base/TMSpinner.js +9 -7
  9. package/lib/components/base/TMTabControl.d.ts +7 -0
  10. package/lib/components/base/TMTabControl.js +24 -12
  11. package/lib/components/base/TMTreeView.js +20 -0
  12. package/lib/components/base/TMWaitPanel.js +1 -1
  13. package/lib/components/base/waitPanel/TMWaitPanelConfirm.d.ts +12 -0
  14. package/lib/components/base/waitPanel/TMWaitPanelConfirm.js +185 -0
  15. package/lib/components/base/waitPanel/TMWaitPanelManager.d.ts +169 -0
  16. package/lib/components/base/waitPanel/TMWaitPanelManager.js +320 -0
  17. package/lib/components/base/waitPanel/TMWaitPanelView.d.ts +53 -0
  18. package/lib/components/base/waitPanel/TMWaitPanelView.js +274 -0
  19. package/lib/components/base/waitPanel/index.d.ts +1 -0
  20. package/lib/components/base/waitPanel/index.js +1 -0
  21. package/lib/components/choosers/TMPathChooser.js +17 -34
  22. package/lib/components/editors/TMTextBox.d.ts +4 -0
  23. package/lib/components/editors/TMTextBox.js +99 -11
  24. package/lib/components/features/archive/TMArchive.js +7 -2
  25. package/lib/components/features/assistant/TMHelpOnLineChat.d.ts +29 -0
  26. package/lib/components/features/assistant/TMHelpOnLineChat.js +1384 -0
  27. package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +2 -2
  28. package/lib/components/features/assistant/dataset/Designer-Suggested-Questions.json +102 -0
  29. package/lib/components/features/assistant/dataset/Login-Suggested-Questions.json +32 -0
  30. package/lib/components/features/assistant/dataset/Surfer-Suggested-Questions.json +102 -0
  31. package/lib/components/features/documents/TMBatchUpdateForm.js +3 -4
  32. package/lib/components/features/documents/TMCopyToFolderForm.js +50 -42
  33. package/lib/components/features/documents/TMDcmtForm.js +50 -61
  34. package/lib/components/features/documents/TMDcmtIcon.d.ts +1 -3
  35. package/lib/components/features/documents/TMDcmtIcon.js +3 -5
  36. package/lib/components/features/documents/TMDcmtPreview.js +5 -3
  37. package/lib/components/features/documents/TMDcmtTasks.js +2 -9
  38. package/lib/components/features/documents/TMFileUploader.js +26 -26
  39. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
  40. package/lib/components/features/documents/TMMasterDetailDcmts.js +53 -141
  41. package/lib/components/features/documents/TMMasterInfoFields.js +3 -2
  42. package/lib/components/features/documents/TMMergeToPdfForm.js +56 -54
  43. package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +14 -15
  44. package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +1 -1
  45. package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +3 -3
  46. package/lib/components/features/documents/TMRelationViewer.d.ts +13 -14
  47. package/lib/components/features/documents/TMRelationViewer.js +206 -143
  48. package/lib/components/features/documents/relationTreeState.d.ts +32 -0
  49. package/lib/components/features/documents/relationTreeState.js +89 -0
  50. package/lib/components/features/search/TMSearch.js +3 -4
  51. package/lib/components/features/search/TMSearchQueryPanel.js +0 -4
  52. package/lib/components/features/search/TMSearchResult.d.ts +5 -0
  53. package/lib/components/features/search/TMSearchResult.js +37 -19
  54. package/lib/components/features/search/TMTreeSelector.js +23 -27
  55. package/lib/components/features/search/TMViewHistoryDcmt.js +14 -25
  56. package/lib/components/features/tasks/TMTasksView.js +91 -90
  57. package/lib/components/features/wg/TMWGsCopyMoveForm.js +91 -91
  58. package/lib/components/forms/TMResultDialog.js +1 -1
  59. package/lib/components/grids/TMBlogsPost.js +92 -96
  60. package/lib/components/index.d.ts +5 -1
  61. package/lib/components/index.js +4 -1
  62. package/lib/components/layout/panelManager/TMPanelManagerContainer.js +16 -15
  63. package/lib/components/layout/panelManager/TMPanelManagerContext.d.ts +1 -0
  64. package/lib/components/layout/panelManager/TMPanelManagerContext.js +5 -1
  65. package/lib/components/layout/panelManager/TMPanelManagerLoader.d.ts +6 -0
  66. package/lib/components/layout/panelManager/TMPanelManagerLoader.js +18 -0
  67. package/lib/components/layout/panelManager/TMPanelManagerToolbar.js +4 -8
  68. package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.d.ts +1 -1
  69. package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.js +2 -1
  70. package/lib/components/pages/TMPage.js +29 -31
  71. package/lib/components/query/TMQueryEditor.d.ts +3 -0
  72. package/lib/components/query/TMQueryEditor.js +2 -1
  73. package/lib/components/sidebar/TMHeader.d.ts +1 -0
  74. package/lib/components/sidebar/TMHeader.js +2 -2
  75. package/lib/helper/Enum_Localizator.js +1 -0
  76. package/lib/helper/SDKUI_Globals.d.ts +3 -0
  77. package/lib/helper/SDKUI_Globals.js +3 -0
  78. package/lib/helper/SDKUI_Localizator.d.ts +21 -0
  79. package/lib/helper/SDKUI_Localizator.js +210 -0
  80. package/lib/helper/ZipManager.d.ts +1 -1
  81. package/lib/helper/ZipManager.js +2 -1
  82. package/lib/helper/dcmtsHelper.d.ts +2 -0
  83. package/lib/helper/dcmtsHelper.js +3 -1
  84. package/lib/hooks/useCheckInOutOperations.d.ts +0 -6
  85. package/lib/hooks/useCheckInOutOperations.js +14 -34
  86. package/lib/hooks/useDcmtOperations.d.ts +3 -12
  87. package/lib/hooks/useDcmtOperations.js +187 -179
  88. package/lib/hooks/useDocumentOperations.d.ts +1 -0
  89. package/lib/hooks/useDocumentOperations.js +14 -25
  90. package/lib/hooks/useMultiMasterDetailDcmts.d.ts +0 -15
  91. package/lib/hooks/useMultiMasterDetailDcmts.js +65 -67
  92. package/lib/hooks/usePreventFileDrop.js +9 -0
  93. package/lib/hooks/useWorkflowApprove.js +33 -17
  94. package/lib/services/caseflow/CaseFlowService.d.ts +36 -6
  95. package/lib/services/caseflow/CaseFlowService.js +55 -14
  96. package/package.json +69 -69
@@ -0,0 +1,32 @@
1
+ import type { RelationTreeItem } from './TMRelationViewer';
2
+ /**
3
+ * Conserva lo stato di un albero delle correlazioni (nodi espansi e fuoco) attraverso
4
+ * un refresh che ricarica i dati da zero. I nodi non sono confrontabili per `key`, che
5
+ * contiene un GUID rigenerato ad ogni caricamento: si usa un percorso costruito sui campi.
6
+ */
7
+ export interface RelationTreeState {
8
+ /** Documenti di input a cui lo stato si riferisce: non va applicato ad altri */
9
+ inputKey: string;
10
+ expandedPaths: string[];
11
+ /**
12
+ * Documenti espansi che avevano già i figli caricati. Quelli espansi ma vuoti
13
+ * (es. il root) non vanno ricaricati: mostrerebbero più di quanto c'era prima.
14
+ */
15
+ loadedPaths: string[];
16
+ focusedPath?: string;
17
+ }
18
+ /** Carica i figli di un documento durante il ripristino. */
19
+ export type LoadChildrenFn = (node: RelationTreeItem) => Promise<RelationTreeItem[]>;
20
+ /**
21
+ * Fotografa lo stato dell'albero.
22
+ * `previousFocusedPath` viene usato quando il fuoco è già stato azzerato dall'esterno.
23
+ */
24
+ export declare const collectRelationTreeState: (nodes: RelationTreeItem[], inputKey: string, focusedKey: string | undefined, previousFocusedPath?: string) => RelationTreeState;
25
+ /**
26
+ * Riapplica lo stato all'albero appena caricato. I nodi che non compaiono nello stato,
27
+ * o che non esistono più (es. documento cancellato), restano chiusi: il confronto per
28
+ * percorso è tollerante per costruzione.
29
+ */
30
+ export declare const applyRelationTreeState: (nodes: RelationTreeItem[], state: RelationTreeState, loadChildren: LoadChildrenFn, isAborted: () => boolean) => Promise<RelationTreeItem[]>;
31
+ /** Cerca un nodo per percorso, per rimettere il fuoco dov'era. */
32
+ export declare const findRelationNodeByPath: (nodes: RelationTreeItem[], path: string) => RelationTreeItem | null;
@@ -0,0 +1,89 @@
1
+ /** I nodi generati (messaggi informativi, separatori) non hanno identità stabile. */
2
+ const hasStableIdentity = (node) => !node.isInfoMessage && !node.isSeparator;
3
+ const getNodeIdentity = (node) => node.isDcmt
4
+ ? `d:${node.tid ?? ''}:${node.did ?? ''}:${node.relationId ?? ''}`
5
+ : `c:${node.tid ?? ''}:${node.relationId ?? ''}:${node.name ?? ''}`;
6
+ /** Il percorso include i padri: lo stesso documento può comparire sotto padri diversi. */
7
+ const getNodePath = (node, parentPath) => {
8
+ const identity = getNodeIdentity(node);
9
+ return parentPath ? `${parentPath}>${identity}` : identity;
10
+ };
11
+ /**
12
+ * Fotografa lo stato dell'albero.
13
+ * `previousFocusedPath` viene usato quando il fuoco è già stato azzerato dall'esterno.
14
+ */
15
+ export const collectRelationTreeState = (nodes, inputKey, focusedKey, previousFocusedPath) => {
16
+ const expandedPaths = [];
17
+ const loadedPaths = [];
18
+ let focusedPath;
19
+ const collect = (items, parentPath) => {
20
+ for (const node of items) {
21
+ if (!hasStableIdentity(node))
22
+ continue;
23
+ const path = getNodePath(node, parentPath);
24
+ if (node.expanded)
25
+ expandedPaths.push(path);
26
+ if (node.expanded && node.isDcmt && node.items)
27
+ loadedPaths.push(path);
28
+ // Entro la stessa istanza montata la key è univoca
29
+ if (focusedKey && node.key === focusedKey)
30
+ focusedPath = path;
31
+ if (node.items)
32
+ collect(node.items, path);
33
+ }
34
+ };
35
+ collect(nodes, '');
36
+ return { inputKey, expandedPaths, loadedPaths, focusedPath: focusedPath ?? previousFocusedPath };
37
+ };
38
+ /**
39
+ * Riapplica lo stato all'albero appena caricato. I nodi che non compaiono nello stato,
40
+ * o che non esistono più (es. documento cancellato), restano chiusi: il confronto per
41
+ * percorso è tollerante per costruzione.
42
+ */
43
+ export const applyRelationTreeState = async (nodes, state, loadChildren, isAborted) => {
44
+ const expandedPaths = new Set(state.expandedPaths);
45
+ const loadedPaths = new Set(state.loadedPaths);
46
+ const apply = async (items, parentPath) => {
47
+ const result = [];
48
+ for (const node of items) {
49
+ if (!hasStableIdentity(node)) {
50
+ result.push(node);
51
+ continue;
52
+ }
53
+ const path = getNodePath(node, parentPath);
54
+ const wasExpanded = expandedPaths.has(path);
55
+ let children = node.items;
56
+ let isLoaded = node.isLoaded;
57
+ let itemsCount = node.itemsCount;
58
+ // I figli dei documenti sono lazy: vanno ricaricati se l'utente li aveva aperti
59
+ if (wasExpanded && node.isDcmt && !children && loadedPaths.has(path) && !isAborted()) {
60
+ children = await loadChildren(node);
61
+ isLoaded = true;
62
+ itemsCount = children.length;
63
+ }
64
+ const updatedItems = children ? await apply(children, path) : children;
65
+ result.push({ ...node, expanded: wasExpanded, items: updatedItems, isLoaded, itemsCount });
66
+ }
67
+ return result;
68
+ };
69
+ return await apply(nodes, '');
70
+ };
71
+ /** Cerca un nodo per percorso, per rimettere il fuoco dov'era. */
72
+ export const findRelationNodeByPath = (nodes, path) => {
73
+ const find = (items, parentPath) => {
74
+ for (const node of items) {
75
+ if (!hasStableIdentity(node))
76
+ continue;
77
+ const currentPath = getNodePath(node, parentPath);
78
+ if (currentPath === path)
79
+ return node;
80
+ if (node.items) {
81
+ const found = find(node.items, currentPath);
82
+ if (found)
83
+ return found;
84
+ }
85
+ }
86
+ return null;
87
+ };
88
+ return find(nodes, '');
89
+ };
@@ -369,7 +369,6 @@ const TMSearchInstance = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback,
369
369
  : _jsx(StyledMultiViewPanel, { $isVisible: currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', isPersistenceEnabled: !isMobile ? hasSavedLayout() : false, persistPanelStates: !isMobile ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: getPersistedPanelStates(), children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true, minPanelSizePx: !isMobile ? 250 : 150 }) }) }), showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsyncDatagrid: onRefreshSearchAsyncDatagrid, onClose: () => { if (onlyShowSearchQueryPanel)
370
370
  setShowSearchResults(false); setCurrentSearchView(TMSearchViews.Search); }, backCaption: onlyShowSearchQueryPanel ? SDKUI_Localizator.BackToSearch : undefined, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, openFileUploaderPdfEditor: openFileUploaderPdfEditor, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, showToppyDraggableHelpCenter: showToppyDraggableHelpCenter, toppyHelpCenterUsePortal: toppyHelpCenterUsePortal, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, inputDID: inputDID, formAutoOpen: formAutoOpen, fetchRemoteCertificates: fetchRemoteCertificates, graphometricManager: graphometricManager })] }));
371
371
  };
372
- const ENABLE_SEARCH_TABS = false;
373
372
  // Ogni tab e' un TMSearch completo e indipendente: TMTabControl li tiene tutti montati, cosi piu ricerche
374
373
  // restano vive insieme, ognuna con i suoi tipi documento, i suoi filtri e i suoi risultati.
375
374
  const TMSearch = (props) => {
@@ -394,9 +393,9 @@ const TMSearch = (props) => {
394
393
  // quel momento: gli altri restano sulla ricerca che stanno svolgendo.
395
394
  const [inputsTabId, setInputsTabId] = useState(tabs.activeId);
396
395
  useEffect(() => { setInputsTabId(activeIdRef.current); }, [inputTID, inputSqdID, inputDID]);
397
- // Nella modalita a solo pannello di ricerca (es. abbinamento molti a molti) i tab non servono,
398
- // cosi come non servono finche' i tab non vengono rilasciati
399
- if (!ENABLE_SEARCH_TABS || onlyShowSearchQueryPanel)
396
+ // Con onlyShowSearchQueryPanel (es. abbinamento molti a molti) si mostra solo il pannello di ricerca
397
+ // di una singola istanza, senza tab: la multi ricerca non serve in quel contesto
398
+ if (onlyShowSearchQueryPanel)
400
399
  return _jsx(TMSearchInstance, { ...props });
401
400
  return (_jsx(TMTabControl, { ...tabs.controlProps, contentAnimation: 'none', onTabRename: undefined, variant: 'module', style: { height: '100%', width: '100%' }, contentStyle: { display: 'flex', flex: 1, minHeight: 0, position: 'relative' }, children: tabs.items.map(t => {
402
401
  const isActiveTab = t.id === tabs.activeId;
@@ -515,7 +515,6 @@ export const refreshLastSearch = async (qd) => {
515
515
  return;
516
516
  let searchResults = [];
517
517
  try {
518
- TMSpinner.show({ description: `${SDKUI_Localizator.Search} ...`, backgroundColor: 'transparent' });
519
518
  let result = await SDK_Globals.tmSession?.NewSearchEngine().SearchByIDAsync(qd);
520
519
  let dcmtsFound = result?.dcmtsFound ?? 0;
521
520
  if (dcmtsFound <= 0)
@@ -526,9 +525,6 @@ export const refreshLastSearch = async (qd) => {
526
525
  catch (ex) {
527
526
  TMExceptionBoxManager.show({ title: SDKUI_Localizator.Search, exception: ex });
528
527
  }
529
- finally {
530
- TMSpinner.hide();
531
- }
532
528
  return searchResults;
533
529
  };
534
530
  // =============================================================================
@@ -23,6 +23,11 @@ interface ITMSearchResultProps {
23
23
  openDcmtFormAsModal?: boolean;
24
24
  showSearchResultSidebar?: boolean;
25
25
  showDcmtFormSidebar?: boolean;
26
+ /** Mostra accanto alla griglia il selettore dei tipi documento trovati:
27
+ * su desktop sono affiancati (30/70),
28
+ * su mobile si naviga a step tra selettore e risultati.
29
+ * Se il risultato ha un solo tipo documento il selettore resta chiuso
30
+ * e lo spazio va tutto alla griglia, riapribile dal menu "Altro" */
26
31
  showSelector?: boolean;
27
32
  showToolbarHeader?: boolean;
28
33
  showBackButton?: boolean;
@@ -3,7 +3,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useSta
3
3
  import styled from 'styled-components';
4
4
  import { LoadIndicator } from 'devextreme-react';
5
5
  import { AppModules, DataColumnTypes, DataListViewModes, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataDomains, SDK_Globals, SystemMIDsAsNumber, UserListCacheService, } from '@topconsultnpm/sdk-ts';
6
- import { customizeSearchByDisplayText, deepCompare, formatDateTimeByMetadataFormat, formatNumberByMetadataFormat, generateUniqueColumnKeys, genUniqueId, getColumnFormatInfo, getDateDisplayText, getNumberDisplayText, getSearchToolbarVisibility, IconAll, IconBoard, IconDcmtTypeSys, IconDelete, IconDuplicate, IconEdit, IconMenuVertical, IconPlatform, IconRefresh, IconSearchCheck, IconShow, isApprovalWorkflowView, isSign4TopEnabled, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, SDKUI_Globals, SDKUI_Localizator, IconCloseOutline, getSearchResultPanelLayout, getSearchResultPanelLayoutSignature, hasSearchResultPanelLayout, saveSearchResultPanelLayout, subscribeSearchResultPanelLayout } from '../../../helper';
6
+ import { customizeSearchByDisplayText, deepCompare, formatDateTimeByMetadataFormat, formatNumberByMetadataFormat, generateUniqueColumnKeys, genUniqueId, getColumnFormatInfo, getDateDisplayText, getNumberDisplayText, getSearchToolbarVisibility, IconAll, IconBoard, IconDcmtTypeSys, IconDelete, IconDuplicate, IconEdit, IconMenuVertical, IconPlatform, IconRefresh, IconSearchCheck, IconShow, isApprovalWorkflowView, isSign4TopEnabled, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, SDKUI_Globals, SDKUI_Localizator, IconCloseOutline, getSearchResultPanelLayout, getSearchResultPanelLayoutSignature, hasSearchResultPanelLayout, saveSearchResultPanelLayout, subscribeSearchResultPanelLayout, DEFAULT_VIRTUAL_RENDERING_THRESHOLD } from '../../../helper';
7
7
  import { CounterItemKey } from '../../base/TMCounterContainer';
8
8
  import { getDcmtCicoStatus } from '../../../helper/checkinCheckoutManager';
9
9
  import { DcmtOperationTypes, SearchResultContext, } from '../../../ts';
@@ -16,11 +16,10 @@ import TMAccordionNew from '../../base/TMAccordionNew';
16
16
  import TMButton from '../../base/TMButton';
17
17
  import TMDataGrid, { TMDataGridPageSize } from '../../base/TMDataGrid';
18
18
  import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
19
- import { TMLayoutItem, TMSplitterLayout } from '../../base/TMLayout';
19
+ import TMLayoutContainer, { TMLayoutItem, TMSplitterLayout } from '../../base/TMLayout';
20
20
  import { ButtonNames, TMExceptionBoxManager, TMMessageBoxManager } from '../../base/TMPopUp';
21
21
  import TMSpinner from '../../base/TMSpinner';
22
22
  import { StyledMultiViewPanel } from '../../base/Styled';
23
- import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
24
23
  import TMMetadataValues from '../../editors/TMMetadataValues';
25
24
  import TMTidViewer from '../../viewers/TMTidViewer';
26
25
  import { useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
@@ -34,7 +33,6 @@ import TMDcmtPreview from '../documents/TMDcmtPreview';
34
33
  import { WorkFlowOperationButtons } from '../workflow/TMWorkflowPopup';
35
34
  // Local
36
35
  import TMSearchResultFloatingActionButton from './TMSearchResultFloatingActionButton';
37
- let abortControllerLocal = new AbortController();
38
36
  //#region Helper Methods
39
37
  export const getSearchResultCountersSingleCategory = (searchResults) => {
40
38
  // let totDcmtTypes = searchResults.length;
@@ -322,6 +320,15 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
322
320
  createTaskFromDocumentOrWorkItem();
323
321
  }
324
322
  };
323
+ const handleRefreshClick = onRefreshSearchAsyncDatagrid ? async () => {
324
+ TMSpinner.show({ description: `${SDKUI_Localizator.UpdateInProgress}`, backgroundColor: 'transparent' });
325
+ try {
326
+ await onRefreshSearchAsyncDatagrid();
327
+ }
328
+ finally {
329
+ TMSpinner.hide();
330
+ }
331
+ } : undefined;
325
332
  const { operationItems, selectedDcmtInfos, renderFloatingBar, renderDcmtOperations, features, } = useDocumentOperations({
326
333
  context: context,
327
334
  documentData: {
@@ -335,7 +342,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
335
342
  searchResult: selectedSearchResult,
336
343
  datagridUtility: {
337
344
  visibleItems,
338
- onRefreshSearchAsyncDatagrid,
345
+ onRefreshSearchAsyncDatagrid: handleRefreshClick,
339
346
  onRefreshDataRowsAsync,
340
347
  refreshFocusedDataRowAsync,
341
348
  onRefreshBlogDatagrid,
@@ -362,6 +369,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
362
369
  allowRelations,
363
370
  showTodoDcmtForm,
364
371
  graphometricManager,
372
+ showSelector,
365
373
  },
366
374
  tasks: {
367
375
  allTasks: allTasks,
@@ -396,7 +404,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
396
404
  openTaskFormHandler,
397
405
  },
398
406
  });
399
- const { isOpenDcmtForm, isDcmtFormModal, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid, showDcmtTypesSelection, showExportForm, updateBatchUpdateForm, closeDcmtFormHandler, handleSignApprove, checkoutInfo: { showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, }, dcmtOperations: { abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, }, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
407
+ const { isOpenDcmtForm, isDcmtFormModal, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid, showDcmtTypesSelection, showExportForm, updateBatchUpdateForm, closeDcmtFormHandler, handleSignApprove, dcmtOperations: { downloadDcmtsAsync, runOperationAsync, }, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
400
408
  // ----- Azioni della colonna di riga (showActionsColumn) -----------------------------------------
401
409
  // Le voci di operationItems agiscono sui documenti selezionati o, in mancanza, su quello a fuoco:
402
410
  // non accettano una riga come argomento. Il click sull'icona quindi azzera la selezione e porta il
@@ -621,11 +629,11 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
621
629
  }, [currentMetadataValues]);
622
630
  const getTitleHeader = () => {
623
631
  let counters = (showSelector && disableAccordionIfSingleCategory && searchResults.length > 1) ? getSearchResultCountersSingleCategory(searchResults) : "";
624
- if (title)
625
- return title + counters;
626
632
  // Nome del tipo documento selezionato, accodato al titolo
627
633
  const selectedDcmtTypeName = selectedSearchResult?.fromName ?? (searchResults?.length === 1 ? searchResults[0]?.fromName : undefined);
628
634
  const withSelectedDcmtTypeName = (baseTitle) => selectedDcmtTypeName ? `${baseTitle} - ${selectedDcmtTypeName}` : baseTitle;
635
+ if (title)
636
+ return withSelectedDcmtTypeName(title) + counters;
629
637
  let titleHeader = withSelectedDcmtTypeName('Ricerca per metadati');
630
638
  switch (context) {
631
639
  case SearchResultContext.MASTER_DETAIL:
@@ -765,12 +773,12 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
765
773
  && !showTodoDcmtForm);
766
774
  }, [showToppyForApprove, showToppyDraggableHelpCenter, selectedDocs, showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, editPdfForm, openS4TViewer, showTodoDcmtForm]);
767
775
  const searchResutlToolbar = _jsxs(_Fragment, { children: [context === SearchResultContext.FAVORITES_AND_RECENTS &&
768
- _jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconDelete, { color: 'white' }), caption: "Rimuovi da " + (selectedSearchResult?.category === "Favorites" ? '"Preferiti"' : '"Recenti"'), disabled: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length <= 0, onClick: removeDcmtFromFavsOrRecents }) }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: onRefreshSearchAsyncDatagrid }), _jsx(TMContextMenu, { items: operationItems, trigger: "left", children: _jsx(IconMenuVertical, { color: 'white', cursor: 'pointer' }) }), showToolbarCloseButton && onClose &&
776
+ _jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconDelete, { color: 'white' }), caption: "Rimuovi da " + (selectedSearchResult?.category === "Favorites" ? '"Preferiti"' : '"Recenti"'), disabled: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length <= 0, onClick: removeDcmtFromFavsOrRecents }) }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: handleRefreshClick }), _jsx(TMContextMenu, { items: operationItems, trigger: "left", children: _jsx(IconMenuVertical, { color: 'white', cursor: 'pointer' }) }), showToolbarCloseButton && onClose &&
769
777
  _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconCloseOutline, { color: 'white' }), caption: SDKUI_Localizator.Close, onClick: onClose })] });
770
778
  const tmSearchResult = useMemo(() => (!searchResults || searchResults.length <= 0)
771
779
  ? _jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%' }, children: [_jsx(IconBoard, { fontSize: 96 }), showNoDcmtFoundMessage && _jsx("div", { style: { fontSize: "15px", marginTop: "10px" }, children: SDKUI_Localizator.NoDcmtFound }), openAddDocumentForm && _jsx("div", { style: { marginTop: "10px" }, children: _jsx(TMButton, { fontSize: "15px", icon: _jsx("i", { className: 'dx-icon-share' }), caption: SDKUI_Localizator.Share, onClick: openAddDocumentForm }) })] })
772
780
  :
773
- _jsxs(_Fragment, { children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs("div", { ref: floatingBarContainerRef, style: { position: 'relative', height: '100%', width: '100%' }, children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: 'visible', separatorSize: Gutters.getGutters(), separatorActiveColor: 'transparent', separatorColor: 'transparent', min: ['0', '0'], showSeparator: showSelector && !isSteppedLayout && !isSelectorCollapsed, start: splitterSizes, children: [showSelector ?
781
+ _jsxs(_Fragment, { children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs("div", { ref: floatingBarContainerRef, style: { position: 'relative', height: '100%', width: '100%' }, children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: isSteppedLayout ? 'hidden' : 'visible', separatorSize: Gutters.getGutters(), separatorActiveColor: 'transparent', separatorColor: 'transparent', min: ['0', '0'], showSeparator: showSelector && !isSteppedLayout && !isSelectorCollapsed, start: splitterSizes, children: [showSelector ?
774
782
  _jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, disableAccordionIfSingleCategory: disableAccordionIfSingleCategory, selectedTID: selectedSearchResultTID, selectedSearchResult: selectedSearchResult, autoSelectFirst: !isMobile || hasSingleDcmtType, onSelectionChanged: onSearchResultSelectionChanged }) })
775
783
  :
776
784
  _jsx(_Fragment, {}), _jsx(TMLayoutItem, { children: _jsx(TMSearchResultGrid, { openInOffice: openInOffice, fromDTD: fromDTD, operationItems: operationItems, allUsers: allUsers, inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, showExportForm: showExportForm, onFocusedItemChanged: handleFocusedItemChangedFromGrid, onDownloadDcmtsAsync: async (inputDcmts, downloadType, downloadMode, _y, confirmAttachments) => await downloadDcmtsAsync({ inputDcmts, downloadType, downloadMode, onFileDownloaded: onFileOpened, confirmAttachments }), lastUpdateSearchTime: lastUpdateSearchTime, searchResult: searchResults.length > 1 ? selectedSearchResult : searchResults[0], onSelectionChanged: (items) => { setSelectedItems(items); }, onDblClick: () => openFormHandler(LayoutModes.Update), showSearchTMDatagrid: showSearchTMDatagrid, onVisibleItemChanged: setVisibleItems, updateDataColumnsFromDataGrid: updateDataColumnsFromDataGrid, updateDataSourceFromDataGrid: updateDataSourceFromDataGrid, updateSelectedRowKeysFromDataGrid: updateSelectedRowKeysFromDataGrid, disableAutoFocus: autoFocusFirstRow === false && isFirstAutoFocusRef.current, dcmtsReturned: dcmtsReturned, dcmtsFound: dcmtsFound, showCounterConfig: showCounterConfig, counterConfig: counterConfig, showActionsColumn: showActionsColumn, compactPager: compactPager, onRowActionRequest: requestRowAction }) })] }), renderFloatingBar] }), _jsx(TMToppyDraggableHelpCenter, { usePortal: toppyHelpCenterUsePortal, isVisible: isToppyHelpCenterVisible, content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { dtd: fromDTD, deviceType: deviceType, onApprove: () => {
@@ -986,10 +994,10 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
986
994
  gap: Gutters.getGutters(),
987
995
  width: '100%',
988
996
  height: '100%',
989
- }, 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(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showCicoWaitPanel, showWaitPanelPrimary: showCicoPrimaryProgress, waitPanelTitle: cicoWaitPanelTitle, waitPanelTextPrimary: cicoPrimaryProgressText, waitPanelValuePrimary: cicoPrimaryProgressValue, waitPanelMaxValuePrimary: cicoPrimaryProgressMax, isCancelable: true, abortController: abortControllerLocal, children: (groupId && groupId.length > 0) ? panelManagerContent
990
- // Senza le prop di persistenza il provider si comporta come quello base:
991
- // i contesti che non ricordano il layout restano come prima
992
- : _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmSearchResult', isPersistenceEnabled: isLayoutPersisted && hasSearchResultPanelLayout(), persistPanelStates: isLayoutPersisted ? (state) => saveSearchResultPanelLayout(state, disabledLayoutPanelIds) : undefined, persistedPanelStates: isLayoutPersisted ? getSearchResultPanelLayout() : undefined, children: panelManagerContent }) }) }) }), renderDcmtOperations] }));
997
+ }, children: _jsx(TMLayoutContainer, { direction: 'vertical', children: (groupId && groupId.length > 0) ? panelManagerContent
998
+ // Senza le prop di persistenza il provider si comporta come quello base:
999
+ // i contesti che non ricordano il layout restano come prima
1000
+ : _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmSearchResult', isPersistenceEnabled: isLayoutPersisted && hasSearchResultPanelLayout(), persistPanelStates: isLayoutPersisted ? (state) => saveSearchResultPanelLayout(state, disabledLayoutPanelIds) : undefined, persistedPanelStates: isLayoutPersisted ? getSearchResultPanelLayout() : undefined, children: panelManagerContent }) }) }), renderDcmtOperations] }));
993
1001
  };
994
1002
  export default TMSearchResult;
995
1003
  /** Cerca una voce di operazione per id, anche dentro i sottomenu */
@@ -1395,11 +1403,13 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, i
1395
1403
  const gridSorting = useMemo(() => ({ mode: 'multiple' }), []);
1396
1404
  const gridSelection = useMemo(() => ({ mode: allowMultipleSelection ? 'multiple' : 'single' }), [allowMultipleSelection]);
1397
1405
  const useNativeScrollbar = SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar === 1;
1406
+ // Con pagine grandi (oltre la soglia impostata, default 500 righe) il rendering virtuale delle righe evita di creare nel DOM tutte le righe della pagina.
1407
+ const virtualRenderingThreshold = SDKUI_Globals.userSettings.searchSettings?.virtualRenderingThreshold ?? DEFAULT_VIRTUAL_RENDERING_THRESHOLD;
1398
1408
  const gridScrolling = useMemo(() => ({
1399
1409
  columnRenderingMode: 'virtual',
1400
- rowRenderingMode: 'standard',
1410
+ rowRenderingMode: pageSize > virtualRenderingThreshold ? 'virtual' : 'standard',
1401
1411
  useNative: useNativeScrollbar
1402
- }), [useNativeScrollbar]);
1412
+ }), [useNativeScrollbar, pageSize, virtualRenderingThreshold]);
1403
1413
  // Handles selection change in the data grid
1404
1414
  const handleSelectionChange = useCallback((e) => {
1405
1415
  if (onSelectionChanged === undefined)
@@ -1489,13 +1499,21 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, i
1489
1499
  ...columns.filter(col => col.dataField !== 'FILEEXT')
1490
1500
  ];
1491
1501
  }, [columns, onDownloadDcmtsAsync, openInOffice, showActionsColumn, actionsColumn]);
1502
+ // Ultime righe visibili pubblicate: contentReady può scattare a ogni passata di rendering,
1503
+ // si pubblica solo se le righe visibili sono cambiate (stessi oggetti nello stesso ordine = nessun cambio).
1504
+ const lastVisibleDataRef = useRef([]);
1492
1505
  const onContentReady = useCallback((e) => {
1493
1506
  if (e === undefined)
1494
1507
  return;
1495
- if (setVisibleItems === undefined)
1508
+ // Righe dati della pagina corrente (già filtrate/ordinate), indipendente dal rendering virtuale
1509
+ // (dove getVisibleRows() ha solo le righe a schermo): si scende solo nei gruppi aperti
1510
+ // (quelli chiusi hanno items = null) e si scartano gli oggetti gruppo
1511
+ const flatten = (items) => items.flatMap(item => Array.isArray(item?.items) ? flatten(item.items) : item?.rowIndex !== undefined ? [item] : []);
1512
+ const visibleData = flatten(e.component.getDataSource()?.items() ?? []);
1513
+ const last = lastVisibleDataRef.current;
1514
+ if (visibleData.length === last.length && visibleData.every((data, i) => data === last[i]))
1496
1515
  return;
1497
- const visibleRows = e.component.getVisibleRows();
1498
- const visibleData = visibleRows.map((row) => row.data);
1516
+ lastVisibleDataRef.current = visibleData;
1499
1517
  setVisibleItems(visibleData);
1500
1518
  }, []);
1501
1519
  useEffect(() => { onVisibleItemChanged?.(visibleItems); }, [visibleItems]);
@@ -22,6 +22,10 @@ const TMTreeDcmtTypeCell = ({ tid, isMobile }) => {
22
22
  }, [isMobile, dtd, tid]);
23
23
  return (_jsxs(StyledTreeDcmtTypeRow, { onMouseEnter: loadDTD, children: [_jsx("span", { style: { cursor: 'pointer', flex: 1, minWidth: 0 }, children: _jsx(TMTidViewer, { tid: tid, showIcon: false }) }), !isMobile && (_jsx("span", { className: 'info-icon', children: _jsx(TMDcmtTypeTooltip, { dtd: dtd, children: _jsx(IconInfo, { color: TMColors.info }) }) }))] }));
24
24
  };
25
+ // La ricerca e l'archiviazione hanno ciascuna il proprio albero predefinito: il contesto lo decide il layoutMode
26
+ const getDefaultTreeId = (layoutMode) => layoutMode == LayoutModes.Update
27
+ ? SDKUI_Globals.userSettings.searchSettings.defaultTree
28
+ : SDKUI_Globals.userSettings.archivingSettings.defaultTree;
25
29
  const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelectedTIDChanged, onClosePanel, allowMaximize = true, onMaximizePanel }) => {
26
30
  const [trees, setTrees] = useState([]);
27
31
  const [selectedTreeId, setSelectedTreeId] = useState(0);
@@ -35,8 +39,9 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
35
39
  const selectedTreeItemKeys = useMemo(() => selectedTreeItemKey !== undefined ? [selectedTreeItemKey] : [], [selectedTreeItemKey]);
36
40
  // Finche' gli alberi non sono arrivati il pannello mostra il loader invece della lista vuota
37
41
  const [isLoadingTrees, setIsLoadingTrees] = useState(true);
38
- const [isGridBoxOpened, setIsGridBoxOpened] = useState(false);
39
- const [defaultTreeId, setDefaultTreeId] = useState(-1);
42
+ const [defaultTreeId, setDefaultTreeId] = useState(() => getDefaultTreeId(layoutMode));
43
+ const dropDownBoxRef = useRef(null);
44
+ const closeDropDown = useCallback(() => { dropDownBoxRef.current?.instance()?.option('opened', false); }, []);
40
45
  const deviceType = useDeviceType();
41
46
  const isMobile = deviceType === DeviceType.MOBILE;
42
47
  const panelRef = useOutsideClick(() => setInfoDTD(undefined));
@@ -49,6 +54,11 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
49
54
  const loadTreesAsync = useCallback(async (forceRefresh = false) => {
50
55
  const isSearchContext = layoutMode == LayoutModes.Update;
51
56
  if (forceRefresh) {
57
+ // Gli alberi arrivano dal server filtrati sui tipi documento della sessione: senza rileggerli
58
+ // prima (RetrieveAll con refreshCache rigenera anche la cache lato server) un tipo documento
59
+ // appena creato da Designer non comparirebbe tra gli elementi dell'albero
60
+ DcmtTypeListCacheService.RemoveAllWithoutMetadata();
61
+ await DcmtTypeListCacheService.GetAllWithoutMetadataAsync();
52
62
  if (isSearchContext)
53
63
  TreeCacheService.RemoveAllSearch();
54
64
  else
@@ -74,18 +84,10 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
74
84
  setSelectedRowKeys([currentTreeId]);
75
85
  return;
76
86
  }
77
- let defaultTree = SDKUI_Globals.userSettings.searchSettings.defaultTree;
78
- let initialTreeId;
79
- let treeToSelect;
80
- if (defaultTree > 0) {
81
- initialTreeId = defaultTree;
82
- treeToSelect = result.find(o => o.id == defaultTree);
83
- }
84
- else {
85
- initialTreeId = result[0]?.id ?? 0;
86
- treeToSelect = result[0];
87
- }
88
- setSelectedTreeId(initialTreeId);
87
+ // Il predefinito puo' non essere piu' tra gli alberi del contesto (cancellato, o permessi cambiati): si ripiega sul primo
88
+ const defaultTree = getDefaultTreeId(layoutMode);
89
+ const treeToSelect = (defaultTree > 0 ? result.find(o => o.id == defaultTree) : undefined) ?? result[0];
90
+ setSelectedTreeId(treeToSelect?.id ?? 0);
89
91
  if (treeToSelect?.id) {
90
92
  setSelectedRowKeys([treeToSelect.id]);
91
93
  }
@@ -133,8 +135,8 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
133
135
  if (selectedKeys.length > 0)
134
136
  setSelectedTreeId(selectedKeys[0]);
135
137
  setSelectedRowKeys(selectedKeys);
136
- setIsGridBoxOpened(false);
137
- }, []);
138
+ closeDropDown();
139
+ }, [closeDropDown]);
138
140
  // Handles click on a tree row in the trees data grid: clicking the already selected tree
139
141
  // does not raise onSelectionChanged, so the drop down must be closed here as well
140
142
  const onRowClickTrees = useCallback((e) => {
@@ -143,8 +145,8 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
143
145
  return;
144
146
  setSelectedTreeId(tree.id);
145
147
  setSelectedRowKeys([tree.id]);
146
- setIsGridBoxOpened(false);
147
- }, []);
148
+ closeDropDown();
149
+ }, [closeDropDown]);
148
150
  // Handles focus change in the data grid
149
151
  const onFocusedRowChanged = useCallback((e) => {
150
152
  setFocusedRowKey(e.row?.key);
@@ -154,12 +156,6 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
154
156
  if (treeItemDescriptor?.id)
155
157
  setSelectedRowKeys([treeItemDescriptor.id]);
156
158
  }, []);
157
- const onGridBoxOpened = useCallback((e) => {
158
- if (e.name === 'opened') {
159
- setIsGridBoxOpened(e.value);
160
- }
161
- ;
162
- }, []);
163
159
  // Callback function to handle double-click events on a tree view cell
164
160
  const onCellDblClickTreeView = useCallback((e) => {
165
161
  // Extract the data from the clicked cell and cast it to the TreeItemDescriptor type
@@ -215,15 +211,15 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
215
211
  width: '100%',
216
212
  boxSizing: 'border-box',
217
213
  minHeight: 0,
218
- }, children: [_jsx("div", { style: { padding: '10px' }, children: _jsx(DropDownBox, { dropDownOptions: {
214
+ }, children: [_jsx("div", { style: { padding: '10px' }, children: _jsx(DropDownBox, { ref: dropDownBoxRef, dropDownOptions: {
219
215
  resizeEnabled: true,
220
216
  minWidth: "100%",
221
217
  height: trees.length <= 10 ? 300 : 500,
222
218
  maxWidth: "100%"
223
- }, value: selectedTreeId, opened: isGridBoxOpened, valueExpr: "id", displayExpr: "nameLoc", deferRendering: false, dataSource: trees, onValueChanged: syncDataGridSelection, onOptionChanged: onGridBoxOpened, style: { height: 30, padding: '5px' }, children: _jsx(TMDataGrid, { height: "100%", width: "100%", dataSource: trees, dataColumns: [
219
+ }, value: selectedTreeId, valueExpr: "id", displayExpr: "nameLoc", deferRendering: false, dataSource: trees, onValueChanged: syncDataGridSelection, style: { height: 30 }, children: _jsx(TMDataGrid, { height: "100%", width: "100%", dataSource: trees, dataColumns: [
224
220
  { dataField: 'nameLoc', caption: SDKUI_Localizator.Name, width: 'auto' },
225
221
  { dataField: 'description', caption: SDKUI_Localizator.Description, width: 'auto' },
226
- ], selection: { mode: 'single', showCheckBoxesMode: "none" }, showHeaderFilter: false, selectedRowKeys: selectedRowKeys, onSelectionChanged: onSelectionChanged, onRowClick: onRowClickTrees, focusedRowKey: focusedRowKey, onFocusedRowChanged: onFocusedRowChanged }) }) }), _jsxs(StyledTreeListWrapper, { children: [_jsxs(TreeList, { height: "100%", dataSource: treeItems, showRowLines: false, showColumnLines: false, showBorders: false, columnAutoWidth: false, keyExpr: "id", parentIdExpr: "parentID", dataStructure: "plain", showColumnHeaders: false, selectedRowKeys: selectedTreeItemKeys, onSelectionChanged: onSelectionChangedTreeView, onCellDblClick: onCellDblClickTreeView, onRowClick: onRowClickTreeView, children: [_jsx(Column, { dataField: "nameLoc", caption: SDKUI_Localizator.Name, cellRender: renderCell, width: "100%" }), _jsx(Scrolling, { mode: "virtual", useNative: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar) === 1 }), _jsx(Selection, { mode: "single" })] }), _jsxs(StyledOffCanvasPanel, { ref: panelRef, $isOpen: isMobile && infoDTD !== undefined, children: [_jsxs(StyledDivHorizontal, { style: { gap: 10, padding: '10px 8px', width: '100%', alignItems: 'center' }, children: [_jsx("p", { style: { fontSize: '1.1rem', fontWeight: 'bold' }, children: `${SDKUI_Localizator.DcmtType} - ${SDKUI_Localizator.About}` }), _jsx(IconCloseOutline, { style: { marginLeft: 'auto', cursor: 'pointer' }, onClick: () => setInfoDTD(undefined) })] }), renderDTDTooltipContent(infoDTD)] })] })] })
222
+ ], selection: { mode: 'single', showCheckBoxesMode: "none" }, showHeaderFilter: false, selectedRowKeys: selectedRowKeys, onSelectionChanged: onSelectionChanged, onRowClick: onRowClickTrees, focusedRowKey: focusedRowKey, onFocusedRowChanged: onFocusedRowChanged }) }) }), _jsxs(StyledTreeListWrapper, { children: [_jsxs(TreeList, { height: "100%", dataSource: treeItems, showRowLines: false, showColumnLines: false, showBorders: false, columnAutoWidth: false, keyExpr: "id", parentIdExpr: "parentID", dataStructure: "plain", showColumnHeaders: false, selectedRowKeys: selectedTreeItemKeys, onSelectionChanged: onSelectionChangedTreeView, onCellDblClick: onCellDblClickTreeView, onRowClick: onRowClickTreeView, children: [_jsx(Column, { dataField: "nameLoc", caption: SDKUI_Localizator.Name, cellRender: renderCell, width: "100%" }), _jsx(Scrolling, { mode: "standard", useNative: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar) === 1 }), _jsx(Selection, { mode: "single" })] }), _jsxs(StyledOffCanvasPanel, { ref: panelRef, $isOpen: isMobile && infoDTD !== undefined, children: [_jsxs(StyledDivHorizontal, { style: { gap: 10, padding: '10px 8px', width: '100%', alignItems: 'center' }, children: [_jsx("p", { style: { fontSize: '1.1rem', fontWeight: 'bold' }, children: `${SDKUI_Localizator.DcmtType} - ${SDKUI_Localizator.About}` }), _jsx(IconCloseOutline, { style: { marginLeft: 'auto', cursor: 'pointer' }, onClick: () => setInfoDTD(undefined) })] }), renderDTDTooltipContent(infoDTD)] })] })] })
227
223
  : isLoadingTrees
228
224
  ? _jsx(_Fragment, {})
229
225
  : _jsx("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%', fontSize: '1.5rem' }, children: SDKUI_Localizator.TreesNoAvailable }) }));
@@ -10,12 +10,13 @@ import TMDcmtIcon from "../documents/TMDcmtIcon";
10
10
  import TMDataGrid from "../../base/TMDataGrid";
11
11
  import TMDcmtForm from "../documents/TMDcmtForm";
12
12
  import { useDcmtOperations } from "../../../hooks/useDcmtOperations";
13
- import { TMLayoutWaitingContainer } from "../../base/TMWaitPanel";
13
+ import TMLayoutContainer from "../../base/TMLayout";
14
+ import TMWaitPanelManager from "../../base/waitPanel/TMWaitPanelManager";
14
15
  import { TMResultManager } from "../../forms/TMResultDialog";
15
16
  let abortLocalController = new AbortController();
16
17
  const TMViewHistoryDcmt = (props) => {
17
18
  const { deviceType, inputDcmt, onClose, fromDTD, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers } = props;
18
- const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync } = useDcmtOperations();
19
+ const { downloadDcmtsAsync } = useDcmtOperations();
19
20
  const [dcmtHistory, setDcmtHistory] = useState([]);
20
21
  // showId is a state variable that determines whether an ID-related component or feature should be displayed
21
22
  const [showId, setShowId] = useState(false);
@@ -33,18 +34,6 @@ const TMViewHistoryDcmt = (props) => {
33
34
  const [showDcmtForm, setShowDcmtForm] = useState(false);
34
35
  // Memoized value to get the selected draft based on the focused row key
35
36
  const selectedDcmt = useMemo(() => dcmtHistory.find(dcmt => dcmt.id === focusedRowKey), [focusedRowKey, dcmtHistory]);
36
- // State variable to control the visibility of the wait panel.
37
- const [showLocalWaitPanel, setShowLocalWaitPanel] = useState(false);
38
- // State variable to store the title of the wait panel.
39
- const [waitLocalPanelTitle, setWaitLocalPanelTitle] = useState('');
40
- // State variable to control the visibility of the primary section of the wait panel.
41
- const [showLocalPrimary, setShowLocalPrimary] = useState(false);
42
- // State variable to store the primary text of the wait panel.
43
- const [waitLocalPanelTextPrimary, setWaitLocalPanelTextPrimary] = useState('');
44
- // State variable to track the current value of the primary progress indicator in the wait panel.
45
- const [waitLocalPanelValuePrimary, setWaitLocalPanelValuePrimary] = useState(0);
46
- // State variable to define the maximum value for the primary progress indicator in the wait panel.
47
- const [waitLocalPanelMaxValuePrimary, setWaitLocalPanelMaxValuePrimary] = useState(0);
48
37
  const getParticipantById = (id, users) => {
49
38
  if (users.length === 0)
50
39
  return null;
@@ -155,18 +144,21 @@ const TMViewHistoryDcmt = (props) => {
155
144
  onButtonClick: async (e) => {
156
145
  if (e !== ButtonNames.YES)
157
146
  return;
158
- setWaitLocalPanelTitle(SDKUI_Localizator.Delete);
159
- setShowLocalWaitPanel(true);
160
- setShowLocalPrimary(true);
161
147
  abortLocalController = new AbortController();
148
+ const panel = TMWaitPanelManager.show({
149
+ title: SDKUI_Localizator.Delete,
150
+ max: 1,
151
+ showCounters: false,
152
+ cancelable: true,
153
+ onAbort: () => abortLocalController.abort(),
154
+ });
162
155
  let result = [];
163
156
  let i = 0;
164
- setWaitLocalPanelMaxValuePrimary(1);
165
157
  if (abortLocalController.signal.aborted) {
166
158
  result.push({ rowIndex: i, id1: currentDcmt.id, id2: currentDcmt.id, resultType: ResultTypes.WARNING, description: `Operazione interrotta. Elaborate ${i}` });
167
159
  }
168
160
  else {
169
- setWaitLocalPanelTextPrimary(SDKUI_Localizator.Delete);
161
+ panel.setSubtitle(SDKUI_Localizator.Delete);
170
162
  const deleteEngine = new DeleteEngine(SDK_Globals.tmSession);
171
163
  await deleteEngine.PhysDeleteByIDAsync(Number(currentDcmt.TID), Number(currentDcmt.DID), false)
172
164
  .then(async () => {
@@ -178,10 +170,7 @@ const TMViewHistoryDcmt = (props) => {
178
170
  });
179
171
  }
180
172
  setFocusedRowKey(undefined);
181
- setWaitLocalPanelTextPrimary('');
182
- setWaitLocalPanelMaxValuePrimary(0);
183
- setWaitLocalPanelValuePrimary(0);
184
- setShowLocalWaitPanel(false);
173
+ panel.close();
185
174
  TMResultManager.show(result, SDKUI_Localizator.Delete, "ID", undefined);
186
175
  }
187
176
  });
@@ -279,7 +268,7 @@ const TMViewHistoryDcmt = (props) => {
279
268
  { dataField: "LastUpdateTime", caption: SDKUI_Localizator.LastUpdateTime, dataType: 'datetime', format: 'dd/MM/yyyy HH:mm:ss', },
280
269
  ]);
281
270
  }, [showId]);
282
- return _jsx(TMModal, { title: `${SDKUI_Localizator.SearchResult} \u2014 ${SDKUI_Localizator.History + ": " + (fromDTD.nameLoc ?? SDKUI_Localizator.Document) + " (DID:" + inputDcmt.DID})`, width: calcResponsiveSizes(deviceType, '700px', '700px', '95%'), height: calcResponsiveSizes(deviceType, '80%', '80%', '95%'), onClose: onClose, 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: _jsxs(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showLocalWaitPanel, showWaitPanelPrimary: showLocalPrimary, waitPanelTitle: waitLocalPanelTitle, waitPanelTextPrimary: waitLocalPanelTextPrimary, waitPanelValuePrimary: waitLocalPanelValuePrimary, waitPanelMaxValuePrimary: waitLocalPanelMaxValuePrimary, isCancelable: true, abortController: abortLocalController, children: [_jsx(TMDataGrid, { dataSource: dcmtHistory, dataColumns: dataColumns, focusedRowKey: focusedRowKey, selection: selection, customContextMenuItems: customContextMenuItems, onFocusedRowChanged: onFocusedRowChanged, onCellDblClick: onCellDblClick, noDataText: SDKUI_Localizator.NoDataToDisplay, showSearchPanel: showSearch }), (showDcmtForm && selectedDcmt !== undefined) &&
283
- _jsx(TMDcmtForm, { TID: Number(selectedDcmt.TID), DID: Number(selectedDcmt.DID), formMode: FormModes.ReadOnly, isModal: true, widthModal: "95%", heightModal: "95%", titleModal: fromDTD.name ?? SDKUI_Localizator.SearchResult, allowNavigation: dcmtHistory.length > 0, itemIndex: selectedIndex + 1, count: dcmtHistory.length, onClose: () => { setShowDcmtForm(false); }, canNext: canNavigateHandler('next'), canPrev: canNavigateHandler('prev'), onNext: () => onNavigateHandler('next'), onPrev: () => onNavigateHandler('prev'), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks ?? [], Number(selectedDcmt.TID), Number(selectedDcmt.DID)) })] }) }) });
271
+ return _jsx(TMModal, { title: `${SDKUI_Localizator.SearchResult} \u2014 ${SDKUI_Localizator.History + ": " + (fromDTD.nameLoc ?? SDKUI_Localizator.Document) + " (DID:" + inputDcmt.DID})`, width: calcResponsiveSizes(deviceType, '700px', '700px', '95%'), height: calcResponsiveSizes(deviceType, '80%', '80%', '95%'), onClose: onClose, children: _jsxs(TMLayoutContainer, { direction: 'vertical', children: [_jsx(TMDataGrid, { dataSource: dcmtHistory, dataColumns: dataColumns, focusedRowKey: focusedRowKey, selection: selection, customContextMenuItems: customContextMenuItems, onFocusedRowChanged: onFocusedRowChanged, onCellDblClick: onCellDblClick, noDataText: SDKUI_Localizator.NoDataToDisplay, showSearchPanel: showSearch }), (showDcmtForm && selectedDcmt !== undefined) &&
272
+ _jsx(TMDcmtForm, { TID: Number(selectedDcmt.TID), DID: Number(selectedDcmt.DID), formMode: FormModes.ReadOnly, isModal: true, widthModal: "95%", heightModal: "95%", titleModal: fromDTD.name ?? SDKUI_Localizator.SearchResult, allowNavigation: dcmtHistory.length > 0, itemIndex: selectedIndex + 1, count: dcmtHistory.length, onClose: () => { setShowDcmtForm(false); }, canNext: canNavigateHandler('next'), canPrev: canNavigateHandler('prev'), onNext: () => onNavigateHandler('next'), onPrev: () => onNavigateHandler('prev'), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks ?? [], Number(selectedDcmt.TID), Number(selectedDcmt.DID)) })] }) });
284
273
  };
285
274
  export default TMViewHistoryDcmt;