@topconsultnpm/sdkui-react 6.22.0-t1 → 6.22.0-t2
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/NewComponents/ContextMenu/TMContextMenu.js +1 -1
- package/lib/components/NewComponents/ContextMenu/styles.d.ts +45 -43
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +1 -1
- package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +67 -60
- package/lib/components/base/Styled.d.ts +92 -76
- package/lib/components/base/TMButton.d.ts +13 -0
- package/lib/components/base/TMButton.js +137 -5
- package/lib/components/base/TMDataGrid.d.ts +2 -0
- package/lib/components/base/TMDataGrid.js +260 -8
- package/lib/components/base/TMDataGridExportForm.js +39 -30
- package/lib/components/base/TMEditorBase.d.ts +2 -0
- package/lib/components/base/TMFileManager.js +5 -3
- package/lib/components/base/TMFileManagerDataGridView.js +11 -2
- package/lib/components/base/TMFileManagerThumbnailItems.js +19 -9
- package/lib/components/base/TMFileManagerUtils.d.ts +6 -6
- package/lib/components/base/TMFileManagerUtils.js +37 -1
- package/lib/components/base/TMModal.d.ts +11 -0
- package/lib/components/base/TMModal.js +47 -13
- package/lib/components/base/TMPanel.d.ts +6 -0
- package/lib/components/base/TMPanel.js +138 -25
- package/lib/components/base/TMPopUp.js +3 -0
- package/lib/components/base/TMTooltip.d.ts +2 -1
- package/lib/components/base/TMTooltip.js +24 -8
- package/lib/components/base/TMTreeView.d.ts +13 -7
- package/lib/components/base/TMTreeView.js +108 -67
- package/lib/components/choosers/TMDcmtTypeChooser.js +4 -3
- package/lib/components/choosers/TMDistinctValues.d.ts +9 -7
- package/lib/components/choosers/TMDistinctValues.js +149 -142
- package/lib/components/choosers/TMMetadataChooser.js +1 -1
- package/lib/components/choosers/TMQuickSearchInfo.d.ts +13 -0
- package/lib/components/choosers/TMQuickSearchInfo.js +279 -0
- package/lib/components/choosers/TMQuickSearchSettingsForm.d.ts +16 -0
- package/lib/components/choosers/TMQuickSearchSettingsForm.js +94 -0
- package/lib/components/choosers/TMSelectedValuesSummary.d.ts +13 -0
- package/lib/components/choosers/TMSelectedValuesSummary.js +91 -0
- package/lib/components/editors/TMDateBox.d.ts +16 -1
- package/lib/components/editors/TMDateBox.js +90 -22
- package/lib/components/editors/TMDropDown.d.ts +3 -0
- package/lib/components/editors/TMDropDown.js +197 -5
- package/lib/components/editors/TMEditorStyled.d.ts +20 -42
- package/lib/components/editors/TMMetadataEditor.d.ts +5 -1
- package/lib/components/editors/TMMetadataEditor.js +27 -23
- package/lib/components/editors/TMTextArea.d.ts +1 -0
- package/lib/components/editors/TMTextArea.js +23 -15
- package/lib/components/editors/TMTextBox.d.ts +2 -0
- package/lib/components/editors/TMTextBox.js +30 -19
- package/lib/components/features/archive/TMArchive.js +17 -3
- package/lib/components/features/documents/TMBatchUpdateForm.js +19 -5
- package/lib/components/features/documents/TMDcmtBlog.d.ts +3 -0
- package/lib/components/features/documents/TMDcmtBlog.js +4 -4
- package/lib/components/features/documents/TMDcmtForm.d.ts +7 -0
- package/lib/components/features/documents/TMDcmtForm.js +232 -53
- package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +11 -0
- package/lib/components/features/documents/TMDcmtFormActionButtons.js +77 -7
- package/lib/components/features/documents/TMDcmtIcon.js +5 -3
- package/lib/components/features/documents/TMDcmtPreview.d.ts +7 -5
- package/lib/components/features/documents/TMDcmtPreview.js +10 -6
- package/lib/components/features/documents/TMMasterDetailDcmts.js +95 -33
- package/lib/components/features/documents/TMMasterInfoFields.d.ts +20 -0
- package/lib/components/features/documents/TMMasterInfoFields.js +186 -0
- package/lib/components/features/documents/TMMergeToPdfForm.d.ts +1 -2
- package/lib/components/features/documents/TMMergeToPdfForm.js +30 -5
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.d.ts +46 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +323 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +370 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +283 -0
- package/lib/components/features/documents/TMRelationViewer.d.ts +14 -1
- package/lib/components/features/documents/TMRelationViewer.js +82 -52
- package/lib/components/features/search/TMSearch.js +103 -24
- package/lib/components/features/search/TMSearchQueryEditor.js +5 -3
- package/lib/components/features/search/TMSearchQueryPanel.d.ts +14 -4
- package/lib/components/features/search/TMSearchQueryPanel.js +152 -57
- package/lib/components/features/search/TMSearchResult.d.ts +16 -0
- package/lib/components/features/search/TMSearchResult.js +438 -145
- package/lib/components/features/search/TMTreeSelector.js +109 -64
- package/lib/components/features/workflow/TMWorkflowPopup.d.ts +10 -0
- package/lib/components/features/workflow/TMWorkflowPopup.js +8 -4
- package/lib/components/features/workflow/diagram/WorkitemRecipientsEditor.d.ts +3 -1
- package/lib/components/forms/Login/ChangePasswordInputs.d.ts +3 -1
- package/lib/components/grids/TMBlogAttachments.js +13 -2
- package/lib/components/grids/TMBlogHeader.js +5 -1
- package/lib/components/grids/TMBlogsPost.d.ts +2 -0
- package/lib/components/grids/TMBlogsPost.js +31 -4
- package/lib/components/grids/TMBlogsPostUtils.d.ts +1 -0
- package/lib/components/grids/TMBlogsPostUtils.js +14 -3
- package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +1 -0
- package/lib/components/layout/panelManager/TMPanelManagerContainer.js +24 -14
- package/lib/components/layout/panelManager/TMPanelManagerContext.js +68 -93
- package/lib/components/layout/panelManager/TMPanelManagerToolbar.d.ts +4 -5
- package/lib/components/layout/panelManager/TMPanelWrapper.js +2 -2
- package/lib/components/layout/panelManager/types.d.ts +3 -0
- package/lib/components/layout/panelManager/utils.js +13 -11
- package/lib/components/query/TMQueryEditor.d.ts +14 -10
- package/lib/components/sidebar/TMCommandsPanel.d.ts +4 -4
- package/lib/components/sidebar/TMHeader.js +30 -20
- package/lib/components/viewers/TMMidViewer.js +5 -2
- package/lib/components/viewers/TMTidViewer.js +86 -25
- package/lib/css/tm-sdkui.css +1 -1
- package/lib/devextreme-license.d.ts +1 -0
- package/lib/devextreme-license.js +3 -0
- package/lib/helper/Globalization.d.ts +1 -1
- package/lib/helper/SDKUI_Globals.d.ts +110 -0
- package/lib/helper/SDKUI_Globals.js +151 -0
- package/lib/helper/SDKUI_Localizator.d.ts +55 -0
- package/lib/helper/SDKUI_Localizator.js +550 -0
- package/lib/helper/TMAppUpdatedModal.d.ts +2 -0
- package/lib/helper/TMAppUpdatedModal.js +134 -0
- package/lib/helper/TMIcons.d.ts +1 -0
- package/lib/helper/TMIcons.js +3 -0
- package/lib/helper/TMUtils.d.ts +51 -4
- package/lib/helper/TMUtils.js +272 -11
- package/lib/helper/dataGridSearchHelper.d.ts +28 -0
- package/lib/helper/dataGridSearchHelper.js +51 -0
- package/lib/helper/dcmtsHelper.d.ts +20 -0
- package/lib/helper/dcmtsHelper.js +58 -1
- package/lib/helper/helpers.d.ts +23 -1
- package/lib/helper/helpers.js +57 -1
- package/lib/helper/index.d.ts +2 -0
- package/lib/helper/index.js +2 -0
- package/lib/helper/queryHelper.d.ts +6 -1
- package/lib/helper/queryHelper.js +8 -3
- package/lib/hooks/tmDistinctValuesGridHelper.d.ts +16 -0
- package/lib/hooks/tmDistinctValuesGridHelper.js +31 -0
- package/lib/hooks/useArchiveListForm.d.ts +39 -0
- package/lib/hooks/useArchiveListForm.js +46 -0
- package/lib/hooks/useCaseFlowApprove.d.ts +56 -0
- package/lib/hooks/useCaseFlowApprove.js +157 -0
- package/lib/hooks/useDataUserIdItem.d.ts +1 -0
- package/lib/hooks/useDataUserIdItem.js +1 -0
- package/lib/hooks/useDocumentOperations.d.ts +4 -0
- package/lib/hooks/useDocumentOperations.js +52 -10
- package/lib/hooks/useMultiMasterDetailDcmts.d.ts +113 -0
- package/lib/hooks/useMultiMasterDetailDcmts.js +760 -0
- package/lib/hooks/useRelatedDocuments.d.ts +1 -0
- package/lib/hooks/useRelatedDocuments.js +22 -27
- package/lib/hooks/useShowDossiersV5.d.ts +12 -0
- package/lib/hooks/useShowDossiersV5.js +37 -0
- package/lib/hooks/useTMDistinctValuesMetadataDisplay.d.ts +18 -0
- package/lib/hooks/useTMDistinctValuesMetadataDisplay.js +103 -0
- package/lib/hooks/useTMDistinctValuesQuickSearch.d.ts +49 -0
- package/lib/hooks/useTMDistinctValuesQuickSearch.js +307 -0
- package/lib/hooks/useTMDistinctValuesSelection.d.ts +42 -0
- package/lib/hooks/useTMDistinctValuesSelection.js +103 -0
- package/lib/hooks/useTMDistinctValuesSource.d.ts +29 -0
- package/lib/hooks/useTMDistinctValuesSource.js +105 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +5 -2
- package/lib/services/caseflow/CaseFlowService.d.ts +236 -0
- package/lib/services/caseflow/CaseFlowService.js +693 -0
- package/lib/services/caseflow/CaseFlowTemplateCacheService.d.ts +28 -0
- package/lib/services/caseflow/CaseFlowTemplateCacheService.js +121 -0
- package/lib/services/caseflow/caseFlowNameCache.d.ts +32 -0
- package/lib/services/caseflow/caseFlowNameCache.js +116 -0
- package/lib/services/caseflow/caseFlowWorkItemUtils.d.ts +61 -0
- package/lib/services/caseflow/caseFlowWorkItemUtils.js +113 -0
- package/lib/services/index.d.ts +4 -0
- package/lib/services/index.js +4 -0
- package/lib/services/platform_services.d.ts +1 -1
- package/package.json +9 -5
|
@@ -132,6 +132,19 @@ 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 on mount to hand over a function that stops the ongoing correlations
|
|
137
|
+
* calculation: no further GetMetadata calls are performed and only the
|
|
138
|
+
* correlations already calculated are kept.
|
|
139
|
+
* The function is synchronous, so it can be safely called right before
|
|
140
|
+
* unmounting the viewer (e.g. when navigating back).
|
|
141
|
+
*/
|
|
142
|
+
onStopCalculationReady?: (stopCalculation: () => void) => void;
|
|
143
|
+
/**
|
|
144
|
+
* Callback invoked when the calculation has actually been stopped
|
|
145
|
+
* (loadData terminated after an abort request).
|
|
146
|
+
*/
|
|
147
|
+
onCalculationStopped?: () => void;
|
|
135
148
|
}
|
|
136
149
|
/**
|
|
137
150
|
* Check if document type has detail relations
|
|
@@ -150,7 +163,7 @@ export declare const getDisplayValueByColumn: (col: DataColumnDescriptor | undef
|
|
|
150
163
|
* For each document, fetches complete metadata using GetMetadataAsync to ensure
|
|
151
164
|
* all metadata properties (isSpecialSearchOutput, permissions, etc.) are available
|
|
152
165
|
*/
|
|
153
|
-
export declare const searchResultToDataSource: (searchResult: SearchResultDescriptor | undefined, hideSysMetadata?: boolean) => Promise<any[]>;
|
|
166
|
+
export declare const searchResultToDataSource: (searchResult: SearchResultDescriptor | undefined, hideSysMetadata?: boolean, signal?: AbortSignal) => Promise<any[]>;
|
|
154
167
|
export declare const DEFAULT_RELATION_EXPAND_LEVEL = 4;
|
|
155
168
|
declare const TMRelationViewer: React.FC<TMRelationViewerProps>;
|
|
156
169
|
export default TMRelationViewer;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
|
-
import { DcmtTypeListCacheService, SDK_Globals, DataColumnTypes,
|
|
4
|
-
import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus, IconChevronDown, IconChevronRight, SDKUI_Localizator, buildDcmtDisplayName, SDKUI_Globals, searchResultToMetadataValues } from '../../../helper';
|
|
3
|
+
import { DcmtTypeListCacheService, SDK_Globals, DataColumnTypes, MetadataDataDomains, RelationCacheService, RelationTypes, UserListCacheService, LayoutModes } from "@topconsultnpm/sdk-ts";
|
|
4
|
+
import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus, IconChevronDown, IconChevronRight, SDKUI_Localizator, buildDcmtDisplayName, SDKUI_Globals, searchResultToMetadataValues, getColumnFormatInfo, formatDateTimeByMetadataFormat, formatNumberByMetadataFormat } from '../../../helper';
|
|
5
5
|
import ShowAlert from '../../base/TMAlert';
|
|
6
6
|
import TMToppyMessage from '../../../helper/TMToppyMessage';
|
|
7
7
|
import { TMColors } from '../../../utils/theme';
|
|
@@ -55,35 +55,14 @@ export const getDisplayValueByColumn = (col, value) => {
|
|
|
55
55
|
return value;
|
|
56
56
|
if (col.dataType === DataColumnTypes.Text)
|
|
57
57
|
return value;
|
|
58
|
-
|
|
59
|
-
const formatCulture = col
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
case MetadataFormats.ShortDateShortTime: return date.toLocaleString(formatCulture, formatCulture == "it-IT" ? { year: "numeric", month: "2-digit", day: "2-digit", hour: '2-digit', minute: '2-digit' } : { dateStyle: 'short', timeStyle: 'short' }).replace(',', '');
|
|
67
|
-
case MetadataFormats.LongDate: return date.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
|
|
68
|
-
case MetadataFormats.LongTime: return date.toLocaleString(formatCulture, { timeStyle: 'medium' });
|
|
69
|
-
case MetadataFormats.LongDateLongTime: return date.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
70
|
-
case MetadataFormats.LongDateShortTime: return date.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: '2-digit', minute: '2-digit' });
|
|
71
|
-
default: return date.toLocaleString(formatCulture, { dateStyle: 'short' });
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (col.dataType === DataColumnTypes.Number) {
|
|
75
|
-
return value.toLocaleString(formatCulture, { useGrouping: format == MetadataFormats.NumberWithThousandsSeparator });
|
|
76
|
-
}
|
|
77
|
-
if (format == MetadataFormats.None)
|
|
78
|
-
return value;
|
|
79
|
-
if (format == MetadataFormats.CurrencyEuro)
|
|
80
|
-
return value.toLocaleString(formatCulture, { style: 'currency', currency: "EUR" });
|
|
81
|
-
if (format == MetadataFormats.CurrencyDollar)
|
|
82
|
-
return value.toLocaleString(formatCulture, { style: 'currency', currency: "USD" });
|
|
83
|
-
if (format == MetadataFormats.CurrencyPound)
|
|
84
|
-
return value.toLocaleString(formatCulture, { style: 'currency', currency: "GBP" });
|
|
85
|
-
if (format == MetadataFormats.CurrencyYen)
|
|
86
|
-
return value.toLocaleString(formatCulture, { style: 'currency', currency: "JPY" });
|
|
58
|
+
// Formato e cultura di visualizzazione definiti sulle proprietà estese della colonna
|
|
59
|
+
const { format, formatCulture } = getColumnFormatInfo(col);
|
|
60
|
+
// Date: il valore arriva come stringa e va prima convertito in Date
|
|
61
|
+
if (col.dataType === DataColumnTypes.DateTime)
|
|
62
|
+
return formatDateTimeByMetadataFormat(new Date(value), format, formatCulture);
|
|
63
|
+
// Numeri (incluse valute): stessa formattazione usata da TMSearchResult
|
|
64
|
+
if (col.dataType === DataColumnTypes.Number)
|
|
65
|
+
return formatNumberByMetadataFormat(value, format, formatCulture);
|
|
87
66
|
return value;
|
|
88
67
|
};
|
|
89
68
|
/**
|
|
@@ -91,7 +70,7 @@ export const getDisplayValueByColumn = (col, value) => {
|
|
|
91
70
|
* For each document, fetches complete metadata using GetMetadataAsync to ensure
|
|
92
71
|
* all metadata properties (isSpecialSearchOutput, permissions, etc.) are available
|
|
93
72
|
*/
|
|
94
|
-
export const searchResultToDataSource = async (searchResult, hideSysMetadata) => {
|
|
73
|
+
export const searchResultToDataSource = async (searchResult, hideSysMetadata, signal) => {
|
|
95
74
|
const rows = searchResult?.dtdResult?.rows ?? [];
|
|
96
75
|
const output = [];
|
|
97
76
|
// Find TID and DID column indices
|
|
@@ -99,6 +78,9 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata) =>
|
|
|
99
78
|
const tidColIndex = columns.findIndex(col => col.caption?.toUpperCase() === 'TID');
|
|
100
79
|
const didColIndex = columns.findIndex(col => col.caption?.toUpperCase() === 'DID');
|
|
101
80
|
for (let index = 0; index < rows.length; index++) {
|
|
81
|
+
// Interruzione richiesta dall'utente: restituisce i documenti già elaborati
|
|
82
|
+
if (signal?.aborted)
|
|
83
|
+
break;
|
|
102
84
|
const row = rows[index];
|
|
103
85
|
// Extract TID and DID from row
|
|
104
86
|
const tid = tidColIndex >= 0 ? Number(row[tidColIndex]) : searchResult?.fromTID;
|
|
@@ -123,9 +105,11 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata) =>
|
|
|
123
105
|
? (mvd.md?.name ?? '').toUpperCase()
|
|
124
106
|
: (mvd.md?.name ?? '');
|
|
125
107
|
if (key) {
|
|
108
|
+
// Find the corresponding column by MID to format the value
|
|
109
|
+
const column = dtdResult?.columns?.find(c => Number(c.extendedProperties?.["MID"] ?? "0") === mvd.mid);
|
|
126
110
|
item[key] = {
|
|
127
111
|
md: mvd.md,
|
|
128
|
-
value: mvd.value
|
|
112
|
+
value: getDisplayValueByColumn(column, mvd.value)
|
|
129
113
|
};
|
|
130
114
|
}
|
|
131
115
|
}
|
|
@@ -163,7 +147,7 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata) =>
|
|
|
163
147
|
return output;
|
|
164
148
|
};
|
|
165
149
|
export const DEFAULT_RELATION_EXPAND_LEVEL = 4; // Default maximum depth level for expansion (can be adjusted)
|
|
166
|
-
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 }) => {
|
|
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 }) => {
|
|
167
151
|
// State
|
|
168
152
|
const [dcmtTypes, setDcmtTypes] = useState([]);
|
|
169
153
|
const [treeData, setTreeData] = useState([]);
|
|
@@ -178,6 +162,8 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
178
162
|
const [waitPanelValuePrimary, setWaitPanelValuePrimary] = useState(0);
|
|
179
163
|
const [waitPanelMaxValuePrimary, setWaitPanelMaxValuePrimary] = useState(0);
|
|
180
164
|
const [abortController] = useState(new AbortController());
|
|
165
|
+
// True quando l'utente ha interrotto il calcolo delle correlazioni (pulsante "Interrompi")
|
|
166
|
+
const [loadStoppedByUser, setLoadStoppedByUser] = useState(false);
|
|
181
167
|
const [showExpansionWaitPanel, setShowExpansionWaitPanel] = useState(false);
|
|
182
168
|
const [expansionWaitPanelText, setExpansionWaitPanelText] = useState('');
|
|
183
169
|
const [expansionWaitPanelValue, setExpansionWaitPanelValue] = useState(0);
|
|
@@ -210,6 +196,27 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
210
196
|
const isLoading = showWaitPanel || showExpansionWaitPanel;
|
|
211
197
|
onLoadingStateChanged?.(isLoading);
|
|
212
198
|
}, [showWaitPanel, showExpansionWaitPanel, onLoadingStateChanged]);
|
|
199
|
+
// Mantiene l'AbortController dell'espansione in corso accessibile da callback stabili
|
|
200
|
+
const expansionAbortControllerRef = React.useRef(undefined);
|
|
201
|
+
useEffect(() => {
|
|
202
|
+
expansionAbortControllerRef.current = expansionAbortController;
|
|
203
|
+
}, [expansionAbortController]);
|
|
204
|
+
/**
|
|
205
|
+
* Interrompe il calcolo delle correlazioni (iniziale e/o espansione in corso):
|
|
206
|
+
* non vengono eseguite ulteriori chiamate GetMetadata e vengono mantenute
|
|
207
|
+
* solo le correlazioni già calcolate.
|
|
208
|
+
* È sincrona: può essere invocata immediatamente prima di smontare il viewer
|
|
209
|
+
* (es. pulsante "Indietro"), quando un effect non farebbe in tempo.
|
|
210
|
+
*/
|
|
211
|
+
const stopCalculation = useCallback(() => {
|
|
212
|
+
if (!abortController.signal.aborted)
|
|
213
|
+
abortController.abort();
|
|
214
|
+
expansionAbortControllerRef.current?.abort();
|
|
215
|
+
}, [abortController]);
|
|
216
|
+
// Espone la funzione di interruzione al componente padre
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
onStopCalculationReady?.(stopCalculation);
|
|
219
|
+
}, [onStopCalculationReady, stopCalculation]);
|
|
213
220
|
// Sincronizza expandLevel quando userSettings.searchSettings.relationExpandLevel cambia
|
|
214
221
|
useEffect(() => {
|
|
215
222
|
const globalExpandLevel = SDKUI_Globals.userSettings?.searchSettings?.relationExpandLevel;
|
|
@@ -239,7 +246,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
239
246
|
/**
|
|
240
247
|
* Recursively retrieve detail documents (adapted from TMMasterDetailDcmts.tsx)
|
|
241
248
|
*/
|
|
242
|
-
const getDetailDcmtsAsync = useCallback(async (mTID, mDID, maxLevel) => {
|
|
249
|
+
const getDetailDcmtsAsync = useCallback(async (mTID, mDID, maxLevel, signal) => {
|
|
243
250
|
const items = [];
|
|
244
251
|
if (!mTID)
|
|
245
252
|
return [];
|
|
@@ -259,6 +266,9 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
259
266
|
return items;
|
|
260
267
|
const results = await searchEngine.GetAllDetailDcmtsAsync(mTID, mDID) ?? [];
|
|
261
268
|
for (const searchResult of results) {
|
|
269
|
+
// Interruzione richiesta dall'utente: restituisce le correlazioni già calcolate
|
|
270
|
+
if (signal?.aborted)
|
|
271
|
+
break;
|
|
262
272
|
// Skip if allowedTIDs is set and this TID is not allowed
|
|
263
273
|
if (allowedTIDs && searchResult.fromTID && !allowedTIDs.includes(searchResult.fromTID)) {
|
|
264
274
|
continue;
|
|
@@ -280,7 +290,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
280
290
|
expanded: false,
|
|
281
291
|
hidden: false
|
|
282
292
|
};
|
|
283
|
-
const source = await searchResultToDataSource(searchResult);
|
|
293
|
+
const source = await searchResultToDataSource(searchResult, undefined, signal);
|
|
284
294
|
if (source && source.length > 0) {
|
|
285
295
|
const dcmtDetails = [];
|
|
286
296
|
// Check once if this document type can have detail relations
|
|
@@ -326,7 +336,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
326
336
|
/**
|
|
327
337
|
* Recursively retrieve master documents
|
|
328
338
|
*/
|
|
329
|
-
const getMasterDcmtsAsync = useCallback(async (dTID, dDID, maxLevel) => {
|
|
339
|
+
const getMasterDcmtsAsync = useCallback(async (dTID, dDID, maxLevel, signal) => {
|
|
330
340
|
const items = [];
|
|
331
341
|
if (!dTID)
|
|
332
342
|
return [];
|
|
@@ -346,6 +356,9 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
346
356
|
return items;
|
|
347
357
|
const results = await searchEngine.GetAllMasterDcmtsAsync(dTID, dDID) ?? [];
|
|
348
358
|
for (const searchResult of results) {
|
|
359
|
+
// Interruzione richiesta dall'utente: restituisce le correlazioni già calcolate
|
|
360
|
+
if (signal?.aborted)
|
|
361
|
+
break;
|
|
349
362
|
// Skip if allowedTIDs is set and this TID is not allowed
|
|
350
363
|
if (allowedTIDs && searchResult.fromTID && !allowedTIDs.includes(searchResult.fromTID)) {
|
|
351
364
|
continue;
|
|
@@ -367,7 +380,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
367
380
|
expanded: false,
|
|
368
381
|
hidden: false
|
|
369
382
|
};
|
|
370
|
-
const source = await searchResultToDataSource(searchResult);
|
|
383
|
+
const source = await searchResultToDataSource(searchResult, undefined, signal);
|
|
371
384
|
if (source && source.length > 0) {
|
|
372
385
|
const dcmtMasters = [];
|
|
373
386
|
// Check once if this document type can have master relations (for inverted mode)
|
|
@@ -595,7 +608,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
595
608
|
}
|
|
596
609
|
const dtd = await DcmtTypeListCacheService.GetAsync(dcmt.TID);
|
|
597
610
|
// Parse document values
|
|
598
|
-
const docValues = await searchResultToDataSource(result);
|
|
611
|
+
const docValues = await searchResultToDataSource(result, undefined, abortController.signal);
|
|
599
612
|
const docRow = docValues.length > 0 ? docValues[0] : undefined;
|
|
600
613
|
// Generate unique GUID for this container
|
|
601
614
|
const containerGUID = genUniqueId();
|
|
@@ -604,16 +617,21 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
604
617
|
// ========================================================================
|
|
605
618
|
if (isForMaster && !invertMasterNavigation) {
|
|
606
619
|
// Carica i master documents
|
|
607
|
-
const masterDocs = await getMasterDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel);
|
|
620
|
+
const masterDocs = await getMasterDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel, abortController.signal);
|
|
608
621
|
// Per ogni master, carica i suoi detail (incluso il documento corrente)
|
|
609
622
|
for (const masterContainer of masterDocs) {
|
|
623
|
+
if (abortController.signal.aborted)
|
|
624
|
+
break;
|
|
610
625
|
if (!masterContainer.items)
|
|
611
626
|
continue;
|
|
612
627
|
// Per ogni master document nel container, carica i detail
|
|
613
628
|
for (const masterDoc of masterContainer.items) {
|
|
629
|
+
// Interruzione richiesta dall'utente: mantiene i dati già calcolati
|
|
630
|
+
if (abortController.signal.aborted)
|
|
631
|
+
break;
|
|
614
632
|
if (masterDoc.tid && masterDoc.did) {
|
|
615
633
|
// Carica i detail del master (incluso il documento di partenza)
|
|
616
|
-
const detailDocs = await getDetailDcmtsAsync(masterDoc.tid, masterDoc.did, 1);
|
|
634
|
+
const detailDocs = await getDetailDcmtsAsync(masterDoc.tid, masterDoc.did, 1, abortController.signal);
|
|
617
635
|
masterDoc.items = detailDocs;
|
|
618
636
|
masterDoc.itemsCount = detailDocs.length;
|
|
619
637
|
masterDoc.isLoaded = true;
|
|
@@ -646,8 +664,8 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
646
664
|
else {
|
|
647
665
|
// Load related documents (detail or master based on isForMaster flag)
|
|
648
666
|
const relatedDocs = isForMaster
|
|
649
|
-
? await getMasterDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel)
|
|
650
|
-
: await getDetailDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel);
|
|
667
|
+
? await getMasterDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel, abortController.signal)
|
|
668
|
+
: await getDetailDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel, abortController.signal);
|
|
651
669
|
// Se showMainDocument è false, mostra i container dei dettagli direttamente sotto il container principale
|
|
652
670
|
if (!showMainDocument) {
|
|
653
671
|
// Check if a container for this TID already exists in the tree
|
|
@@ -794,8 +812,15 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
794
812
|
// Check recursively if there are any actual documents
|
|
795
813
|
return hasNoActualDocuments(container.items);
|
|
796
814
|
});
|
|
815
|
+
// Calcolo interrotto dall'utente: mostra solo ciò che è stato calcolato,
|
|
816
|
+
// senza notificare l'assenza di correlazioni (il risultato è parziale, non definitivo)
|
|
817
|
+
const wasStopped = abortController.signal.aborted;
|
|
818
|
+
if (wasStopped) {
|
|
819
|
+
setLoadStoppedByUser(true);
|
|
820
|
+
onCalculationStopped?.();
|
|
821
|
+
}
|
|
797
822
|
// If no relations found, notify parent
|
|
798
|
-
if (hasNoRelations && onNoRelationsFound) {
|
|
823
|
+
if (!wasStopped && hasNoRelations && onNoRelationsFound) {
|
|
799
824
|
onNoRelationsFound();
|
|
800
825
|
}
|
|
801
826
|
// Update metadata error count state
|
|
@@ -823,7 +848,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
823
848
|
// Now it will correctly detect expanded nodes and add infoMessage if all children are hidden
|
|
824
849
|
const processedTree = updateHiddenProperty(expandedTree);
|
|
825
850
|
setTreeData(processedTree);
|
|
826
|
-
}, [inputDcmts, dcmtTypes, maxDepthLevel, isForMaster, invertMasterNavigation, getDetailDcmtsAsync, getMasterDcmtsAsync, abortController, updateHiddenProperty, showMainDocument, labelMainContainer, onNoRelationsFound]);
|
|
851
|
+
}, [inputDcmts, dcmtTypes, maxDepthLevel, isForMaster, invertMasterNavigation, getDetailDcmtsAsync, getMasterDcmtsAsync, abortController, updateHiddenProperty, showMainDocument, labelMainContainer, onNoRelationsFound, onCalculationStopped]);
|
|
827
852
|
/**
|
|
828
853
|
* Merge main tree data with additional static items
|
|
829
854
|
*/
|
|
@@ -1066,15 +1091,15 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1066
1091
|
let loadedItems = [];
|
|
1067
1092
|
if (isForMaster && !invertMasterNavigation) {
|
|
1068
1093
|
// Original mode: detail documents load detail documents (natural detail→detail navigation)
|
|
1069
|
-
loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1);
|
|
1094
|
+
loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1, newAbortController.signal);
|
|
1070
1095
|
}
|
|
1071
1096
|
else if (isForMaster) {
|
|
1072
1097
|
// Inverted master mode: load master documents
|
|
1073
|
-
loadedItems = await getMasterDcmtsAsync(node.tid, node.did, 1);
|
|
1098
|
+
loadedItems = await getMasterDcmtsAsync(node.tid, node.did, 1, newAbortController.signal);
|
|
1074
1099
|
}
|
|
1075
1100
|
else {
|
|
1076
1101
|
// Standard mode: load detail documents
|
|
1077
|
-
loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1);
|
|
1102
|
+
loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1, newAbortController.signal);
|
|
1078
1103
|
}
|
|
1079
1104
|
// Espandi automaticamente il primo container se ci sono documenti correlati
|
|
1080
1105
|
if (loadedItems.length > 0 && loadedItems[0].isContainer) {
|
|
@@ -1436,13 +1461,13 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1436
1461
|
let loadedItems = [];
|
|
1437
1462
|
// Carica i documenti correlati (detail o master in base alla modalità)
|
|
1438
1463
|
if (isForMaster && !invertMasterNavigation) {
|
|
1439
|
-
loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1);
|
|
1464
|
+
loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1, newAbortController.signal);
|
|
1440
1465
|
}
|
|
1441
1466
|
else if (isForMaster) {
|
|
1442
|
-
loadedItems = await getMasterDcmtsAsync(node.tid, node.did, 1);
|
|
1467
|
+
loadedItems = await getMasterDcmtsAsync(node.tid, node.did, 1, newAbortController.signal);
|
|
1443
1468
|
}
|
|
1444
1469
|
else {
|
|
1445
|
-
loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1);
|
|
1470
|
+
loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1, newAbortController.signal);
|
|
1446
1471
|
}
|
|
1447
1472
|
// Applica le regole di visibilità (showZeroDcmts)
|
|
1448
1473
|
expandedNode.items = updateHiddenProperty(loadedItems);
|
|
@@ -1543,6 +1568,10 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1543
1568
|
return _jsx("div", { style: { padding: '20px', textAlign: 'center' }, children: _jsx(TMWaitPanel, { title: SDKUI_Localizator.LoadingDetailDocuments, showPrimary: true, textPrimary: waitPanelTextPrimary, valuePrimary: waitPanelValuePrimary, maxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, onAbortClick: () => { setTimeout(() => { abortController.abort(); }, 1000); } }) });
|
|
1544
1569
|
}
|
|
1545
1570
|
if (mergedTreeData.length === 0) {
|
|
1571
|
+
// Calcolo interrotto dall'utente prima di aver calcolato qualsiasi correlazione
|
|
1572
|
+
if (loadStoppedByUser) {
|
|
1573
|
+
return _jsx(TMToppyMessage, { message: SDKUI_Localizator.RelationsCalculationStopped });
|
|
1574
|
+
}
|
|
1546
1575
|
// Se NON isForMaster e tutti i GetMetadataAsync sono falliti
|
|
1547
1576
|
if (!isForMaster && metadataErrorCount === inputDcmts.length) {
|
|
1548
1577
|
return _jsx(TMToppyMessage, { message: SDKUI_Localizator.DocumentsNotAvailableOrNoCorrelations });
|
|
@@ -1553,7 +1582,8 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1553
1582
|
return _jsx("div", { style: { padding: '20px', textAlign: 'center', color: '#666' }, children: SDKUI_Localizator.NoRelationsAvailable });
|
|
1554
1583
|
}
|
|
1555
1584
|
// Se isForMaster e non ci sono master documents disponibili
|
|
1556
|
-
|
|
1585
|
+
// (se il calcolo è stato interrotto l'albero parziale viene comunque mostrato)
|
|
1586
|
+
if (isForMaster && totalMasterDocuments === 0 && !loadStoppedByUser) {
|
|
1557
1587
|
return _jsx(TMToppyMessage, { message: SDKUI_Localizator.NoMasterDocumentsAvailable });
|
|
1558
1588
|
}
|
|
1559
1589
|
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0, width: '100%' }, children: [showExpandAllButton && (_jsxs("div", { style: { flexShrink: 0, display: 'flex', alignItems: 'center', gap: '6px', height: '40px', paddingLeft: '10px', backgroundColor: TMColors.toolbar_background }, children: [_jsx(TMTooltip, { content: expandLevel === 0
|
|
@@ -5,13 +5,13 @@ import TMSavedQuerySelector from './TMSavedQuerySelector';
|
|
|
5
5
|
import TMTreeSelector from './TMTreeSelector';
|
|
6
6
|
import { TabPanel, Item } from 'devextreme-react/tab-panel';
|
|
7
7
|
import TMSearchQueryPanel, { refreshLastSearch } from './TMSearchQueryPanel';
|
|
8
|
-
import { getSysAllDcmtsSQD, IconFilter, IconRecentlyViewed, IconSavedQuery, IconTree, removeMruTid, SDKUI_Globals, SDKUI_Localizator, updateMruTids } from '../../../helper';
|
|
8
|
+
import { getSysAllDcmtsSQD, SYS_ALL_DCMTS_SQD_ID, IconFilter, IconRecentlyViewed, IconSavedQuery, IconTree, mergeSearchResultsAppend, removeMruTid, SDKUI_Globals, SDKUI_Localizator, updateMruTids } from '../../../helper';
|
|
9
9
|
import TMSearchResult from './TMSearchResult';
|
|
10
10
|
import TMRecentsManager from '../../grids/TMRecentsManager';
|
|
11
11
|
import { SearchResultContext } from '../../../ts';
|
|
12
12
|
import { useDeviceType, DeviceType } from '../../base/TMDeviceProvider';
|
|
13
13
|
import { StyledMultiViewPanel } from '../../base/Styled';
|
|
14
|
-
import { useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
|
|
14
|
+
import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
|
|
15
15
|
import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
|
|
16
16
|
import { TMPanelManagerWithPersistenceProvider } from '../../layout/panelManager/TMPanelManagerWithPersistenceProvider';
|
|
17
17
|
import { TMExceptionBoxManager } from '../../base/TMPopUp';
|
|
@@ -32,7 +32,7 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
32
32
|
const [currentSearchView, setCurrentSearchView] = useState(TMSearchViews.Search);
|
|
33
33
|
const [currentSQDMode, setCurrentSQDMode] = useState(1);
|
|
34
34
|
const [lastQdSearched, setLastQdSearched] = useState();
|
|
35
|
-
const [showSearchResults, setShowSearchResults] = useState(
|
|
35
|
+
const [showSearchResults, setShowSearchResults] = useState(!onlyShowSearchQueryPanel);
|
|
36
36
|
const [maxDcmtsToBeReturned, setMaxDcmtsToBeReturned] = useState(SDKUI_Globals.userSettings.searchSettings?.maxDcmtsToBeReturned ?? 1000);
|
|
37
37
|
const deviceType = useDeviceType();
|
|
38
38
|
useEffect(() => {
|
|
@@ -152,6 +152,42 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
152
152
|
if (sqdToBeSet)
|
|
153
153
|
await setSqdAsync?.(sqdToBeSet);
|
|
154
154
|
}, []);
|
|
155
|
+
// --- REFRESH DEI PANNELLI ---
|
|
156
|
+
// Scorciatoie: rilegge dal server l'elenco dei tipi documento, così le scorciatoie riflettono
|
|
157
|
+
// quelli aggiunti o rimossi. La nuova identità di mruTIDs fa ricaricare i descrittori a TMRecentsManager.
|
|
158
|
+
const refreshRecentsAsync = useCallback(async () => {
|
|
159
|
+
DcmtTypeListCacheService.RemoveAllWithoutMetadata();
|
|
160
|
+
await DcmtTypeListCacheService.GetAllWithoutMetadataAsync();
|
|
161
|
+
setMruTIDs([...SDKUI_Globals.userSettings.searchSettings.mruTIDs]);
|
|
162
|
+
}, []);
|
|
163
|
+
// Ricerche rapide: invalida la cache delle saved query e ricarica l'elenco del tipo documento corrente
|
|
164
|
+
const refreshSavedQueriesAsync = useCallback(async () => {
|
|
165
|
+
// loadDataSQDsAsync riporta la selezione sulla prima tab: il refresh non deve spostare quella scelta dall'utente
|
|
166
|
+
const sqdMode = currentSQDMode;
|
|
167
|
+
await loadDataSQDsAsync(true, fromDTD?.id ?? currentTID);
|
|
168
|
+
setCurrentSQDMode(sqdMode);
|
|
169
|
+
}, [fromDTD?.id, currentTID, currentSQDMode]);
|
|
170
|
+
// Pannello dei metadati: rilegge dal server i metadati del tipo documento e la definizione della
|
|
171
|
+
// ricerca rapida corrente, con cui il pannello ricostruisce i filtri (i valori digitati vengono persi)
|
|
172
|
+
const refreshSearchQueryPanelAsync = useCallback(async () => {
|
|
173
|
+
const tid = fromDTD?.id ?? currentTID;
|
|
174
|
+
if (!tid)
|
|
175
|
+
return;
|
|
176
|
+
const dtd = await DcmtTypeListCacheService.GetAsync(tid, true, undefined, false, true);
|
|
177
|
+
setFromDTD(dtd);
|
|
178
|
+
// Passare da undefined forza la ricostruzione dei filtri anche quando la query selezionata non cambia
|
|
179
|
+
const sqdToRestore = currentSQD;
|
|
180
|
+
SavedQueryCacheService.Remove();
|
|
181
|
+
await setSQDAsync(undefined);
|
|
182
|
+
// La ricerca di sistema non è in cache: va ricostruita, così recepisce i metadati appena riletti
|
|
183
|
+
await setSQDAsync(sqdToRestore?.id === SYS_ALL_DCMTS_SQD_ID ? await getSysAllDcmtsSQD(tid, false) : sqdToRestore);
|
|
184
|
+
// mruTIDs è tra le dipendenze perché setSQDAsync lo legge
|
|
185
|
+
}, [fromDTD?.id, currentTID, currentSQD, mruTIDs]);
|
|
186
|
+
// Prima di ogni ricerca il pannello rilegge i metadati del tipo documento: si recepisce il descrittore
|
|
187
|
+
// aggiornato, così anche il resto della vista (titoli, badge, form dei metadati) lavora sulla lista corrente
|
|
188
|
+
const handleDcmtTypeReloaded = useCallback((dtd) => {
|
|
189
|
+
setFromDTD(dtd);
|
|
190
|
+
}, []);
|
|
155
191
|
const onRefreshSearchAsyncDatagrid = async () => {
|
|
156
192
|
try {
|
|
157
193
|
if (lastQdSearched) {
|
|
@@ -164,6 +200,32 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
164
200
|
console.error("Error refreshing search:", error);
|
|
165
201
|
}
|
|
166
202
|
};
|
|
203
|
+
const handleSearchCompleted = useCallback((searchResult, qd, append) => {
|
|
204
|
+
if (searchResult.length <= 0) {
|
|
205
|
+
// In ricerca normale un array vuoto resetta i risultati; in accoda si mantiene il set accumulato
|
|
206
|
+
if (!append)
|
|
207
|
+
setSearchResult(searchResult);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const newResult = searchResult[0];
|
|
211
|
+
// In modalità accoda unisce il nuovo risultato a quello precedente (più recenti in cima).
|
|
212
|
+
setSearchResult(prev => {
|
|
213
|
+
if (append && prev.length > 0 && prev[0]?.fromTID === newResult?.fromTID) {
|
|
214
|
+
const merged = mergeSearchResultsAppend(prev[0], newResult);
|
|
215
|
+
return merged ? [merged] : searchResult;
|
|
216
|
+
}
|
|
217
|
+
return searchResult;
|
|
218
|
+
});
|
|
219
|
+
setLastQdSearched(qd);
|
|
220
|
+
setCurrentSearchView(TMSearchViews.Result);
|
|
221
|
+
// Salvataggio ultimi 10 TIDs
|
|
222
|
+
let fromTID = searchResult?.[0].fromTID;
|
|
223
|
+
let newMruTIDS = updateMruTids(SDKUI_Globals.userSettings.searchSettings.mruTIDs, fromTID);
|
|
224
|
+
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS;
|
|
225
|
+
setMruTIDs(newMruTIDS);
|
|
226
|
+
setCurrentMruTID(fromTID);
|
|
227
|
+
setShowSearchResults(true);
|
|
228
|
+
}, []);
|
|
167
229
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
168
230
|
const isTabletOrMobile = deviceType === DeviceType.TABLET || deviceType === DeviceType.MOBILE;
|
|
169
231
|
// --- JSX WRAPPERS ---
|
|
@@ -182,23 +244,11 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
182
244
|
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS;
|
|
183
245
|
setMruTIDs(newMruTIDS);
|
|
184
246
|
} }), [mruTIDs, currentMruTID, deviceType]);
|
|
185
|
-
const tmSearchQueryPanelElement = useMemo(() => _jsx(TMSearchQueryPanelWrapper, { passToArchiveCallback: passToArchiveCallback, isExpertMode: isExpertMode, showBackToResultButton: searchResult.length > 0, fromDTD: fromDTD, SQD: currentSQD, inputMids: inputMids, maxDcmtsToBeReturned: maxDcmtsToBeReturned, onBackToResult: () => {
|
|
186
|
-
|
|
187
|
-
if (searchResult.length <= 0)
|
|
188
|
-
return;
|
|
189
|
-
setLastQdSearched(qd);
|
|
190
|
-
setCurrentSearchView(TMSearchViews.Result);
|
|
191
|
-
// Salvataggio ultimi 10 TIDs
|
|
192
|
-
let fromTID = searchResult?.[0].fromTID;
|
|
193
|
-
let newMruTIDS = updateMruTids(SDKUI_Globals.userSettings.searchSettings.mruTIDs, fromTID);
|
|
194
|
-
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS;
|
|
195
|
-
setMruTIDs(newMruTIDS);
|
|
196
|
-
setCurrentMruTID(fromTID);
|
|
197
|
-
setShowSearchResults(true);
|
|
198
|
-
}, onSqdSaved: async (newSqd) => {
|
|
247
|
+
const tmSearchQueryPanelElement = useMemo(() => _jsx(TMSearchQueryPanelWrapper, { isSearchViewOnScreen: currentSearchView === TMSearchViews.Search, passToArchiveCallback: passToArchiveCallback, isExpertMode: isExpertMode, showBackToResultButton: searchResult.length > 0, fromDTD: fromDTD, SQD: currentSQD, inputMids: inputMids, maxDcmtsToBeReturned: maxDcmtsToBeReturned, onBackToResult: () => { if (onlyShowSearchQueryPanel)
|
|
248
|
+
setShowSearchResults(true); setCurrentSearchView(TMSearchViews.Result); }, onSearchCompleted: handleSearchCompleted, onRefreshRequested: refreshSearchQueryPanelAsync, onDcmtTypeReloaded: handleDcmtTypeReloaded, onSqdSaved: async (newSqd) => {
|
|
199
249
|
await loadDataSQDsAsync(true, newSqd.masterTID);
|
|
200
250
|
await setSQDAsync(newSqd);
|
|
201
|
-
} }), [fromDTD, showSearchResults, setShowSearchResults, currentSQD, isExpertMode, mruTIDs, searchResult, passToArchiveCallback, inputMids, maxDcmtsToBeReturned]);
|
|
251
|
+
} }), [fromDTD, showSearchResults, setShowSearchResults, currentSQD, currentSearchView, isExpertMode, mruTIDs, searchResult, passToArchiveCallback, inputMids, maxDcmtsToBeReturned, handleSearchCompleted, refreshSearchQueryPanelAsync, handleDcmtTypeReloaded, onlyShowSearchQueryPanel]);
|
|
202
252
|
const tmSavedQuerySelectorElement = useMemo(() => _jsxs(TabPanel, { width: "100%", height: "100%", showNavButtons: true, repaintChangesOnly: true, selectedIndex: currentSQDMode, onSelectedIndexChange: (index) => setCurrentSQDMode(index), children: [(currentTID || currentSQD) ? _jsx(Item, { title: fromDTD?.nameLoc, children: _jsx(TMSavedQuerySelectorWrapper, { allowShowSearch: false, items: filteredByTIDSQDs, selectedId: currentSQD?.id, onRefreshData: () => { loadDataSQDsAsync(true); }, onItemClick: (sqd) => {
|
|
203
253
|
onSQDItemClick(sqd, setSQDAsync);
|
|
204
254
|
}, onDeleted: (sqd) => onSQDDeleted(sqd, sqd.id == currentSQD?.id ? filteredByTIDSQDs.find(o => o.id == 1) : currentSQD, setSQDAsync), refreshFavoriteSavedQueries: refreshFavoriteSavedQueries }) }) : _jsx(_Fragment, {}), _jsx(Item, { title: SDKUI_Localizator.AllFemale, children: _jsx(TMSavedQuerySelectorWrapper, { allowShowSearch: true, items: allSQDs, manageDefault: false, onItemClick: (sqd) => {
|
|
@@ -250,7 +300,14 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
250
300
|
{
|
|
251
301
|
id: 'TMRecentsManager',
|
|
252
302
|
name: SDKUI_Localizator.Shortcuts,
|
|
253
|
-
contentOptions: {
|
|
303
|
+
contentOptions: {
|
|
304
|
+
component: tmRecentsManagerElement,
|
|
305
|
+
panelContainer: {
|
|
306
|
+
title: SDKUI_Localizator.Shortcuts,
|
|
307
|
+
totalItems: mruTIDs.length,
|
|
308
|
+
onRefresh: refreshRecentsAsync
|
|
309
|
+
}
|
|
310
|
+
},
|
|
254
311
|
toolbarOptions: { icon: _jsx(IconRecentlyViewed, { fontSize: 24 }), visible: true, orderNumber: 2, isActive: allInitialPanelVisibility['TMRecentsManager'] }
|
|
255
312
|
},
|
|
256
313
|
{
|
|
@@ -262,11 +319,33 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
|
|
|
262
319
|
{
|
|
263
320
|
id: 'TMSavedQuerySelector',
|
|
264
321
|
name: SDK_Localizator.SavedQueries,
|
|
265
|
-
contentOptions: {
|
|
322
|
+
contentOptions: {
|
|
323
|
+
component: tmSavedQuerySelectorElement,
|
|
324
|
+
panelContainer: {
|
|
325
|
+
title: SDK_Localizator.SavedQueries,
|
|
326
|
+
onRefresh: refreshSavedQueriesAsync
|
|
327
|
+
}
|
|
328
|
+
},
|
|
266
329
|
toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
|
|
267
330
|
}
|
|
268
|
-
], [tmTreeSelectorElement, showSearchResults, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
|
|
269
|
-
|
|
331
|
+
], [tmTreeSelectorElement, showSearchResults, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs, refreshRecentsAsync, refreshSavedQueriesAsync]);
|
|
332
|
+
// Quando è visibile solo il pannello di ricerca (es. modale di abbinamento molti a molti) serve
|
|
333
|
+
const singlePanelVisibility = { 'TMSearchQueryPanel': true };
|
|
334
|
+
const singlePanelDimensions = { 'TMSearchQueryPanel': { width: '100%', height: '100%' } };
|
|
335
|
+
const singlePanelDefinition = useMemo(() => [
|
|
336
|
+
{
|
|
337
|
+
id: 'TMSearchQueryPanel',
|
|
338
|
+
name: fromDTD?.nameLoc ?? SDKUI_Localizator.Search_Metadata,
|
|
339
|
+
contentOptions: { component: tmSearchQueryPanelElement },
|
|
340
|
+
toolbarOptions: { icon: _jsx(IconFilter, { fontSize: 24 }), visible: false, orderNumber: 1, isActive: true }
|
|
341
|
+
}
|
|
342
|
+
], [tmSearchQueryPanelElement, fromDTD]);
|
|
343
|
+
return (_jsxs(_Fragment, { children: [onlyShowSearchQueryPanel
|
|
344
|
+
// Il pannello di ricerca resta montato anche quando sono a schermo i risultati: tornando
|
|
345
|
+
// indietro si ritrova l'ultima ricerca impostata, senza rimontaggi che ne resettano i filtri
|
|
346
|
+
? _jsx(StyledMultiViewPanel, { "$isVisible": !showSearchResults, children: _jsx(TMPanelManagerProvider, { panels: singlePanelDefinition, initialVisibility: singlePanelVisibility, defaultDimensions: singlePanelDimensions, initialDimensions: singlePanelDimensions, initialMobilePanelId: 'TMSearchQueryPanel', children: tmSearchQueryPanelElement }) })
|
|
347
|
+
: _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)
|
|
348
|
+
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 })] }));
|
|
270
349
|
};
|
|
271
350
|
export default TMSearch;
|
|
272
351
|
const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
|
|
@@ -285,11 +364,11 @@ const TMRecentsManagerWrapper = ({ mruTIDs, currentMruTID, deviceType, onSelecte
|
|
|
285
364
|
onDeletedTID?.(tid);
|
|
286
365
|
} }));
|
|
287
366
|
};
|
|
288
|
-
const TMSearchQueryPanelWrapper = ({ fromDTD, SQD, isExpertMode, showBackToResultButton, onSearchCompleted, onSqdSaved, onBackToResult, passToArchiveCallback, inputMids, maxDcmtsToBeReturned }) => {
|
|
367
|
+
const TMSearchQueryPanelWrapper = ({ isSearchViewOnScreen, fromDTD, SQD, isExpertMode, showBackToResultButton, onSearchCompleted, onSqdSaved, onBackToResult, passToArchiveCallback, inputMids, maxDcmtsToBeReturned, onRefreshRequested, onDcmtTypeReloaded }) => {
|
|
289
368
|
const { setPanelVisibilityById, toggleMaximize, countVisibleLeafPanels } = useTMPanelManagerContext();
|
|
290
369
|
const deviceType = useDeviceType();
|
|
291
370
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
292
|
-
return (_jsx(TMSearchQueryPanel, { onClosePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('TMSearchQueryPanel', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => toggleMaximize("TMSearchQueryPanel") : undefined, isExpertMode: isExpertMode, fromDTD: fromDTD, SQD: SQD, inputMids: inputMids, onSearchCompleted: onSearchCompleted, onSqdSaved: onSqdSaved, showBackToResultButton: showBackToResultButton, onBackToResult: onBackToResult, passToArchiveCallback: passToArchiveCallback, maxDcmtsToBeReturned: maxDcmtsToBeReturned }));
|
|
371
|
+
return (_jsx(TMSearchQueryPanel, { isSearchViewOnScreen: isSearchViewOnScreen, onClosePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('TMSearchQueryPanel', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => toggleMaximize("TMSearchQueryPanel") : undefined, isExpertMode: isExpertMode, fromDTD: fromDTD, SQD: SQD, inputMids: inputMids, onSearchCompleted: onSearchCompleted, onRefreshRequested: onRefreshRequested, onDcmtTypeReloaded: onDcmtTypeReloaded, onSqdSaved: onSqdSaved, showBackToResultButton: showBackToResultButton, onBackToResult: onBackToResult, passToArchiveCallback: passToArchiveCallback, maxDcmtsToBeReturned: maxDcmtsToBeReturned }));
|
|
293
372
|
};
|
|
294
373
|
const TMSavedQuerySelectorWrapper = ({ items, selectedId, allowShowSearch, manageDefault, onRefreshData, onItemClick, onDeleted, refreshFavoriteSavedQueries }) => {
|
|
295
374
|
const { setPanelVisibilityById } = useTMPanelManagerContext();
|
|
@@ -58,10 +58,12 @@ const TMSearchQueryEditor = ({ qd, dcmtTypesList = [], isExpertMode = SDKUI_Glob
|
|
|
58
58
|
const handleItemSelect = useCallback((tid, mid) => {
|
|
59
59
|
if (currentEditingMID !== mid)
|
|
60
60
|
setCurrentEditingMID(mid);
|
|
61
|
-
if (!focusedTidMid || mid !== focusedTidMid.mid) {
|
|
62
|
-
|
|
61
|
+
if (!focusedTidMid || mid !== focusedTidMid.mid || tid !== focusedTidMid.tid) {
|
|
62
|
+
const newFocusedTidMid = { tid: tid, mid: mid };
|
|
63
|
+
setFocusedTidMid(newFocusedTidMid);
|
|
64
|
+
onFocusedMetadataChanged?.(newFocusedTidMid);
|
|
63
65
|
}
|
|
64
|
-
}, [currentEditingMID, focusedTidMid]);
|
|
66
|
+
}, [currentEditingMID, focusedTidMid, onFocusedMetadataChanged]);
|
|
65
67
|
const handleAdvancedMenuClick = useCallback((e) => {
|
|
66
68
|
if (e.button === AdvancedMenuButtons.MakeEditable && e.mid) {
|
|
67
69
|
addOrRemoveEditableList(e.mid);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { DcmtTypeDescriptor, QueryDescriptor, SavedQueryDescriptor, SearchResultDescriptor } from '@topconsultnpm/sdk-ts';
|
|
3
3
|
interface ITMSearchQueryPanelProps {
|
|
4
|
+
isSearchViewOnScreen?: boolean;
|
|
4
5
|
fromDTD?: DcmtTypeDescriptor;
|
|
5
6
|
SQD?: SavedQueryDescriptor;
|
|
6
7
|
isExpertMode?: boolean;
|
|
@@ -12,7 +13,7 @@ interface ITMSearchQueryPanelProps {
|
|
|
12
13
|
onBack?: () => void;
|
|
13
14
|
onBackToResult?: () => void;
|
|
14
15
|
onSqdSaved?: (newSqd: SavedQueryDescriptor) => void;
|
|
15
|
-
onSearchCompleted?: (searchResult: SearchResultDescriptor[], qd: QueryDescriptor | undefined) => void;
|
|
16
|
+
onSearchCompleted?: (searchResult: SearchResultDescriptor[], qd: QueryDescriptor | undefined, append?: boolean) => void;
|
|
16
17
|
onClosePanel?: () => void;
|
|
17
18
|
allowMaximize?: boolean;
|
|
18
19
|
onMaximizePanel?: () => void;
|
|
@@ -21,10 +22,19 @@ interface ITMSearchQueryPanelProps {
|
|
|
21
22
|
value: string;
|
|
22
23
|
}>, tid?: number) => void;
|
|
23
24
|
maxDcmtsToBeReturned?: number;
|
|
25
|
+
onRefreshRequested?: () => Promise<void>;
|
|
26
|
+
/** Notifica il tipo documento riletto dal server prima di ogni ricerca, così il chiamante allinea il proprio descrittore */
|
|
27
|
+
onDcmtTypeReloaded?: (dtd: DcmtTypeDescriptor) => void;
|
|
24
28
|
}
|
|
25
29
|
declare const TMSearchQueryPanel: React.FunctionComponent<ITMSearchQueryPanelProps>;
|
|
26
30
|
export default TMSearchQueryPanel;
|
|
27
31
|
export declare const refreshLastSearch: (qd: QueryDescriptor | undefined) => Promise<SearchResultDescriptor[] | undefined>;
|
|
28
|
-
export declare const StyledToppyTextContainer: import("styled-components/dist/types").IStyledComponentBase<"web",
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
export declare const StyledToppyTextContainer: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
|
|
33
|
+
style?: React.CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
|
|
34
|
+
}> & string;
|
|
35
|
+
export declare const StyledToppyText: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, "style"> & {
|
|
36
|
+
style?: React.CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
|
|
37
|
+
}> & string;
|
|
38
|
+
export declare const StyledToppyImage: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "style"> & {
|
|
39
|
+
style?: React.CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
|
|
40
|
+
}> & string;
|