@topconsultnpm/sdkui-react 6.21.0-t3 → 6.21.0-t4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +23 -18
  2. package/lib/components/base/TMPopUp.js +3 -3
  3. package/lib/components/base/TMTreeView.d.ts +16 -13
  4. package/lib/components/base/TMTreeView.js +230 -64
  5. package/lib/components/choosers/TMDistinctValues.js +1 -1
  6. package/lib/components/editors/TMTextBox.d.ts +1 -0
  7. package/lib/components/editors/TMTextBox.js +2 -1
  8. package/lib/components/features/documents/TMDcmtForm.d.ts +2 -0
  9. package/lib/components/features/documents/TMDcmtForm.js +2 -1
  10. package/lib/components/features/documents/TMDcmtIcon.d.ts +3 -1
  11. package/lib/components/features/documents/TMDcmtIcon.js +5 -32
  12. package/lib/components/features/documents/TMFileUploader.js +1 -1
  13. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
  14. package/lib/components/features/documents/TMMasterDetailDcmts.js +54 -14
  15. package/lib/components/features/documents/TMMergeToPdfForm.d.ts +2 -1
  16. package/lib/components/features/documents/TMMergeToPdfForm.js +91 -48
  17. package/lib/components/features/documents/TMRelationViewer.d.ts +12 -10
  18. package/lib/components/features/documents/TMRelationViewer.js +401 -96
  19. package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +4 -3
  20. package/lib/components/features/documents/copyAndMergeDcmtsShared.js +47 -23
  21. package/lib/components/features/documents/mergePdfUtils.d.ts +52 -0
  22. package/lib/components/features/documents/mergePdfUtils.js +268 -0
  23. package/lib/components/features/search/TMSearch.d.ts +2 -0
  24. package/lib/components/features/search/TMSearch.js +2 -2
  25. package/lib/components/features/search/TMSearchResult.d.ts +2 -0
  26. package/lib/components/features/search/TMSearchResult.js +58 -9
  27. package/lib/components/viewers/TMTidViewer.js +14 -2
  28. package/lib/helper/Enum_Localizator.js +1 -0
  29. package/lib/helper/SDKUI_Globals.d.ts +1 -0
  30. package/lib/helper/SDKUI_Globals.js +1 -0
  31. package/lib/helper/SDKUI_Localizator.d.ts +34 -0
  32. package/lib/helper/SDKUI_Localizator.js +352 -12
  33. package/lib/helper/TMUtils.d.ts +33 -1
  34. package/lib/helper/TMUtils.js +104 -1
  35. package/lib/helper/certificateImportHelper.d.ts +43 -0
  36. package/lib/helper/certificateImportHelper.js +403 -0
  37. package/lib/helper/helpers.js +9 -0
  38. package/lib/helper/index.d.ts +1 -0
  39. package/lib/helper/index.js +1 -0
  40. package/lib/hooks/useDcmtOperations.d.ts +2 -1
  41. package/lib/hooks/useDcmtOperations.js +10 -2
  42. package/lib/hooks/useDocumentOperations.d.ts +2 -0
  43. package/lib/hooks/useDocumentOperations.js +28 -6
  44. package/lib/services/platform_services.d.ts +1 -1
  45. package/lib/ts/types.d.ts +2 -1
  46. package/lib/ts/types.js +1 -0
  47. package/package.json +3 -2
@@ -1,14 +1,18 @@
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, MetadataFormats, SystemMIDs, MetadataDataDomains, RelationCacheService, RelationTypes, UserListCacheService } from "@topconsultnpm/sdk-ts";
4
- import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus, IconChevronDown, IconChevronRight, SDKUI_Localizator } from '../../../helper';
3
+ import { DcmtTypeListCacheService, SDK_Globals, DataColumnTypes, MetadataFormats, MetadataDataDomains, RelationCacheService, RelationTypes, UserListCacheService } from "@topconsultnpm/sdk-ts";
4
+ import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus, IconChevronDown, IconChevronRight, SDKUI_Localizator, buildDcmtDisplayName, SDKUI_Globals } from '../../../helper';
5
+ import ShowAlert from '../../base/TMAlert';
6
+ import TMToppyMessage from '../../../helper/TMToppyMessage';
5
7
  import { TMColors } from '../../../utils/theme';
6
- import { StyledDivHorizontal, StyledBadge, StyledToolbarForm } from '../../base/Styled';
8
+ import { StyledDivHorizontal, StyledBadge } from '../../base/Styled';
7
9
  import TMTreeView from '../../base/TMTreeView';
8
10
  import { TMWaitPanel } from '../../base/TMWaitPanel';
9
11
  import TMDataListItemViewer from '../../viewers/TMDataListItemViewer';
10
12
  import TMDcmtIcon from './TMDcmtIcon';
11
13
  import TMDataUserIdItemViewer from '../../viewers/TMDataUserIdItemViewer';
14
+ import TMTooltip from '../../base/TMTooltip';
15
+ import TMSpinner from '../../base/TMSpinner';
12
16
  /**
13
17
  * Check if document type has detail relations
14
18
  */
@@ -41,31 +45,6 @@ const isManyToManyRelation = async (relationID) => {
41
45
  const rdlManyToMany = allRelations.filter(o => o.relationType == RelationTypes.ManyToMany && o.id === relationID) ?? [];
42
46
  return rdlManyToMany.length > 0;
43
47
  };
44
- /**
45
- * Get metadata keys excluding system metadata
46
- */
47
- export const getMetadataKeys = (obj) => {
48
- if (!obj)
49
- return [];
50
- const keys = Object.keys(obj);
51
- // Escludi metadati di sistema (MID < 100 che sono uppercase) e altri campi tecnici
52
- const sysMIDs = Object.values(SystemMIDs).map(o => o.toUpperCase());
53
- return keys.filter(k => obj?.[k].value && !sysMIDs.includes(k)).filter(o => o !== "rowIndex" && o !== "ISLEXPROT");
54
- };
55
- /**
56
- * Get display value keys for a document (max 5, prioritize SYS_Abstract)
57
- */
58
- export const getDcmtDisplayValue = (obj) => {
59
- if (!obj)
60
- return [];
61
- // Prima cerca SYS_Abstract
62
- if (obj['SYS_Abstract']?.value) {
63
- return ['SYS_Abstract'];
64
- }
65
- // Altrimenti prendi i primi 5 metadati non di sistema
66
- const mdKeys = getMetadataKeys(obj);
67
- return mdKeys.slice(0, 5);
68
- };
69
48
  /**
70
49
  * Get display value formatted by column type
71
50
  */
@@ -113,36 +92,50 @@ export const getDisplayValueByColumn = (col, value) => {
113
92
  export const searchResultToDataSource = async (searchResult, hideSysMetadata) => {
114
93
  const rows = searchResult?.dtdResult?.rows ?? [];
115
94
  const tid = searchResult?.fromTID;
116
- const dtd = await DcmtTypeListCacheService.GetAsync(tid);
95
+ // IMPORTANT: Pass true to get full metadata with all properties (isSpecialSearchOutput, etc.)
96
+ const dtd = await DcmtTypeListCacheService.GetAsync(tid, true);
117
97
  const output = [];
118
98
  for (let index = 0; index < rows.length; index++) {
119
99
  const item = { rowIndex: index };
120
100
  const row = rows[index];
121
101
  for (let i = 0; i < row.length; i++) {
122
- const mid = Number(searchResult?.dtdResult?.columns?.[i]?.extendedProperties?.["MID"] ?? "0");
102
+ const column = searchResult?.dtdResult?.columns?.[i];
103
+ const mid = Number(column?.extendedProperties?.["MID"] ?? "0");
123
104
  if (hideSysMetadata && mid < 100)
124
105
  continue;
125
- let key = searchResult?.dtdResult?.columns?.[i].caption ?? '';
126
- if (mid <= 100)
106
+ // For system metadata (MID <= 100), use UPPERCASE caption as key
107
+ // For custom metadata (MID > 100), use caption as key but handle duplicates
108
+ let key = column?.caption ?? '';
109
+ if (mid <= 100) {
127
110
  key = key.toUpperCase();
111
+ }
112
+ else {
113
+ // If key already exists with a different MID, append MID to make it unique
114
+ if (item[key] !== undefined && item[key]?.md?.id !== mid) {
115
+ key = `${key}_${mid}`;
116
+ }
117
+ }
128
118
  const value = row[i];
129
119
  const md = dtd?.metadata?.find(o => o.id == mid);
130
120
  item[key] = {
131
121
  md: md,
132
- value: getDisplayValueByColumn(searchResult?.dtdResult?.columns?.[i], value)
122
+ value: getDisplayValueByColumn(column, value)
133
123
  };
134
124
  }
135
125
  output.push(item);
136
126
  }
137
127
  return output;
138
128
  };
139
- 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 }) => {
129
+ export const DEFAULT_RELATION_EXPAND_LEVEL = 4; // Default maximum depth level for expansion (can be adjusted)
130
+ 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 }) => {
140
131
  // State
141
132
  const [dcmtTypes, setDcmtTypes] = useState([]);
142
133
  const [treeData, setTreeData] = useState([]);
143
134
  const [showZeroDcmts, setShowZeroDcmts] = useState(initialShowZeroDcmts);
144
135
  const [staticItemsState, setStaticItemsState] = useState([]);
145
- const [allExpanded, setAllExpanded] = useState(defaultExpandAll);
136
+ const getInitialExpandLevel = () => SDKUI_Globals.userSettings?.searchSettings?.relationExpandLevel ?? DEFAULT_RELATION_EXPAND_LEVEL;
137
+ const [expandLevel, setExpandLevel] = useState(getInitialExpandLevel);
138
+ const [isAllCollapsed, setIsAllCollapsed] = useState(false);
146
139
  const initialExpandAllAppliedRef = React.useRef(false);
147
140
  const [showWaitPanel, setShowWaitPanel] = useState(false);
148
141
  const [waitPanelTextPrimary, setWaitPanelTextPrimary] = useState('');
@@ -158,6 +151,10 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
158
151
  const lastLoadedInputRef = React.useRef('');
159
152
  // State to track loaded input key - triggers re-render for focus selection
160
153
  const [loadedInputKey, setLoadedInputKey] = React.useState('');
154
+ // State to track how many GetMetadataAsync calls failed
155
+ const [metadataErrorCount, setMetadataErrorCount] = React.useState(0);
156
+ // State to track total master documents found (used when isForMaster is true)
157
+ const [totalMasterDocuments, setTotalMasterDocuments] = React.useState(0);
161
158
  // Ref to track if user has manually expanded/collapsed static items
162
159
  const userInteractedWithStaticItemsRef = React.useRef(false);
163
160
  // Ref to track the last inputKey for which we set the focused item
@@ -172,6 +169,18 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
172
169
  };
173
170
  fetchAllUsers();
174
171
  }, []);
172
+ // Notify parent when loading state changes
173
+ useEffect(() => {
174
+ const isLoading = showWaitPanel || showExpansionWaitPanel;
175
+ onLoadingStateChanged?.(isLoading);
176
+ }, [showWaitPanel, showExpansionWaitPanel, onLoadingStateChanged]);
177
+ // Sincronizza expandLevel quando userSettings.searchSettings.relationExpandLevel cambia
178
+ useEffect(() => {
179
+ const globalExpandLevel = SDKUI_Globals.userSettings?.searchSettings?.relationExpandLevel;
180
+ if (globalExpandLevel !== undefined && globalExpandLevel !== expandLevel) {
181
+ setExpandLevel(globalExpandLevel);
182
+ }
183
+ }, [SDKUI_Globals.userSettings?.searchSettings?.relationExpandLevel]);
175
184
  /**
176
185
  * Generate a stable key from inputDcmts to detect real changes
177
186
  */
@@ -200,7 +209,10 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
200
209
  return [];
201
210
  if (!mDID)
202
211
  return [];
203
- if (maxLevel <= 0)
212
+ // maxLevel = 0 means unlimited depth (expand as much as possible)
213
+ // maxLevel > 0 means specific depth limit
214
+ // maxLevel < 0 means stop recursion
215
+ if (maxLevel < 0)
204
216
  return [];
205
217
  const dcmtTypeHasRel = await hasDetailRelations(mTID);
206
218
  if (!dcmtTypeHasRel)
@@ -283,7 +295,10 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
283
295
  return [];
284
296
  if (!dDID)
285
297
  return [];
286
- if (maxLevel <= 0)
298
+ // maxLevel = 0 means unlimited depth (expand as much as possible)
299
+ // maxLevel > 0 means specific depth limit
300
+ // maxLevel < 0 means stop recursion
301
+ if (maxLevel < 0)
287
302
  return [];
288
303
  const dcmtTypeHasRel = await hasMasterRelations(dTID);
289
304
  if (!dcmtTypeHasRel)
@@ -341,6 +356,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
341
356
  isExpandible: canExpand, // Can this doc be expanded?
342
357
  values: row,
343
358
  searchResult: [searchResult],
359
+ fileExt: row?.FILEEXT?.value,
344
360
  // Leave items and itemsCount undefined so TMTreeView shows expand arrow based on isExpandible
345
361
  // Children will be loaded lazily by calculateItemsForNode when expanded
346
362
  expanded: false,
@@ -386,7 +402,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
386
402
  updatedItems = [
387
403
  {
388
404
  key: `__info__${node.key}`,
389
- name: 'Nessun documento correlato da visualizzare',
405
+ name: SDKUI_Localizator.NoRelatedDocumentsToDisplay,
390
406
  isContainer: false,
391
407
  isDcmt: false,
392
408
  isInfoMessage: true,
@@ -497,6 +513,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
497
513
  }
498
514
  const tree = [];
499
515
  let processedCount = 0;
516
+ let errorCount = 0;
500
517
  for (const dcmt of inputDcmts) {
501
518
  // Check for abort
502
519
  if (abortController.signal.aborted) {
@@ -509,7 +526,24 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
509
526
  if (!searchEngine)
510
527
  continue;
511
528
  // Load document metadata
512
- const result = await searchEngine.GetMetadataAsync(dcmt.TID, dcmt.DID, false);
529
+ let result;
530
+ try {
531
+ result = await searchEngine.GetMetadataAsync(dcmt.TID, dcmt.DID, false);
532
+ }
533
+ catch (metadataError) {
534
+ console.warn('[TMRelationViewer] GetMetadataAsync failed for TID:', dcmt.TID, 'DID:', dcmt.DID, metadataError);
535
+ errorCount++;
536
+ ShowAlert({
537
+ title: SDKUI_Localizator.Warning,
538
+ message: `Il documento (TID: ${dcmt.TID}, DID: ${dcmt.DID}) non esiste più o non è accessibile.`,
539
+ mode: 'warning',
540
+ duration: 5000
541
+ });
542
+ // Skip this document and continue with the next one
543
+ processedCount++;
544
+ setWaitPanelValuePrimary(processedCount);
545
+ continue;
546
+ }
513
547
  const dtd = await DcmtTypeListCacheService.GetAsync(dcmt.TID);
514
548
  // Parse document values
515
549
  const docValues = await searchResultToDataSource(result);
@@ -714,6 +748,24 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
714
748
  if (hasNoRelations && onNoRelationsFound) {
715
749
  onNoRelationsFound();
716
750
  }
751
+ // Update metadata error count state
752
+ setMetadataErrorCount(errorCount);
753
+ // Count total master documents (only relevant when isForMaster is true)
754
+ if (isForMaster) {
755
+ const countMasterDocuments = (items) => {
756
+ let count = 0;
757
+ for (const item of items) {
758
+ if (item.isDcmt && !item.isZero) {
759
+ count++;
760
+ }
761
+ if (item.items && Array.isArray(item.items)) {
762
+ count += countMasterDocuments(item.items);
763
+ }
764
+ }
765
+ return count;
766
+ };
767
+ setTotalMasterDocuments(countMasterDocuments(tree));
768
+ }
717
769
  // FIRST setup initial expansion state (root container expanded, first document expanded with focus, first correlation folder expanded)
718
770
  // This must run BEFORE updateHiddenProperty so that infoMessage logic sees expanded=true
719
771
  const expandedTree = setupInitialTreeExpansion(tree);
@@ -904,7 +956,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
904
956
  return [
905
957
  {
906
958
  key: `__info__${node.key}`,
907
- name: 'Nessun documento correlato da visualizzare',
959
+ name: SDKUI_Localizator.NoRelatedDocumentsToDisplay,
908
960
  isContainer: false,
909
961
  isDcmt: false,
910
962
  isInfoMessage: true,
@@ -933,7 +985,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
933
985
  return [
934
986
  {
935
987
  key: `__info__${node.key}`,
936
- name: 'Nessun documento correlato da visualizzare',
988
+ name: SDKUI_Localizator.NoRelatedDocumentsToDisplay,
937
989
  isContainer: false,
938
990
  isDcmt: false,
939
991
  isInfoMessage: true,
@@ -988,7 +1040,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
988
1040
  return [
989
1041
  {
990
1042
  key: `__info__${node.key}`,
991
- name: 'Nessun documento correlato da visualizzare',
1043
+ name: SDKUI_Localizator.NoRelatedDocumentsToDisplay,
992
1044
  isContainer: false,
993
1045
  isDcmt: false,
994
1046
  isInfoMessage: true,
@@ -1083,34 +1135,36 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
1083
1135
  : defaultDocumentStyle;
1084
1136
  const textDecoration = isLogicallyDeleted ? 'line-through' : 'none';
1085
1137
  const textColor = isLogicallyDeleted ? 'gray' : undefined;
1086
- const defaultMetadataContent = item.values && (_jsx(StyledDivHorizontal, { style: {
1087
- fontSize: '1rem',
1088
- overflow: 'hidden',
1089
- flex: 1,
1090
- minWidth: 0,
1091
- whiteSpace: 'nowrap',
1092
- textDecoration: textDecoration,
1093
- color: textColor
1094
- }, children: getDcmtDisplayValue(item.values).map((key, index) => {
1095
- const md = item.values?.[key]?.md;
1096
- const value = item.values?.[key]?.value;
1097
- const displayValues = getDcmtDisplayValue(item.values);
1098
- const isLast = index === displayValues.length - 1;
1099
- return (_jsxs(StyledDivHorizontal, { style: {
1100
- flexShrink: isLast ? 1 : 0,
1101
- minWidth: isLast ? 0 : 'auto',
1102
- overflow: isLast ? 'hidden' : 'visible',
1103
- textDecoration: textDecoration,
1104
- color: textColor
1105
- }, children: [index > 0 && _jsx("span", { style: { margin: '0 5px', color: textColor || '#999', textDecoration: textDecoration }, children: "\u2022" }), showMetadataNames && (_jsxs("span", { style: { color: textColor || '#666', marginRight: '5px', textDecoration: textDecoration }, children: [md?.name || key, ":"] })), md?.dataDomain === MetadataDataDomains.DataList ? (_jsx("span", { style: { textDecoration: textDecoration, color: textColor }, children: _jsx(TMDataListItemViewer, { dataListId: md.dataListID, viewMode: md.dataListViewMode, value: value }) })) : md?.dataDomain === MetadataDataDomains.UserID ? (_jsx("span", { style: { textDecoration: textDecoration, color: textColor }, children: _jsx(TMDataUserIdItemViewer, { userId: value, showIcon: true }) })) : (_jsx("span", { style: {
1106
- fontWeight: 500,
1107
- overflow: isLast ? 'hidden' : 'visible',
1108
- textOverflow: isLast ? 'ellipsis' : 'clip',
1109
- whiteSpace: 'nowrap',
1110
- textDecoration: textDecoration,
1111
- color: textColor
1112
- }, children: value }))] }, `${key}_${index}`));
1113
- }) }));
1138
+ const defaultMetadataContent = item.values && (() => {
1139
+ const displayKeys = buildDcmtDisplayName(item.values);
1140
+ return (_jsx(StyledDivHorizontal, { style: {
1141
+ fontSize: '1rem',
1142
+ overflow: 'hidden',
1143
+ flex: 1,
1144
+ minWidth: 0,
1145
+ whiteSpace: 'nowrap',
1146
+ textDecoration: textDecoration,
1147
+ color: textColor
1148
+ }, children: displayKeys.map((key, index) => {
1149
+ const md = item.values?.[key]?.md;
1150
+ const value = item.values?.[key]?.value;
1151
+ const isLast = index === displayKeys.length - 1;
1152
+ return (_jsxs(StyledDivHorizontal, { style: {
1153
+ flexShrink: isLast ? 1 : 0,
1154
+ minWidth: isLast ? 0 : 'auto',
1155
+ overflow: isLast ? 'hidden' : 'visible',
1156
+ textDecoration: textDecoration,
1157
+ color: textColor
1158
+ }, children: [index > 0 && _jsx("span", { style: { margin: '0 5px', color: textColor || '#999', textDecoration: textDecoration }, children: "\u2022" }), showMetadataNames && (_jsxs("span", { style: { color: textColor || '#666', marginRight: '5px', textDecoration: textDecoration }, children: [md?.name || key, ":"] })), md?.dataDomain === MetadataDataDomains.DataList ? (_jsx("span", { style: { textDecoration: textDecoration, color: textColor }, children: _jsx(TMDataListItemViewer, { dataListId: md.dataListID, viewMode: md.dataListViewMode, value: value }) })) : md?.dataDomain === MetadataDataDomains.UserID ? (_jsx("span", { style: { textDecoration: textDecoration, color: textColor }, children: _jsx(TMDataUserIdItemViewer, { userId: value, showIcon: true }) })) : (_jsx("span", { style: {
1159
+ fontWeight: 500,
1160
+ overflow: isLast ? 'hidden' : 'visible',
1161
+ textOverflow: isLast ? 'ellipsis' : 'clip',
1162
+ whiteSpace: 'nowrap',
1163
+ textDecoration: textDecoration,
1164
+ color: textColor
1165
+ }, children: value }))] }, `${key}_${index}`));
1166
+ }) }));
1167
+ })();
1114
1168
  const metadataContent = customDocumentContent
1115
1169
  ? customDocumentContent(item, defaultMetadataContent || _jsx(_Fragment, {}))
1116
1170
  : defaultMetadataContent;
@@ -1137,7 +1191,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
1137
1191
  checkoutStatusIcon = checkoutStatus.icon;
1138
1192
  }
1139
1193
  }
1140
- return (_jsxs("div", { onDoubleClick: handleDoubleClick, style: documentStyle, children: [item.did && item.tid && showCurrentDcmtIndicator && inputDcmts?.some(d => d.DID === item.did && d.TID === item.tid) ? _jsx(IconBackhandIndexPointingRight, { fontSize: 22, overflow: 'visible' }) : _jsx(_Fragment, {}), item.values && (_jsx(TMDcmtIcon, { tid: item.values?.TID?.value, did: item.values?.DID?.value, fileExtension: item.values?.FILEEXT?.value, fileCount: item.values?.FILECOUNT?.value, isLexProt: item.values?.IsLexProt?.value, isMail: item.values?.ISMAIL?.value, isShared: item.values?.ISSHARED?.value, isSigned: item.values?.ISSIGNED?.value, downloadMode: 'openInNewWindow' })), checkoutStatusIcon, metadataContent] }));
1194
+ return (_jsxs("div", { onDoubleClick: handleDoubleClick, style: documentStyle, children: [item.did && item.tid && showCurrentDcmtIndicator && inputDcmts?.some(d => d.DID === item.did && d.TID === item.tid) ? _jsx(IconBackhandIndexPointingRight, { fontSize: 22, overflow: 'visible' }) : _jsx(_Fragment, {}), item.values && (_jsx(TMDcmtIcon, { tid: item.values?.TID?.value, did: item.values?.DID?.value, fileExtension: item.values?.FILEEXT?.value, fileCount: item.values?.FILECOUNT?.value, isLexProt: item.values?.IsLexProt?.value, isMail: item.values?.ISMAIL?.value, isShared: item.values?.ISSHARED?.value, isSigned: item.values?.ISSIGNED?.value, downloadMode: 'openInNewWindow', usePortal: true })), checkoutStatusIcon, metadataContent] }));
1141
1195
  }, [onDocumentDoubleClick, showCurrentDcmtIndicator, inputDcmts, customMainContainerContent, customDocumentStyle, customDocumentContent, showMetadataNames, showMainDocument, allUsers]);
1142
1196
  /**
1143
1197
  * Wrapper renderer that handles custom rendering if provided
@@ -1183,13 +1237,231 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
1183
1237
  return { ...node, expanded: canExpand ? expanded : node.expanded, items: newItems };
1184
1238
  });
1185
1239
  }, []);
1186
- const handleToggleExpandAll = useCallback(() => {
1187
- const next = !allExpanded;
1188
- setAllExpanded(next);
1189
- setTreeData(prev => setExpandedRecursively(prev, next));
1190
- setStaticItemsState(prev => setExpandedRecursively(prev, next));
1191
- userInteractedWithStaticItemsRef.current = true;
1192
- }, [allExpanded, setExpandedRecursively]);
1240
+ // Collassa l'albero impostando tutti i nodi come non espansi
1241
+ const handleCollapseTree = useCallback(() => {
1242
+ // Funzione helper per collassare ricorsivamente tutti i nodi
1243
+ const collapseAllNodes = (nodes) => {
1244
+ return nodes.map(node => ({
1245
+ ...node,
1246
+ expanded: false,
1247
+ items: node.items ? collapseAllNodes(node.items) : node.items
1248
+ }));
1249
+ };
1250
+ // Collassa tutti i nodi dell'albero
1251
+ setTreeData(prevData => collapseAllNodes(prevData));
1252
+ setStaticItemsState(prevData => collapseAllNodes(prevData));
1253
+ setIsAllCollapsed(true);
1254
+ }, []);
1255
+ /**
1256
+ * Espande ricorsivamente l'albero fino a `expandLevel`.
1257
+ * Carica i figli lazy (API) solo se non già in memoria (isLoaded).
1258
+ * Il contatore totalNodes cresce dinamicamente per una % progresso accurata.
1259
+ *
1260
+ * @param forceReload - Se true (Ctrl+click), ricarica tutto ignorando la cache
1261
+ */
1262
+ const handleExpandToLevel = useCallback(async (forceReload = false) => {
1263
+ // Mostra spinner per feedback immediato all'utente
1264
+ TMSpinner.show({ description: forceReload ? SDKUI_Localizator.FullReloadInProgress : SDKUI_Localizator.ExpansionInProgress });
1265
+ // Piccolo delay per permettere allo spinner di renderizzarsi prima del processing pesante
1266
+ await new Promise(resolve => setTimeout(resolve, 50));
1267
+ /**
1268
+ * Se forceReload è true, prima resettiamo tutti i nodi come se non fossero mai stati caricati.
1269
+ * Questo significa rimuovere isLoaded e items da tutti i nodi documento,
1270
+ * così l'espansione successiva li ricaricherà tutti da API.
1271
+ */
1272
+ const resetLoadedState = (nodes) => {
1273
+ return nodes.map(node => {
1274
+ const resetNode = { ...node };
1275
+ // Reset isLoaded per forzare il ricaricamento
1276
+ if (resetNode.isDcmt || resetNode.isExpandible) {
1277
+ resetNode.isLoaded = false;
1278
+ // Manteniamo items solo per i container (cartelle),
1279
+ // perché i container non vengono ricaricati via API
1280
+ // I documenti invece devono ricaricare i loro figli (correlazioni)
1281
+ if (resetNode.isDcmt) {
1282
+ resetNode.items = undefined;
1283
+ resetNode.itemsCount = undefined;
1284
+ }
1285
+ }
1286
+ // Reset ricorsivo sui figli
1287
+ if (resetNode.items && Array.isArray(resetNode.items)) {
1288
+ resetNode.items = resetLoadedState(resetNode.items);
1289
+ }
1290
+ return resetNode;
1291
+ });
1292
+ };
1293
+ // Se forceReload, reset dello stato prima di iniziare
1294
+ let workingTreeData = treeData;
1295
+ let workingStaticData = staticItemsState;
1296
+ if (forceReload) {
1297
+ workingTreeData = resetLoadedState(treeData);
1298
+ workingStaticData = resetLoadedState(staticItemsState);
1299
+ // Aggiorna subito lo stato per riflettere il reset
1300
+ setTreeData(workingTreeData);
1301
+ setStaticItemsState(workingStaticData);
1302
+ }
1303
+ const targetLevel = expandLevel;
1304
+ const newAbortController = new AbortController();
1305
+ setExpansionAbortController(newAbortController);
1306
+ // CONTATORI DINAMICI:
1307
+ // - totalNodes: cresce quando scopriamo nuovi nodi (evita che percentuale > 100%)
1308
+ // - processedNodes: quanti nodi abbiamo già processato
1309
+ // - maxReachedProgress: percentuale massima raggiunta (evita che la barra torni indietro)
1310
+ let totalNodes = 0;
1311
+ let processedNodes = 0;
1312
+ let hasApiCalls = false;
1313
+ let maxReachedProgress = 0;
1314
+ /**
1315
+ * Conta i nodi espandibili in un array (solo primo livello, non ricorsivo).
1316
+ * Usato per aggiornare totalNodes man mano che scopriamo nuovi figli.
1317
+ */
1318
+ const countNodesAtLevel = (nodes) => {
1319
+ let count = 0;
1320
+ for (const node of nodes) {
1321
+ if (node.isContainer || node.isExpandible || node.isDcmt) {
1322
+ count++;
1323
+ }
1324
+ }
1325
+ return count;
1326
+ };
1327
+ // Conta iniziale: solo i nodi al livello root
1328
+ totalNodes = countNodesAtLevel([...workingTreeData, ...workingStaticData]);
1329
+ /**
1330
+ * FUNZIONE RICORSIVA DI ESPANSIONE
1331
+ *
1332
+ * @param nodes - Array di nodi da processare
1333
+ * @param currentLevel - Livello corrente (0 = root)
1334
+ * @returns Array di nodi con expanded=true e figli caricati
1335
+ *
1336
+ * FLUSSO:
1337
+ * 1. Se targetLevel > 0 e currentLevel >= targetLevel → STOP, ritorna i nodi così come sono
1338
+ * (Se targetLevel = 0 → espandi senza limiti, non applicare mai il limite)
1339
+ * 2. Per ogni nodo espandibile:
1340
+ * a) Imposta expanded = true
1341
+ * b) Se i figli non sono caricati → chiama API per caricarli
1342
+ * c) Aggiorna totalNodes con i nuovi figli scoperti
1343
+ * d) CHIAMATA RICORSIVA su expandedNode.items con currentLevel + 1
1344
+ * → QUESTO È IL PUNTO CHIAVE: i nuovi nodi vengono espansi!
1345
+ */
1346
+ const expandToLevel = async (nodes, currentLevel) => {
1347
+ // CONDIZIONE DI USCITA: abbiamo raggiunto il livello target
1348
+ // targetLevel = 0 significa espandi senza limiti (non applicare mai il limite)
1349
+ // targetLevel > 0 significa applica il limite normalmente
1350
+ if (targetLevel > 0 && currentLevel >= targetLevel)
1351
+ return nodes;
1352
+ // Controlla se l'utente ha annullato l'operazione
1353
+ if (newAbortController.signal.aborted)
1354
+ return nodes;
1355
+ const result = [];
1356
+ for (const node of nodes) {
1357
+ // Controlla abort per ogni nodo (permette cancellazione veloce)
1358
+ if (newAbortController.signal.aborted) {
1359
+ result.push(node);
1360
+ continue;
1361
+ }
1362
+ // Crea copia del nodo (immutabilità React)
1363
+ let expandedNode = { ...node };
1364
+ // Verifica se questo nodo può essere espanso
1365
+ const canExpand = node.isContainer || node.isExpandible || node.isDcmt;
1366
+ if (canExpand) {
1367
+ // PASSO 1: Imposta il nodo come espanso
1368
+ expandedNode.expanded = true;
1369
+ // PASSO 2: Verifica se i figli sono già caricati o vanno caricati via API
1370
+ // Se forceReload è true, ricarica sempre (ignora isLoaded e items esistenti)
1371
+ const hasLoadedItems = !forceReload && node.items && Array.isArray(node.items) && node.items.length > 0;
1372
+ const actualHasItems = node.items && Array.isArray(node.items) && node.items.length > 0;
1373
+ const needsLoading = (forceReload || (!hasLoadedItems && !node.isLoaded)) && (node.isExpandible || node.isDcmt);
1374
+ if (needsLoading && node.tid && node.did) {
1375
+ // ═══════════════════════════════════════════════════════════════
1376
+ // CASO A: I figli NON sono in memoria → CHIAMATA API
1377
+ // ═══════════════════════════════════════════════════════════════
1378
+ // Mostra pannello di attesa solo quando ci sono chiamate API
1379
+ if (!hasApiCalls) {
1380
+ hasApiCalls = true;
1381
+ TMSpinner.hide();
1382
+ setShowExpansionWaitPanel(true);
1383
+ setExpansionWaitPanelMaxValue(100);
1384
+ setExpansionWaitPanelValue(0);
1385
+ }
1386
+ try {
1387
+ let loadedItems = [];
1388
+ // Carica i documenti correlati (detail o master in base alla modalità)
1389
+ if (isForMaster && !invertMasterNavigation) {
1390
+ loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1);
1391
+ }
1392
+ else if (isForMaster) {
1393
+ loadedItems = await getMasterDcmtsAsync(node.tid, node.did, 1);
1394
+ }
1395
+ else {
1396
+ loadedItems = await getDetailDcmtsAsync(node.tid, node.did, 1);
1397
+ }
1398
+ // Applica le regole di visibilità (showZeroDcmts)
1399
+ expandedNode.items = updateHiddenProperty(loadedItems);
1400
+ expandedNode.isLoaded = true;
1401
+ expandedNode.itemsCount = loadedItems.length;
1402
+ // IMPORTANTE: Aggiungi i nuovi nodi scoperti al contatore totale
1403
+ // Questo viene fatto SOLO se non siamo all'ultimo livello
1404
+ // (perché i nodi dell'ultimo livello non verranno espansi)
1405
+ // targetLevel = 0 significa illimitato, quindi aggiungi sempre
1406
+ if (targetLevel === 0 || currentLevel + 1 < targetLevel) {
1407
+ const newExpandableCount = countNodesAtLevel(loadedItems);
1408
+ totalNodes += newExpandableCount;
1409
+ }
1410
+ }
1411
+ catch (error) {
1412
+ console.error('Errore nel caricamento dei figli del nodo:', error);
1413
+ }
1414
+ }
1415
+ else if (actualHasItems && (targetLevel === 0 || currentLevel + 1 < targetLevel)) {
1416
+ // ═══════════════════════════════════════════════════════════════
1417
+ // CASO B: I figli esistono già in memoria (non ricaricati via API)
1418
+ // Aggiungiamo comunque il loro conteggio a totalNodes
1419
+ // Usiamo actualHasItems invece di hasLoadedItems per gestire anche forceReload
1420
+ // ═══════════════════════════════════════════════════════════════
1421
+ const childCount = countNodesAtLevel(node.items);
1422
+ totalNodes += childCount;
1423
+ }
1424
+ // Aggiorna il progresso DOPO aver processato questo nodo
1425
+ processedNodes++;
1426
+ // Calcola percentuale e aggiorna solo se è più alta di prima
1427
+ // (evita che la barra di progresso torni indietro)
1428
+ const currentProgress = totalNodes > 0 ? Math.floor((processedNodes / totalNodes) * 100) : 0;
1429
+ if (currentProgress > maxReachedProgress) {
1430
+ maxReachedProgress = currentProgress;
1431
+ setExpansionWaitPanelValue(maxReachedProgress);
1432
+ }
1433
+ setExpansionWaitPanelText(SDKUI_Localizator.ExpansionProgress.replaceParams(processedNodes.toString(), totalNodes.toString()));
1434
+ // ═══════════════════════════════════════════════════════════════════
1435
+ // PASSO 3: CHIAMATA RICORSIVA SUI FIGLI
1436
+ // Questo è il punto chiave: i nuovi nodi appena caricati vengono
1437
+ // passati a expandToLevel con currentLevel + 1, quindi anche loro
1438
+ // verranno espansi (se non abbiamo raggiunto il livello target)
1439
+ // ═══════════════════════════════════════════════════════════════════
1440
+ if (expandedNode.items && Array.isArray(expandedNode.items) && expandedNode.items.length > 0) {
1441
+ expandedNode.items = await expandToLevel(expandedNode.items, currentLevel + 1);
1442
+ }
1443
+ }
1444
+ result.push(expandedNode);
1445
+ }
1446
+ return result;
1447
+ };
1448
+ try {
1449
+ // Avvia l'espansione dal livello 0 (root)
1450
+ const expandedTree = await expandToLevel(workingTreeData, 0);
1451
+ setTreeData(expandedTree);
1452
+ // Espandi anche gli item statici (se presenti)
1453
+ const expandedStatic = await expandToLevel(workingStaticData, 0);
1454
+ setStaticItemsState(expandedStatic);
1455
+ setIsAllCollapsed(false);
1456
+ userInteractedWithStaticItemsRef.current = true;
1457
+ }
1458
+ finally {
1459
+ // Cleanup: nascondi spinner e pannello di attesa
1460
+ TMSpinner.hide();
1461
+ setShowExpansionWaitPanel(false);
1462
+ setExpansionAbortController(undefined);
1463
+ }
1464
+ }, [expandLevel, treeData, staticItemsState, isForMaster, invertMasterNavigation, getDetailDcmtsAsync, getMasterDcmtsAsync, updateHiddenProperty]);
1193
1465
  /**
1194
1466
  * Apply defaultExpandAll once on initial tree load.
1195
1467
  */
@@ -1215,37 +1487,70 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
1215
1487
  setStaticItemsState(staticItems); // Preserve static items state (expanded/collapsed)
1216
1488
  // Mark that user has interacted with the tree (expanded/collapsed nodes)
1217
1489
  userInteractedWithStaticItemsRef.current = true;
1490
+ // Reset collapsed state when user manually expands a node
1491
+ setIsAllCollapsed(false);
1218
1492
  }, []);
1219
1493
  if (showWaitPanel) {
1220
- return _jsx("div", { style: { padding: '20px', textAlign: 'center' }, children: _jsx(TMWaitPanel, { title: 'Caricamento documenti dettaglio', showPrimary: true, textPrimary: waitPanelTextPrimary, valuePrimary: waitPanelValuePrimary, maxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); } }) });
1494
+ 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); } }) });
1221
1495
  }
1222
1496
  if (mergedTreeData.length === 0) {
1497
+ // Se NON isForMaster e tutti i GetMetadataAsync sono falliti
1498
+ if (!isForMaster && metadataErrorCount === inputDcmts.length) {
1499
+ return _jsx(TMToppyMessage, { message: SDKUI_Localizator.DocumentsNotAvailableOrNoCorrelations });
1500
+ }
1223
1501
  // If parent handles no-relations via callback, render nothing to avoid UI flash
1224
1502
  if (onNoRelationsFound)
1225
1503
  return null;
1226
- return _jsx("div", { style: { padding: '20px', textAlign: 'center', color: '#666' }, children: "Nessuna relazione disponibile." });
1504
+ return _jsx("div", { style: { padding: '20px', textAlign: 'center', color: '#666' }, children: SDKUI_Localizator.NoRelationsAvailable });
1505
+ }
1506
+ // Se isForMaster e non ci sono master documents disponibili
1507
+ if (isForMaster && totalMasterDocuments === 0) {
1508
+ return _jsx(TMToppyMessage, { message: SDKUI_Localizator.NoMasterDocumentsAvailable });
1227
1509
  }
1228
- return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0, width: '100%' }, children: [showExpandAllButton && (_jsx(StyledToolbarForm, { style: { flexShrink: 0 }, children: _jsxs("button", { type: "button", onClick: handleToggleExpandAll, title: allExpanded ? SDKUI_Localizator.CollapseAll : SDKUI_Localizator.ExpandAll, style: {
1229
- display: 'inline-flex',
1230
- alignItems: 'center',
1231
- gap: '4px',
1232
- padding: '4px 8px',
1233
- fontSize: '0.8rem',
1234
- color: TMColors.primary,
1235
- background: 'transparent',
1236
- border: `1px solid ${TMColors.border_normal}`,
1237
- borderRadius: '4px',
1238
- cursor: 'pointer',
1239
- whiteSpace: 'nowrap',
1240
- outline: 'none'
1241
- }, children: [_jsx("span", { style: { display: 'flex', alignItems: 'center' }, children: allExpanded ? _jsx(IconChevronRight, { fontSize: 14 }) : _jsx(IconChevronDown, { fontSize: 14 }) }), _jsx("span", { children: allExpanded ? SDKUI_Localizator.CollapseAll : SDKUI_Localizator.ExpandAll })] }) })), _jsx("div", { style: { flex: 1, minHeight: 0, overflow: 'auto' }, children: _jsx(TMTreeView, { dataSource: mergedTreeData, itemRender: finalItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: handleDataChanged, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, itemsPerPage: 100, onSelectionChanged: handleSelectedItemsChanged, onItemContextMenu: onItemContextMenu, shouldDelayFocusOnEvent: (node, e) => {
1510
+ 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
1511
+ ? `${SDKUI_Localizator.ExpandAllLevels} (${SDKUI_Localizator.CtrlClickToReloadAll})`
1512
+ : `${SDKUI_Localizator.ExpandToLevel.replaceParams(expandLevel.toString())} (${SDKUI_Localizator.CtrlClickToReloadAll})`, children: _jsxs("button", { type: "button", onClick: (e) => handleExpandToLevel(e.ctrlKey), style: {
1513
+ display: 'inline-flex',
1514
+ alignItems: 'center',
1515
+ justifyContent: 'center',
1516
+ gap: '5px',
1517
+ height: '28px',
1518
+ padding: '0 10px',
1519
+ fontSize: '0.8rem',
1520
+ fontWeight: 500,
1521
+ color: 'white',
1522
+ background: TMColors.primary,
1523
+ border: 'none',
1524
+ borderRadius: '4px',
1525
+ cursor: 'pointer',
1526
+ whiteSpace: 'nowrap',
1527
+ outline: 'none',
1528
+ transition: 'background 0.2s'
1529
+ }, children: [_jsx(IconChevronDown, { fontSize: 14 }), _jsx("span", { children: expandLevel === 0 ? SDKUI_Localizator.ExpandAllLevels : SDKUI_Localizator.ExpandLevels.replaceParams(expandLevel.toString()) })] }) }), _jsx(TMTooltip, { content: SDKUI_Localizator.CollapseTree, children: _jsxs("button", { type: "button", onClick: handleCollapseTree, disabled: isAllCollapsed, style: {
1530
+ display: 'inline-flex',
1531
+ alignItems: 'center',
1532
+ justifyContent: 'center',
1533
+ gap: '5px',
1534
+ height: '28px',
1535
+ padding: '0 10px',
1536
+ fontSize: '0.8rem',
1537
+ fontWeight: 500,
1538
+ color: isAllCollapsed ? '#999' : 'white',
1539
+ background: isAllCollapsed ? '#e0e0e0' : TMColors.secondary || '#6c757d',
1540
+ border: 'none',
1541
+ borderRadius: '4px',
1542
+ cursor: isAllCollapsed ? 'not-allowed' : 'pointer',
1543
+ whiteSpace: 'nowrap',
1544
+ outline: 'none',
1545
+ transition: 'background 0.2s'
1546
+ }, children: [_jsx(IconChevronRight, { fontSize: 14 }), _jsx("span", { children: SDKUI_Localizator.CollapseAll })] }) })] })), _jsx("div", { style: { flex: 1, minHeight: 0, overflow: 'auto' }, children: _jsx(TMTreeView, { dataSource: mergedTreeData, itemRender: finalItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: handleDataChanged, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, itemsPerPage: 100, onSelectionChanged: handleSelectedItemsChanged, onItemContextMenu: showExpansionWaitPanel ? undefined : onItemContextMenu, enableVirtualization: true, shouldDelayFocusOnEvent: (node, e) => {
1242
1547
  // Ritarda il focus quando si clicca sull'icona del documento
1243
1548
  // per permettere al doppio click di funzionare
1244
1549
  const target = e.target;
1245
1550
  return !!target.closest('.tm-dcmt-icon');
1246
- } }) }), showExpansionWaitPanel && (_jsx(TMWaitPanel, { title: isForMaster ? 'Caricamento documenti master' : 'Caricamento documenti dettaglio', showPrimary: true, textPrimary: expansionWaitPanelText, valuePrimary: expansionWaitPanelValue, maxValuePrimary: expansionWaitPanelMaxValue, isCancelable: true, abortController: expansionAbortController, onAbortClick: (abortController) => {
1551
+ } }) }), showExpansionWaitPanel && (_jsx(TMWaitPanel, { title: isForMaster ? SDKUI_Localizator.LoadingMasterDocuments : SDKUI_Localizator.LoadingDetailDocuments, showPrimary: true, textPrimary: expansionWaitPanelText, valuePrimary: expansionWaitPanelValue, maxValuePrimary: expansionWaitPanelMaxValue, isCancelable: true, abortController: expansionAbortController, onAbortClick: () => {
1247
1552
  setTimeout(() => {
1248
- abortController?.abort();
1553
+ expansionAbortController?.abort();
1249
1554
  }, 100);
1250
1555
  } }))] }));
1251
1556
  };