@topconsultnpm/sdkui-react 6.22.0-dev3.9 → 6.22.0-dev4.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/base/TMAlert.js +6 -8
- package/lib/components/base/TMAreaManager.js +53 -55
- package/lib/components/base/TMButton.js +4 -2
- package/lib/components/base/TMCounterContainer.d.ts +3 -1
- package/lib/components/base/TMCounterContainer.js +16 -1
- package/lib/components/base/TMCustomButton.js +40 -48
- package/lib/components/base/TMDataGrid.js +24 -4
- package/lib/components/base/TMPanel.js +173 -170
- package/lib/components/base/TMSpinner.d.ts +2 -1
- package/lib/components/base/TMSpinner.js +9 -7
- package/lib/components/base/TMTabControl.d.ts +5 -0
- package/lib/components/base/TMTabControl.js +18 -7
- package/lib/components/base/TMTreeView.js +20 -0
- package/lib/components/base/TMWaitPanel.js +1 -1
- package/lib/components/base/waitPanel/TMWaitPanelConfirm.d.ts +12 -0
- package/lib/components/base/waitPanel/TMWaitPanelConfirm.js +185 -0
- package/lib/components/base/waitPanel/TMWaitPanelManager.d.ts +179 -0
- package/lib/components/base/waitPanel/TMWaitPanelManager.js +373 -0
- package/lib/components/base/waitPanel/TMWaitPanelView.d.ts +58 -0
- package/lib/components/base/waitPanel/TMWaitPanelView.js +346 -0
- package/lib/components/base/waitPanel/index.d.ts +1 -0
- package/lib/components/base/waitPanel/index.js +1 -0
- package/lib/components/choosers/TMDistinctValues.js +3 -3
- package/lib/components/choosers/TMPathChooser.js +17 -34
- package/lib/components/editors/TMTextBox.d.ts +4 -0
- package/lib/components/editors/TMTextBox.js +99 -11
- package/lib/components/features/archive/TMArchive.js +7 -2
- package/lib/components/features/assistant/TMHelpOnLineChat.d.ts +28 -0
- package/lib/components/features/assistant/TMHelpOnLineChat.js +1231 -0
- package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +2 -2
- package/lib/components/features/documents/TMBatchUpdateForm.js +3 -4
- package/lib/components/features/documents/TMCopyToFolderForm.js +53 -84
- package/lib/components/features/documents/TMDcmtForm.js +50 -61
- package/lib/components/features/documents/TMDcmtIcon.d.ts +1 -3
- package/lib/components/features/documents/TMDcmtIcon.js +3 -5
- package/lib/components/features/documents/TMDcmtPreview.js +5 -3
- package/lib/components/features/documents/TMDcmtTasks.js +2 -9
- package/lib/components/features/documents/TMFileUploader.js +26 -26
- package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
- package/lib/components/features/documents/TMMasterDetailDcmts.js +53 -148
- package/lib/components/features/documents/TMMasterInfoFields.js +3 -2
- package/lib/components/features/documents/TMMergeToPdfForm.js +52 -56
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +14 -15
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +1 -1
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +3 -3
- package/lib/components/features/documents/TMRelationViewer.d.ts +13 -14
- package/lib/components/features/documents/TMRelationViewer.js +206 -143
- package/lib/components/features/documents/relationTreeState.d.ts +32 -0
- package/lib/components/features/documents/relationTreeState.js +89 -0
- package/lib/components/features/search/TMSearch.js +3 -4
- package/lib/components/features/search/TMSearchQueryPanel.js +0 -4
- package/lib/components/features/search/TMSearchResult.d.ts +5 -0
- package/lib/components/features/search/TMSearchResult.js +51 -24
- package/lib/components/features/search/TMTreeSelector.js +23 -27
- package/lib/components/features/search/TMViewHistoryDcmt.js +15 -26
- package/lib/components/features/tasks/TMTasksView.js +97 -90
- package/lib/components/features/wg/TMWGsCopyMoveForm.js +104 -100
- package/lib/components/forms/TMResultDialog.js +1 -1
- package/lib/components/grids/TMBlogsPost.js +93 -97
- package/lib/components/index.d.ts +5 -1
- package/lib/components/index.js +4 -1
- package/lib/components/layout/panelManager/TMPanelManagerContainer.js +16 -15
- package/lib/components/layout/panelManager/TMPanelManagerContext.d.ts +1 -0
- package/lib/components/layout/panelManager/TMPanelManagerContext.js +5 -1
- package/lib/components/layout/panelManager/TMPanelManagerLoader.d.ts +6 -0
- package/lib/components/layout/panelManager/TMPanelManagerLoader.js +18 -0
- package/lib/components/layout/panelManager/TMPanelManagerToolbar.js +4 -8
- package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.d.ts +1 -1
- package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.js +2 -1
- package/lib/components/pages/TMPage.js +32 -31
- package/lib/components/query/TMQueryEditor.d.ts +3 -0
- package/lib/components/query/TMQueryEditor.js +2 -1
- package/lib/components/sidebar/TMHeader.d.ts +1 -0
- package/lib/components/sidebar/TMHeader.js +2 -2
- package/lib/helper/Enum_Localizator.js +1 -0
- package/lib/helper/SDKUI_Globals.d.ts +7 -2
- package/lib/helper/SDKUI_Globals.js +7 -2
- package/lib/helper/SDKUI_Localizator.d.ts +31 -6
- package/lib/helper/SDKUI_Localizator.js +301 -51
- package/lib/helper/ZipManager.d.ts +1 -1
- package/lib/helper/ZipManager.js +2 -1
- package/lib/helper/checkinCheckoutManager.js +2 -3
- package/lib/helper/dcmtsHelper.d.ts +2 -0
- package/lib/helper/dcmtsHelper.js +3 -1
- package/lib/hooks/useCheckInOutOperations.d.ts +0 -6
- package/lib/hooks/useCheckInOutOperations.js +16 -37
- package/lib/hooks/useDcmtOperations.d.ts +3 -19
- package/lib/hooks/useDcmtOperations.js +175 -229
- package/lib/hooks/useDocumentOperations.d.ts +1 -0
- package/lib/hooks/useDocumentOperations.js +16 -29
- package/lib/hooks/useMultiMasterDetailDcmts.d.ts +0 -15
- package/lib/hooks/useMultiMasterDetailDcmts.js +70 -68
- package/lib/hooks/usePreventFileDrop.js +9 -0
- package/lib/hooks/useWorkflowApprove.js +33 -17
- package/lib/services/caseflow/CaseFlowService.d.ts +69 -9
- package/lib/services/caseflow/CaseFlowService.js +126 -58
- package/package.json +2 -2
|
@@ -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
|
-
//
|
|
398
|
-
//
|
|
399
|
-
if (
|
|
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,8 +3,8 @@ 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';
|
|
7
|
-
import { CounterItemKey } from '../../base/TMCounterContainer';
|
|
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, VIRTUAL_RENDERING_THRESHOLD, VIRTUAL_RENDERING_CELL_THRESHOLD } from '../../../helper';
|
|
7
|
+
import { CounterItemKey, formatCount } from '../../base/TMCounterContainer';
|
|
8
8
|
import { getDcmtCicoStatus } from '../../../helper/checkinCheckoutManager';
|
|
9
9
|
import { DcmtOperationTypes, SearchResultContext, } from '../../../ts';
|
|
10
10
|
import { Gutters, TMColors } from '../../../utils/theme';
|
|
@@ -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,
|
|
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:
|
|
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(
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
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,16 @@ 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
|
+
// Rendering virtuale delle righe oltre VIRTUAL_RENDERING_THRESHOLD righe o VIRTUAL_RENDERING_CELL_THRESHOLD celle (righe effettive × colonne)
|
|
1407
|
+
const pageRowCount = Math.min(pageSize, dataSource?.length ?? 0);
|
|
1408
|
+
// +1 per la colonna icona (FILEEXT) sempre presente
|
|
1409
|
+
const visibleColumnCount = columns.filter(col => col.visible !== false && col.dataField !== 'FILEEXT').length + 1;
|
|
1410
|
+
const useVirtualRows = pageRowCount > VIRTUAL_RENDERING_THRESHOLD || pageRowCount * visibleColumnCount > VIRTUAL_RENDERING_CELL_THRESHOLD;
|
|
1398
1411
|
const gridScrolling = useMemo(() => ({
|
|
1399
1412
|
columnRenderingMode: 'virtual',
|
|
1400
|
-
rowRenderingMode: 'standard',
|
|
1413
|
+
rowRenderingMode: useVirtualRows ? 'virtual' : 'standard',
|
|
1401
1414
|
useNative: useNativeScrollbar
|
|
1402
|
-
}), [useNativeScrollbar]);
|
|
1415
|
+
}), [useNativeScrollbar, useVirtualRows]);
|
|
1403
1416
|
// Handles selection change in the data grid
|
|
1404
1417
|
const handleSelectionChange = useCallback((e) => {
|
|
1405
1418
|
if (onSelectionChanged === undefined)
|
|
@@ -1410,8 +1423,14 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, i
|
|
|
1410
1423
|
// Handles focus change in the data grid
|
|
1411
1424
|
const handleFocusedRowChange = useCallback((e) => {
|
|
1412
1425
|
// Non bloccare mai questo handler: è chiamato quando l'utente clicca su una riga
|
|
1413
|
-
|
|
1414
|
-
|
|
1426
|
+
// Con il rendering virtuale la riga su cui il cambio pagina sposta il fuoco può non essere ancora disegnata:
|
|
1427
|
+
// e.row è undefined e il documento si ricava dalla chiave (altrimenti focusedRowKey ricadrebbe su 0, cioè pagina 1)
|
|
1428
|
+
const rowData = e.row?.data ?? dataSource?.find(item => item.rowIndex === e.component.option('focusedRowKey'));
|
|
1429
|
+
// La prop controllata va allineata subito: finché resta sulla riga precedente, il wrapper React
|
|
1430
|
+
// riporta lì il fuoco e autoNavigateToFocusedRow riporta la griglia alla sua pagina
|
|
1431
|
+
setFocusedItem(rowData);
|
|
1432
|
+
onFocusedItemChanged?.(rowData);
|
|
1433
|
+
}, [onFocusedItemChanged, dataSource]);
|
|
1415
1434
|
// Handler for double-click row event
|
|
1416
1435
|
const onRowDblClick = useCallback((e) => {
|
|
1417
1436
|
if (onDblClick === undefined)
|
|
@@ -1489,13 +1508,21 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, i
|
|
|
1489
1508
|
...columns.filter(col => col.dataField !== 'FILEEXT')
|
|
1490
1509
|
];
|
|
1491
1510
|
}, [columns, onDownloadDcmtsAsync, openInOffice, showActionsColumn, actionsColumn]);
|
|
1511
|
+
// Ultime righe visibili pubblicate: contentReady può scattare a ogni passata di rendering,
|
|
1512
|
+
// si pubblica solo se le righe visibili sono cambiate (stessi oggetti nello stesso ordine = nessun cambio).
|
|
1513
|
+
const lastVisibleDataRef = useRef([]);
|
|
1492
1514
|
const onContentReady = useCallback((e) => {
|
|
1493
1515
|
if (e === undefined)
|
|
1494
1516
|
return;
|
|
1495
|
-
|
|
1517
|
+
// Righe dati della pagina corrente (già filtrate/ordinate), indipendente dal rendering virtuale
|
|
1518
|
+
// (dove getVisibleRows() ha solo le righe a schermo): si scende solo nei gruppi aperti
|
|
1519
|
+
// (quelli chiusi hanno items = null) e si scartano gli oggetti gruppo
|
|
1520
|
+
const flatten = (items) => items.flatMap(item => Array.isArray(item?.items) ? flatten(item.items) : item?.rowIndex !== undefined ? [item] : []);
|
|
1521
|
+
const visibleData = flatten(e.component.getDataSource()?.items() ?? []);
|
|
1522
|
+
const last = lastVisibleDataRef.current;
|
|
1523
|
+
if (visibleData.length === last.length && visibleData.every((data, i) => data === last[i]))
|
|
1496
1524
|
return;
|
|
1497
|
-
|
|
1498
|
-
const visibleData = visibleRows.map((row) => row.data);
|
|
1525
|
+
lastVisibleDataRef.current = visibleData;
|
|
1499
1526
|
setVisibleItems(visibleData);
|
|
1500
1527
|
}, []);
|
|
1501
1528
|
useEffect(() => { onVisibleItemChanged?.(visibleItems); }, [visibleItems]);
|
|
@@ -1504,8 +1531,8 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, i
|
|
|
1504
1531
|
[CounterItemKey.allItems, {
|
|
1505
1532
|
key: CounterItemKey.allItems,
|
|
1506
1533
|
show: true,
|
|
1507
|
-
caption: `${dcmtsReturned} restituiti su ${dcmtsFound} trovati`,
|
|
1508
|
-
value: `${dcmtsReturned}/${dcmtsFound}`,
|
|
1534
|
+
caption: `${formatCount(dcmtsReturned)} restituiti su ${formatCount(dcmtsFound)} trovati`,
|
|
1535
|
+
value: `${formatCount(dcmtsReturned)}/${formatCount(dcmtsFound)}`,
|
|
1509
1536
|
icon: _jsx(IconAll, {}),
|
|
1510
1537
|
order: -1
|
|
1511
1538
|
}]
|
|
@@ -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 [
|
|
39
|
-
const
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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: "
|
|
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
|
|
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 {
|
|
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
|
-
result.push({ rowIndex: i, id1: currentDcmt.id, id2: currentDcmt.id, resultType: ResultTypes.WARNING, description:
|
|
158
|
+
result.push({ rowIndex: i, id1: currentDcmt.id, id2: currentDcmt.id, resultType: ResultTypes.WARNING, description: SDKUI_Localizator.OperationItemsInterrupted.replaceParams(i) });
|
|
167
159
|
}
|
|
168
160
|
else {
|
|
169
|
-
|
|
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
|
-
|
|
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:
|
|
283
|
-
|
|
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;
|