@topconsultnpm/sdkui-react 6.22.0-dev3.4 → 6.22.0-dev3.6
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.
|
@@ -90,12 +90,19 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
90
90
|
setIsCheckingFirstLoad(false);
|
|
91
91
|
handleBack();
|
|
92
92
|
}, [handleBack]);
|
|
93
|
+
// Avanzamento del calcolo correlazioni, mostrato nell'overlay di primo caricamento
|
|
94
|
+
const [relationsProgress, setRelationsProgress] = useState({ value: 0, max: 0 });
|
|
95
|
+
const handleRelationsProgress = useCallback((value, max) => {
|
|
96
|
+
setRelationsProgress({ value, max });
|
|
97
|
+
}, []);
|
|
93
98
|
// Notifica all'utente che i dati mostrati sono parziali (non quando si sta uscendo)
|
|
94
|
-
const handleRelationsCalculationStopped = useCallback(() => {
|
|
99
|
+
const handleRelationsCalculationStopped = useCallback((loadedCount, totalCount) => {
|
|
95
100
|
if (isLeavingRef.current)
|
|
96
101
|
return;
|
|
102
|
+
// Con piu' documenti in input, indica quanti sono stati completati (es. "3/10")
|
|
103
|
+
const progress = totalCount > 1 ? ` (${loadedCount}/${totalCount})` : '';
|
|
97
104
|
ShowAlert({
|
|
98
|
-
message: SDKUI_Localizator.RelationsCalculationStopped
|
|
105
|
+
message: `${SDKUI_Localizator.RelationsCalculationStopped}${progress}`,
|
|
99
106
|
title: SDKUI_Localizator.Attention,
|
|
100
107
|
duration: 4000,
|
|
101
108
|
mode: 'info',
|
|
@@ -379,7 +386,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
379
386
|
setContextMenuVisible(true);
|
|
380
387
|
}, children: [_jsx(TMRelationViewerWrapper, { refreshKey: refreshKey, inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, showZeroDcmts: showZeroDcmts,
|
|
381
388
|
// customItemRender={customItemRender}
|
|
382
|
-
allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound, onItemContextMenu: isRelationViewerLoading ? undefined : onItemContextMenu, focusedItemFormData: focusedItemFormData, onLoadingStateChanged: setIsRelationViewerLoading, onStopCalculationReady: handleStopCalculationReady, onCalculationStopped: handleRelationsCalculationStopped }), _jsx(TMContextMenu, { items: operationItems, externalControl: {
|
|
389
|
+
allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound, onItemContextMenu: isRelationViewerLoading ? undefined : onItemContextMenu, focusedItemFormData: focusedItemFormData, onLoadingStateChanged: setIsRelationViewerLoading, onLoadingProgress: handleRelationsProgress, onStopCalculationReady: handleStopCalculationReady, onCalculationStopped: handleRelationsCalculationStopped }), _jsx(TMContextMenu, { items: operationItems, externalControl: {
|
|
383
390
|
visible: contextMenuVisible,
|
|
384
391
|
position: contextMenuPosition,
|
|
385
392
|
onClose: () => setContextMenuVisible(false)
|
|
@@ -463,7 +470,9 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
463
470
|
toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
|
|
464
471
|
}
|
|
465
472
|
], [tmTreeView, tmFormOrResult, focusedItem?.isDcmt, dtdMaster]);
|
|
466
|
-
return (_jsxs("div", { style: { width: '100%', height: '100%', position: 'relative' }, children: [isCheckingFirstLoad && (_jsx(TMLoadingOverlay, { onCancel: handleCancelFirstLoad, onStop: handleStopRelationsCalculation
|
|
473
|
+
return (_jsxs("div", { style: { width: '100%', height: '100%', position: 'relative' }, children: [isCheckingFirstLoad && (_jsx(TMLoadingOverlay, { onCancel: handleCancelFirstLoad, onStop: handleStopRelationsCalculation, description: relationsProgress.max > 1
|
|
474
|
+
? `${isForMaster ? SDKUI_Localizator.LoadingMasterDocuments : SDKUI_Localizator.LoadingDetailDocuments} (${relationsProgress.value}/${relationsProgress.max})`
|
|
475
|
+
: undefined, progressValue: relationsProgress.value, progressMax: relationsProgress.max })), _jsxs("div", { style: isCheckingFirstLoad ? { position: 'absolute', width: 0, height: 0, overflow: 'hidden', opacity: 0, pointerEvents: 'none' } : { width: '100%', height: '100%' }, children: [_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }), renderDcmtOperations, renderFloatingBar] })] }));
|
|
467
476
|
};
|
|
468
477
|
export default TMMasterDetailDcmts;
|
|
469
478
|
/**
|
|
@@ -472,7 +481,7 @@ export default TMMasterDetailDcmts;
|
|
|
472
481
|
* - Panel visibility toggling
|
|
473
482
|
* - Focus delay handling
|
|
474
483
|
*/
|
|
475
|
-
const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound, onItemContextMenu, focusedItemFormData, onLoadingStateChanged, onStopCalculationReady, onCalculationStopped }) => {
|
|
484
|
+
const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound, onItemContextMenu, focusedItemFormData, onLoadingStateChanged, onLoadingProgress, onStopCalculationReady, onCalculationStopped }) => {
|
|
476
485
|
const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
|
|
477
486
|
// Monitor device type changes to restore panel visibility when switching from mobile to desktop
|
|
478
487
|
const deviceType = useDeviceType();
|
|
@@ -532,7 +541,7 @@ const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurr
|
|
|
532
541
|
onItemContextMenu?.(item, e);
|
|
533
542
|
}, 100);
|
|
534
543
|
}, [onItemContextMenu, handleFocusedItemChanged]);
|
|
535
|
-
return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, showExpandAllButton: true, onNoRelationsFound: onNoRelationsFound, onItemContextMenu: onContextMenu, focusedItemFormData: focusedItemFormData, onLoadingStateChanged: onLoadingStateChanged, onStopCalculationReady: onStopCalculationReady, onCalculationStopped: onCalculationStopped }, refreshKey));
|
|
544
|
+
return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, showExpandAllButton: true, onNoRelationsFound: onNoRelationsFound, onItemContextMenu: onContextMenu, focusedItemFormData: focusedItemFormData, onLoadingStateChanged: onLoadingStateChanged, onLoadingProgress: onLoadingProgress, onStopCalculationReady: onStopCalculationReady, onCalculationStopped: onCalculationStopped }, refreshKey));
|
|
536
545
|
};
|
|
537
546
|
const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid, onRefreshSearchResults, handleNavigateToReference, fetchRemoteCertificates }) => {
|
|
538
547
|
const { setPanelVisibilityById } = useTMPanelManagerContext();
|
|
@@ -542,7 +551,11 @@ const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCrea
|
|
|
542
551
|
}, fetchRemoteCertificates: fetchRemoteCertificates }, refreshKey) :
|
|
543
552
|
focusedItem?.searchResult === undefined ? (_jsx(TMPanel, { title: SDKUI_Localizator.SearchResult, children: _jsx(TMToppyMessage, { message: SDKUI_Localizator.SelectDocumentToViewSearchResults }) })) : (_jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, autoFocusFirstRow: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, enablePinIcons: false, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, showBackButton: false, onRefreshSearchAsyncDatagrid: onRefreshSearchResults, onReferenceClick: handleNavigateToReference, fetchRemoteCertificates: fetchRemoteCertificates }, refreshKey)) }));
|
|
544
553
|
};
|
|
545
|
-
const TMLoadingOverlay = ({ onCancel, onStop, description, cancelText, stopText }) => {
|
|
554
|
+
const TMLoadingOverlay = ({ onCancel, onStop, description, cancelText, stopText, progressValue, progressMax }) => {
|
|
555
|
+
// Stesso calcolo di TMWaitPanel: 0 quando il massimo non è ancora noto
|
|
556
|
+
const progressPercent = (progressMax ?? 0) > 0
|
|
557
|
+
? Math.min(100, ((progressValue ?? 0) / (progressMax ?? 1)) * 100)
|
|
558
|
+
: 0;
|
|
546
559
|
return (_jsx("div", { style: {
|
|
547
560
|
position: 'absolute',
|
|
548
561
|
top: 0,
|
|
@@ -612,7 +625,7 @@ const TMLoadingOverlay = ({ onCancel, onStop, description, cancelText, stopText
|
|
|
612
625
|
.tm-spinner-animation div:nth-child(7):after { top: 63px; left: 17px; background: #782b7d; }
|
|
613
626
|
.tm-spinner-animation div:nth-child(8) { animation-delay: -0.288s; }
|
|
614
627
|
.tm-spinner-animation div:nth-child(8):after { top: 56px; left: 12px; background: #782b7d; }
|
|
615
|
-
` }), _jsxs("div", { className: "tm-spinner-animation", children: [_jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {})] })] }), _jsx("span", { style: { fontSize: '14px', color: '#334155', textAlign: 'center' }, children: description ?? SDKUI_Localizator.Loading }), (onStop || onCancel) && (_jsxs("div", { style: { marginTop: '4px', display: 'flex', alignItems: 'center', justifyContent: 'center', flexWrap: 'wrap', gap: '10px' }, children: [onStop && (_jsx("button", { onClick: onStop, title: SDKUI_Localizator.StopRelationsCalculation, style: {
|
|
628
|
+
` }), _jsxs("div", { className: "tm-spinner-animation", children: [_jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {}), _jsx("div", {})] })] }), _jsx("span", { style: { fontSize: '14px', color: '#334155', textAlign: 'center' }, children: description ?? SDKUI_Localizator.Loading }), (progressMax ?? 0) > 1 && (_jsxs("div", { style: { width: '260px' }, children: [_jsx("div", { style: { width: '100%', height: '20px', background: '#e0e0e0', borderRadius: '10px', overflow: 'hidden' }, children: _jsx("div", { style: { width: `${progressPercent.toFixed(2)}%`, height: '100%', background: '#4caf50', transition: 'width 0.3s ease' } }) }), _jsxs("p", { style: { fontWeight: 'bold', color: '#333', margin: '8px 0 0', textAlign: 'center' }, children: [progressPercent.toFixed(2), "%"] })] })), (onStop || onCancel) && (_jsxs("div", { style: { marginTop: '4px', display: 'flex', alignItems: 'center', justifyContent: 'center', flexWrap: 'wrap', gap: '10px' }, children: [onStop && (_jsx("button", { onClick: onStop, title: SDKUI_Localizator.StopRelationsCalculation, style: {
|
|
616
629
|
padding: '8px 24px',
|
|
617
630
|
fontSize: '13px',
|
|
618
631
|
fontWeight: 500,
|
|
@@ -132,6 +132,11 @@ export interface TMRelationViewerProps {
|
|
|
132
132
|
* Useful to disable interactions (like context menu) during loading.
|
|
133
133
|
*/
|
|
134
134
|
onLoadingStateChanged?: (isLoading: boolean) => void;
|
|
135
|
+
/**
|
|
136
|
+
* Invoked while the initial correlations load progresses, with how many input
|
|
137
|
+
* documents have been processed out of the total.
|
|
138
|
+
*/
|
|
139
|
+
onLoadingProgress?: (value: number, max: number) => void;
|
|
135
140
|
/**
|
|
136
141
|
* Invoked on mount to hand over a function that stops the ongoing correlations
|
|
137
142
|
* calculation: no further GetMetadata calls are performed and only the
|
|
@@ -143,8 +148,9 @@ export interface TMRelationViewerProps {
|
|
|
143
148
|
/**
|
|
144
149
|
* Callback invoked when the calculation has actually been stopped
|
|
145
150
|
* (loadData terminated after an abort request).
|
|
151
|
+
* Riceve quanti documenti di input sono stati completati sul totale.
|
|
146
152
|
*/
|
|
147
|
-
onCalculationStopped?: () => void;
|
|
153
|
+
onCalculationStopped?: (loadedCount: number, totalCount: number) => void;
|
|
148
154
|
}
|
|
149
155
|
/**
|
|
150
156
|
* Check if document type has detail relations
|
|
@@ -160,8 +166,10 @@ export declare const hasMasterRelations: (dTID: number | undefined) => Promise<b
|
|
|
160
166
|
export declare const getDisplayValueByColumn: (col: DataColumnDescriptor | undefined, value: any) => any;
|
|
161
167
|
/**
|
|
162
168
|
* Convert SearchResultDescriptor to structured data source with metadata
|
|
163
|
-
*
|
|
164
|
-
*
|
|
169
|
+
* I valori dei documenti sono GIÀ presenti nelle righe restituite dalla ricerca:
|
|
170
|
+
* qui vengono solo abbinati ai rispettivi MetadataDescriptor (perm,
|
|
171
|
+
* isSpecialSearchOutput, ...), risolti UNA SOLA VOLTA per tipo documento.
|
|
172
|
+
* Nessuna chiamata al server per riga.
|
|
165
173
|
*/
|
|
166
174
|
export declare const searchResultToDataSource: (searchResult: SearchResultDescriptor | undefined, hideSysMetadata?: boolean, signal?: AbortSignal) => Promise<any[]>;
|
|
167
175
|
export declare const DEFAULT_RELATION_EXPAND_LEVEL = 4;
|
|
@@ -67,8 +67,10 @@ export const getDisplayValueByColumn = (col, value) => {
|
|
|
67
67
|
};
|
|
68
68
|
/**
|
|
69
69
|
* Convert SearchResultDescriptor to structured data source with metadata
|
|
70
|
-
*
|
|
71
|
-
*
|
|
70
|
+
* I valori dei documenti sono GIÀ presenti nelle righe restituite dalla ricerca:
|
|
71
|
+
* qui vengono solo abbinati ai rispettivi MetadataDescriptor (perm,
|
|
72
|
+
* isSpecialSearchOutput, ...), risolti UNA SOLA VOLTA per tipo documento.
|
|
73
|
+
* Nessuna chiamata al server per riga.
|
|
72
74
|
*/
|
|
73
75
|
export const searchResultToDataSource = async (searchResult, hideSysMetadata, signal) => {
|
|
74
76
|
const rows = searchResult?.dtdResult?.rows ?? [];
|
|
@@ -77,27 +79,28 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata, si
|
|
|
77
79
|
const columns = searchResult?.dtdResult?.columns ?? [];
|
|
78
80
|
const tidColIndex = columns.findIndex(col => col.caption?.toUpperCase() === 'TID');
|
|
79
81
|
const didColIndex = columns.findIndex(col => col.caption?.toUpperCase() === 'DID');
|
|
82
|
+
const firstRow = rows[0] ?? [];
|
|
83
|
+
const tid = tidColIndex >= 0 && firstRow.length > 0 ? Number(firstRow[tidColIndex]) : searchResult?.fromTID;
|
|
84
|
+
const firstDid = didColIndex >= 0 && firstRow.length > 0 ? Number(firstRow[didColIndex]) : undefined;
|
|
85
|
+
const dtdWithMetadata = await DcmtTypeListCacheService.GetWithNotGrantedAsync(tid, firstDid, searchResult);
|
|
86
|
+
const mdList = dtdWithMetadata?.metadata ?? [];
|
|
87
|
+
// Posizione di ogni MID nelle colonne del risultato: identica per tutte le righe,
|
|
88
|
+
// quindi calcolata una volta sola invece di una find() per metadato per riga.
|
|
89
|
+
const mids = columns.map(col => Number(col.extendedProperties?.["MID"] ?? "0"));
|
|
90
|
+
const columnByMid = new Map();
|
|
91
|
+
columns.forEach((col, i) => { if (!columnByMid.has(mids[i]))
|
|
92
|
+
columnByMid.set(mids[i], col); });
|
|
93
|
+
const dtdResult = searchResult?.dtdResult;
|
|
80
94
|
for (let index = 0; index < rows.length; index++) {
|
|
81
95
|
// Interruzione richiesta dall'utente: restituisce i documenti già elaborati
|
|
82
96
|
if (signal?.aborted)
|
|
83
97
|
break;
|
|
84
98
|
const row = rows[index];
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const did = didColIndex >= 0 ? Number(row[didColIndex]) : undefined;
|
|
88
|
-
// Fetch complete metadata for this specific document (like getFilteredMetadata does)
|
|
89
|
-
const metadata = await SDK_Globals.tmSession?.NewSearchEngine().GetMetadataAsync(tid, did, true);
|
|
90
|
-
if (metadata) {
|
|
91
|
-
// Get full DTD with metadata for this document
|
|
92
|
-
const dtdResult = metadata.dtdResult;
|
|
93
|
-
const metadataRows = dtdResult?.rows?.[0] ?? [];
|
|
94
|
-
const mids = metadata.selectMIDs;
|
|
95
|
-
const dtdWithMetadata = await DcmtTypeListCacheService.GetWithNotGrantedAsync(tid, did, metadata);
|
|
96
|
-
const mdList = dtdWithMetadata?.metadata ?? [];
|
|
99
|
+
const item = { rowIndex: index };
|
|
100
|
+
if (mdList.length > 0) {
|
|
97
101
|
// Convert to MetadataValueDescriptorEx array
|
|
98
|
-
const metadataList = searchResultToMetadataValues(tid, dtdResult,
|
|
102
|
+
const metadataList = searchResultToMetadataValues(tid, dtdResult, row, mids, mdList, LayoutModes.Update);
|
|
99
103
|
// Convert to DcmtMetadataMap format (like getFilteredMetadata does)
|
|
100
|
-
const item = { rowIndex: index };
|
|
101
104
|
for (const mvd of metadataList) {
|
|
102
105
|
if (hideSysMetadata && mvd.mid !== undefined && mvd.mid < 100)
|
|
103
106
|
continue;
|
|
@@ -106,23 +109,18 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata, si
|
|
|
106
109
|
: (mvd.md?.name ?? '');
|
|
107
110
|
if (key) {
|
|
108
111
|
// Find the corresponding column by MID to format the value
|
|
109
|
-
const column = dtdResult?.columns?.find(c => Number(c.extendedProperties?.["MID"] ?? "0") === mvd.mid);
|
|
110
112
|
item[key] = {
|
|
111
113
|
md: mvd.md,
|
|
112
|
-
value: getDisplayValueByColumn(
|
|
114
|
+
value: getDisplayValueByColumn(columnByMid.get(mvd.mid ?? 0), mvd.value)
|
|
113
115
|
};
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
|
-
output.push(item);
|
|
117
118
|
}
|
|
118
119
|
else {
|
|
119
|
-
// Fallback:
|
|
120
|
-
const item = { rowIndex: index };
|
|
121
|
-
const fallbackTid = searchResult?.fromTID;
|
|
122
|
-
const dtd = await DcmtTypeListCacheService.GetWithNotGrantedAsync(fallbackTid, undefined, searchResult);
|
|
120
|
+
// Fallback: il DTD non è risolvibile, usa le colonne grezze del risultato
|
|
123
121
|
for (let i = 0; i < row.length; i++) {
|
|
124
|
-
const column =
|
|
125
|
-
const mid =
|
|
122
|
+
const column = columns[i];
|
|
123
|
+
const mid = mids[i];
|
|
126
124
|
if (hideSysMetadata && mid < 100)
|
|
127
125
|
continue;
|
|
128
126
|
let key = column?.caption ?? '';
|
|
@@ -134,20 +132,18 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata, si
|
|
|
134
132
|
key = `${key}_${mid}`;
|
|
135
133
|
}
|
|
136
134
|
}
|
|
137
|
-
const value = row[i];
|
|
138
|
-
const md = dtd?.metadata?.find(o => o.id == mid);
|
|
139
135
|
item[key] = {
|
|
140
|
-
md:
|
|
141
|
-
value: getDisplayValueByColumn(column,
|
|
136
|
+
md: undefined,
|
|
137
|
+
value: getDisplayValueByColumn(column, row[i])
|
|
142
138
|
};
|
|
143
139
|
}
|
|
144
|
-
output.push(item);
|
|
145
140
|
}
|
|
141
|
+
output.push(item);
|
|
146
142
|
}
|
|
147
143
|
return output;
|
|
148
144
|
};
|
|
149
145
|
export const DEFAULT_RELATION_EXPAND_LEVEL = 4; // Default maximum depth level for expansion (can be adjusted)
|
|
150
|
-
const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndicator = true, allowShowZeroDcmts = true, initialShowZeroDcmts = false, allowedTIDs, allowMultipleSelection = false, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onAllItemsChanged, onDocumentDoubleClick, customItemRender, customDocumentStyle, customMainContainerContent, customDocumentContent, showMetadataNames = false, maxDepthLevel = 2, invertMasterNavigation = true, additionalStaticItems, showMainDocument = true, labelMainContainer, onNoRelationsFound, onItemContextMenu, focusedItemFormData = [], showExpandAllButton = false, defaultExpandAll = false, onLoadingStateChanged, onStopCalculationReady, onCalculationStopped }) => {
|
|
146
|
+
const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndicator = true, allowShowZeroDcmts = true, initialShowZeroDcmts = false, allowedTIDs, allowMultipleSelection = false, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onAllItemsChanged, onDocumentDoubleClick, customItemRender, customDocumentStyle, customMainContainerContent, customDocumentContent, showMetadataNames = false, maxDepthLevel = 2, invertMasterNavigation = true, additionalStaticItems, showMainDocument = true, labelMainContainer, onNoRelationsFound, onItemContextMenu, focusedItemFormData = [], showExpandAllButton = false, defaultExpandAll = false, onLoadingStateChanged, onLoadingProgress, onStopCalculationReady, onCalculationStopped }) => {
|
|
151
147
|
// State
|
|
152
148
|
const [dcmtTypes, setDcmtTypes] = useState([]);
|
|
153
149
|
const [treeData, setTreeData] = useState([]);
|
|
@@ -196,6 +192,11 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
196
192
|
const isLoading = showWaitPanel || showExpansionWaitPanel;
|
|
197
193
|
onLoadingStateChanged?.(isLoading);
|
|
198
194
|
}, [showWaitPanel, showExpansionWaitPanel, onLoadingStateChanged]);
|
|
195
|
+
// Notifica al padre l'avanzamento del caricamento iniziale (documenti processati
|
|
196
|
+
// sul totale), così può mostrarlo nel proprio overlay che copre il wait panel interno
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
onLoadingProgress?.(waitPanelValuePrimary, waitPanelMaxValuePrimary);
|
|
199
|
+
}, [waitPanelValuePrimary, waitPanelMaxValuePrimary, onLoadingProgress]);
|
|
199
200
|
// Mantiene l'AbortController dell'espansione in corso accessibile da callback stabili
|
|
200
201
|
const expansionAbortControllerRef = React.useRef(undefined);
|
|
201
202
|
useEffect(() => {
|
|
@@ -638,6 +639,11 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
638
639
|
}
|
|
639
640
|
}
|
|
640
641
|
}
|
|
642
|
+
// Interruzione richiesta dall'utente: il documento corrente non è stato
|
|
643
|
+
// caricato per intero, quindi non viene aggiunto all'albero. Il parziale
|
|
644
|
+
// resta così a granularità di documento (es. 3 completi su 10).
|
|
645
|
+
if (abortController.signal.aborted)
|
|
646
|
+
break;
|
|
641
647
|
// Aggiungi i master come root, raggruppando per TID e relationId
|
|
642
648
|
for (const masterContainer of masterDocs) {
|
|
643
649
|
const existingContainer = tree.find(c => c.tid === masterContainer.tid && c.relationId === masterContainer.relationId && c.isContainer);
|
|
@@ -666,6 +672,9 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
666
672
|
const relatedDocs = isForMaster
|
|
667
673
|
? await getMasterDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel, abortController.signal)
|
|
668
674
|
: await getDetailDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel, abortController.signal);
|
|
675
|
+
// Interruzione richiesta dall'utente
|
|
676
|
+
if (abortController.signal.aborted)
|
|
677
|
+
break;
|
|
669
678
|
// Se showMainDocument è false, mostra i container dei dettagli direttamente sotto il container principale
|
|
670
679
|
if (!showMainDocument) {
|
|
671
680
|
// Check if a container for this TID already exists in the tree
|
|
@@ -817,7 +826,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
817
826
|
const wasStopped = abortController.signal.aborted;
|
|
818
827
|
if (wasStopped) {
|
|
819
828
|
setLoadStoppedByUser(true);
|
|
820
|
-
onCalculationStopped?.();
|
|
829
|
+
onCalculationStopped?.(processedCount, inputDcmts.length);
|
|
821
830
|
}
|
|
822
831
|
// If no relations found, notify parent
|
|
823
832
|
if (!wasStopped && hasNoRelations && onNoRelationsFound) {
|