@topconsultnpm/sdkui-react 6.21.0-dev1.2 → 6.21.0-dev1.21

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 (35) hide show
  1. package/lib/components/base/TMAreaManager.js +18 -3
  2. package/lib/components/base/TMPanel.js +1 -0
  3. package/lib/components/base/TMTreeView.d.ts +2 -1
  4. package/lib/components/base/TMTreeView.js +8 -3
  5. package/lib/components/choosers/TMUserChooser.js +3 -1
  6. package/lib/components/editors/TMFormulaEditor.js +3 -3
  7. package/lib/components/features/archive/TMArchive.js +1 -1
  8. package/lib/components/features/documents/TMDcmtForm.js +12 -8
  9. package/lib/components/features/documents/TMFileUploader.d.ts +1 -1
  10. package/lib/components/features/documents/TMFileUploader.js +3 -3
  11. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +27 -2
  12. package/lib/components/features/documents/TMMasterDetailDcmts.js +215 -20
  13. package/lib/components/features/documents/TMRelationViewer.d.ts +12 -1
  14. package/lib/components/features/documents/TMRelationViewer.js +49 -10
  15. package/lib/components/features/search/TMSavedQuerySelector.js +1 -1
  16. package/lib/components/features/search/TMSearch.d.ts +1 -0
  17. package/lib/components/features/search/TMSearch.js +2 -2
  18. package/lib/components/features/search/TMSearchResult.d.ts +1 -0
  19. package/lib/components/features/search/TMSearchResult.js +18 -4
  20. package/lib/components/features/search/TMViewHistoryDcmt.js +6 -0
  21. package/lib/components/features/workflow/diagram/DiagramItemForm.js +5 -1
  22. package/lib/components/features/workflow/diagram/WFDiagram.js +7 -1
  23. package/lib/components/features/workflow/diagram/xmlParser.js +13 -14
  24. package/lib/components/pages/TMPage.js +4 -2
  25. package/lib/components/query/TMQueryEditor.js +20 -1
  26. package/lib/helper/SDKUI_Globals.d.ts +2 -0
  27. package/lib/helper/checkinCheckoutManager.d.ts +1 -1
  28. package/lib/helper/checkinCheckoutManager.js +18 -4
  29. package/lib/hooks/useDcmtOperations.d.ts +1 -0
  30. package/lib/hooks/useDcmtOperations.js +75 -4
  31. package/lib/hooks/useDocumentOperations.d.ts +1 -0
  32. package/lib/hooks/useDocumentOperations.js +46 -12
  33. package/lib/hooks/useInputDialog.d.ts +2 -0
  34. package/lib/hooks/useInputDialog.js +34 -0
  35. package/package.json +55 -55
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useMemo, useState } from 'react';
3
- import { DcmtTypeListCacheService, SDK_Localizator } from '@topconsultnpm/sdk-ts';
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
+ import { DcmtTypeListCacheService, LayoutModes, SDK_Globals, SDK_Localizator } from '@topconsultnpm/sdk-ts';
4
4
  import TMRelationViewer from './TMRelationViewer';
5
5
  import TMContextMenu from '../../NewComponents/ContextMenu/TMContextMenu';
6
- import { IconMultipleSelection, IconCheckFile, IconDetailDcmts, SDKUI_Localizator, IconMenuVertical, IconDataList, IconPreview, IconSearchCheck, IconBoard, IconDcmtTypeSys, IconShow, getMoreInfoTasksForDocument } from '../../../helper';
6
+ import { IconMultipleSelection, IconCheckFile, IconDetailDcmts, SDKUI_Localizator, IconMenuVertical, IconDataList, IconPreview, IconSearchCheck, IconBoard, IconDcmtTypeSys, IconShow, getMoreInfoTasksForDocument, isApprovalWorkflowView, searchResultToMetadataValues, IconRefresh } from '../../../helper';
7
7
  import { FormModes, SearchResultContext } from '../../../ts';
8
8
  import { TMColors } from '../../../utils/theme';
9
9
  import ShowAlert from '../../base/TMAlert';
@@ -14,8 +14,10 @@ import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/p
14
14
  import TMSearchResult from '../search/TMSearchResult';
15
15
  import TMDcmtForm from './TMDcmtForm';
16
16
  import { TMNothingToShow } from './TMDcmtPreview';
17
- import { Spinner } from '../..';
18
- const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, appendMasterDcmts, onTaskCreateRequest }) => {
17
+ import { Spinner, TMButton } from '../..';
18
+ import { useDocumentOperations } from '../../../hooks/useDocumentOperations';
19
+ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, appendMasterDcmts, onTaskCreateRequest, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, datagridUtility, dcmtUtility }) => {
20
+ const floatingBarContainerRef = useRef(null);
19
21
  const [focusedItem, setFocusedItem] = useState();
20
22
  const [selectedItems, setSelectedItems] = useState([]);
21
23
  const [showZeroDcmts, setShowZeroDcmts] = useState(false);
@@ -23,6 +25,174 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
23
25
  const [dtdMaster, setDtdMaster] = useState();
24
26
  const [noRelationsOnFirstLoad, setNoRelationsOnFirstLoad] = useState(false);
25
27
  const [isCheckingFirstLoad, setIsCheckingFirstLoad] = useState(true);
28
+ const [contextMenuVisible, setContextMenuVisible] = useState(false);
29
+ const [contextMenuPosition, setContextMenuPosition] = useState({ x: 0, y: 0 });
30
+ const [dtdFocused, setDtdFocused] = useState();
31
+ const [refreshKey, setRefreshKey] = useState(0);
32
+ // Separate refresh key for TMFormOrResultWrapper only (doesn't affect tmTreeView)
33
+ const [refreshKeyFormOrResult, setRefreshKeyFormOrResult] = useState(0);
34
+ /** State for transformed focusedItem metadata values (similar to formData in TMDcmtForm) */
35
+ const [focusedItemFormData, setFocusedItemFormData] = useState([]);
36
+ // Trigger operationItems refresh (after file substitution, etc.)
37
+ const [refreshOperationsTrigger, setRefreshOperationsTrigger] = useState(0);
38
+ // Increments trigger counter to force operationItems to re-calculate
39
+ const onRefreshOperationsDatagrid = useCallback(async () => {
40
+ setRefreshOperationsTrigger(prev => prev + 1);
41
+ }, []);
42
+ // Refresh ALL panels (tree view + search results) with fade-out -> update -> fade-in transition
43
+ const onRefreshAllPanels = async () => {
44
+ await dcmtUtility?.onRefreshPreviewForm?.(); // Refresh preview form data
45
+ setFocusedItem(undefined); // Clear focused item to avoid stale references
46
+ setTimeout(async () => {
47
+ setRefreshKey(prev => prev + 1); // Force re-render of tmTreeView
48
+ setRefreshKeyFormOrResult(prev => prev + 1); // Force re-render of TMFormOrResultWrapper
49
+ await onRefreshOperationsDatagrid(); // Refresh operation items
50
+ }, 200); // Wait for fade-out animation
51
+ };
52
+ useEffect(() => {
53
+ const fetchFocusedItemMetadata = async () => {
54
+ if (!focusedItem?.tid || !focusedItem?.did) {
55
+ setFocusedItemFormData([]);
56
+ return;
57
+ }
58
+ try {
59
+ const tid = focusedItem?.tid;
60
+ const did = focusedItem?.did;
61
+ const metadata = await SDK_Globals.tmSession?.NewSearchEngine().GetMetadataAsync(tid, did, true);
62
+ // Transform metadata to MetadataValueDescriptorEx[] (similar to setMetadataList in TMDcmtForm)
63
+ if (metadata) {
64
+ const dtdResult = metadata.dtdResult;
65
+ const rows = dtdResult?.rows ? dtdResult.rows[0] : [];
66
+ const mids = metadata.selectMIDs;
67
+ // Get DTD with metadata descriptors
68
+ const dtdWithMetadata = await DcmtTypeListCacheService.GetWithNotGrantedAsync(tid, did, metadata);
69
+ const mdList = dtdWithMetadata?.metadata ?? [];
70
+ const metadataList = searchResultToMetadataValues(tid, dtdResult, rows, mids, mdList, LayoutModes.Update);
71
+ setFocusedItemFormData(structuredClone(metadataList));
72
+ }
73
+ }
74
+ catch (error) {
75
+ console.error('Error fetching focusedItem metadata:', error);
76
+ setFocusedItemFormData([]);
77
+ }
78
+ };
79
+ fetchFocusedItemMetadata();
80
+ }, [focusedItem?.tid, focusedItem?.did, refreshOperationsTrigger]);
81
+ // Load dtdFocused when focusedItem changes
82
+ useEffect(() => {
83
+ const loadDtdFocused = async () => {
84
+ if (!focusedItem?.tid) {
85
+ setDtdFocused(undefined);
86
+ return;
87
+ }
88
+ const dtd = await DcmtTypeListCacheService.GetAsync(focusedItem.tid);
89
+ setDtdFocused(dtd);
90
+ };
91
+ loadDtdFocused();
92
+ }, [focusedItem?.tid]);
93
+ const openTaskFormHandler = (onTaskCreated) => {
94
+ if (selectedItems.length > 1)
95
+ return;
96
+ const item = selectedItems.length === 1 ? selectedItems[0] : focusedItem;
97
+ if (item && item.tid && item.did) {
98
+ const createTaskFromDocumentOrWorkItem = async () => {
99
+ try {
100
+ const dtd = await DcmtTypeListCacheService.GetWithNotGrantedAsync(item.tid, item?.did);
101
+ if (dtd) {
102
+ const isWorkItem = isApprovalWorkflowView(dtd);
103
+ if (item.tid === undefined || item.did === undefined) {
104
+ console.error("TID or DID is undefined for the selected item.");
105
+ return;
106
+ }
107
+ const name = `${dtd.name ?? '-'} (DID: ${item.did})`;
108
+ onTaskCreateRequest?.(isWorkItem
109
+ ? { workItem: { tid: item.tid, did: item.did, name } }
110
+ : { document: { tid: item.tid, did: item.did, name } }, onTaskCreated);
111
+ }
112
+ }
113
+ catch (error) {
114
+ console.error("Error fetching data:", error);
115
+ }
116
+ };
117
+ createTaskFromDocumentOrWorkItem();
118
+ }
119
+ };
120
+ const { operationItems, renderFloatingBar, renderDcmtOperations, features } = useDocumentOperations({
121
+ context: SearchResultContext.MASTER_DETAIL,
122
+ documentData: {
123
+ dtd: dtdFocused,
124
+ selectedItems: selectedItems ? selectedItems.map(item => ({ TID: item.tid, DID: item.did, FILEEXT: item.fileExt })) : [],
125
+ focusedItem: focusedItem ? { TID: focusedItem.tid, DID: focusedItem.did, FILEEXT: focusedItem.fileExt } : undefined,
126
+ currentSearchResults: [],
127
+ currentMetadataValues: [],
128
+ allUsers: [],
129
+ // searchResult: selectedSearchResult,
130
+ datagridUtility: {
131
+ visibleItems: [],
132
+ onRefreshSearchAsyncDatagrid: onRefreshAllPanels,
133
+ onRefreshDataRowsAsync: onRefreshAllPanels,
134
+ refreshFocusedDataRowAsync: onRefreshAllPanels,
135
+ onRefreshBlogDatagrid: onRefreshAllPanels,
136
+ onRefreshPreviewDatagrid: onRefreshAllPanels,
137
+ refreshOperationsTrigger,
138
+ onRefreshOperationsDatagrid,
139
+ },
140
+ dcmtUtility: {
141
+ approvalVID: dcmtUtility?.approvalVID,
142
+ dcmtDataRowForCicoStatus: focusedItemFormData, // Passa i metadata trasformati del focusedItem per le operazioni di CICO
143
+ selectedDcmtSearchResultRelations: dcmtUtility?.selectedDcmtSearchResultRelations,
144
+ dcmtTIDHasDetailRelations: dcmtUtility?.dcmtTIDHasDetailRelations,
145
+ dcmtTIDHasMasterRelations: dcmtUtility?.dcmtTIDHasMasterRelations,
146
+ updateCurrentDcmt: onRefreshAllPanels,
147
+ onCloseDcmtForm: dcmtUtility?.onCloseDcmtForm,
148
+ onRefreshBlogForm: dcmtUtility?.onRefreshBlogForm,
149
+ onRefreshPreviewForm: onRefreshAllPanels,
150
+ taskFormDialogComponent: dcmtUtility?.taskFormDialogComponent,
151
+ s4TViewerDialogComponent: dcmtUtility?.s4TViewerDialogComponent
152
+ },
153
+ },
154
+ uiConfig: {
155
+ floatingBarContainerRef,
156
+ openS4TViewer,
157
+ showDcmtFormSidebar: true,
158
+ openDcmtFormAsModal: true,
159
+ allowFloatingBar: false,
160
+ enablePinIcons: false,
161
+ allowRelations: true,
162
+ inputDcmtFormLayoutMode: LayoutModes.Update,
163
+ },
164
+ tasks: {
165
+ allTasks: allTasks,
166
+ getAllTasks: getAllTasks,
167
+ deleteTaskByIdsCallback: deleteTaskByIdsCallback,
168
+ addTaskCallback: addTaskCallback,
169
+ editTaskCallback: editTaskCallback
170
+ },
171
+ callbacks: {
172
+ // Refresh operations (data consistency)
173
+ /* onSavedAsyncCallback, */
174
+ // Workflow operations
175
+ /* onWFOperationCompleted, */
176
+ // Navigation
177
+ /* canNavigateHandler,
178
+ onNavigateHandler, */
179
+ handleNavigateToWGs,
180
+ handleNavigateToDossiers,
181
+ /* onReferenceClick, */
182
+ // Document forms/operations
183
+ /* openAddDocumentForm,
184
+ openCommentFormCallback,
185
+ onFileOpened,
186
+ passToArchiveCallback,
187
+ openWGsCopyMoveForm, */
188
+ onOpenS4TViewerRequest,
189
+ onOpenPdfEditorRequest,
190
+ // Task related
191
+ onTaskCreateRequest,
192
+ openTaskFormHandler,
193
+ onRefreshAfterAddDcmtToFavs,
194
+ },
195
+ });
26
196
  // Load dtdMaster when inputDcmts changes
27
197
  useEffect(() => {
28
198
  const loadDtdMaster = async () => {
@@ -53,6 +223,12 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
53
223
  setNoRelationsOnFirstLoad(true);
54
224
  }
55
225
  }, [isCheckingFirstLoad]);
226
+ const onItemContextMenu = useCallback((item, e) => {
227
+ if (!item.isDcmt)
228
+ return; // Show context menu only for document items
229
+ setContextMenuPosition({ x: e.clientX, y: e.clientY });
230
+ setContextMenuVisible(true);
231
+ }, []);
56
232
  // Show warning alert and navigate back when no relations found on first load
57
233
  useEffect(() => {
58
234
  if (noRelationsOnFirstLoad) {
@@ -90,17 +266,26 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
90
266
  }
91
267
  }
92
268
  ];
93
- const toolbar = _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [allowMultipleSelection && _jsx("p", { style: { color: TMColors.colorHeader, textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${selectedItems.filter(item => item.isDcmt).length} selezionati` }), allowNavigation && canPrev != undefined && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', iconColor: 'white', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), allowNavigation && canNext != undefined && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', iconColor: 'white', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(TMContextMenu, { items: commandsMenuItems, trigger: 'left', children: _jsx(IconMenuVertical, { color: 'white', cursor: 'pointer' }) })] });
269
+ const toolbar = _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [allowMultipleSelection && _jsx("p", { style: { color: TMColors.colorHeader, textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${selectedItems.filter(item => item.isDcmt).length} selezionati` }), allowNavigation && canPrev != undefined && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', iconColor: 'white', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), allowNavigation && canNext != undefined && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', iconColor: 'white', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: onRefreshAllPanels }), _jsx(TMContextMenu, { items: commandsMenuItems, trigger: 'left', children: _jsx(IconMenuVertical, { color: 'white', cursor: 'pointer' }) })] });
94
270
  const getTitle = () => isForMaster ? `${SDKUI_Localizator.DcmtsMaster} - ${dtdMaster?.nameLoc}` : SDKUI_Localizator.DcmtsDetail;
95
271
  const isMobile = deviceType === DeviceType.MOBILE;
96
272
  const tmTreeView = useMemo(() => _jsx(_Fragment, { children: !inputDcmts || inputDcmts.length === 0
97
273
  ?
98
274
  _jsx(TMNothingToShow, { text: getTitle(), secondText: SDKUI_Localizator.NoDataToDisplay, icon: isForMaster ? _jsx(IconDetailDcmts, { fontSize: 96, transform: 'scale(-1, 1)' }) : _jsx(IconDetailDcmts, { fontSize: 96 }) })
99
275
  :
100
- _jsx(TMRelationViewerWrapper, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, showZeroDcmts: showZeroDcmts,
101
- // customItemRender={customItemRender}
102
- allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound]);
103
- const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { deviceType: deviceType, focusedItem: focusedItem, onTaskCreateRequest: onTaskCreateRequest, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers]);
276
+ _jsxs("div", { ref: floatingBarContainerRef, style: { width: "100%", height: "100%" }, onContextMenu: (e) => {
277
+ // Mostra context menu anche sullo spazio bianco (quando non si clicca su un item)
278
+ e.preventDefault();
279
+ setContextMenuPosition({ x: e.clientX, y: e.clientY });
280
+ setContextMenuVisible(true);
281
+ }, children: [_jsx(TMRelationViewerWrapper, { refreshKey: refreshKey, inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, showZeroDcmts: showZeroDcmts,
282
+ // customItemRender={customItemRender}
283
+ allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound, onItemContextMenu: onItemContextMenu, focusedItemFormData: focusedItemFormData }), _jsx(TMContextMenu, { items: operationItems, externalControl: {
284
+ visible: contextMenuVisible,
285
+ position: contextMenuPosition,
286
+ onClose: () => setContextMenuVisible(false)
287
+ } })] }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound, onItemContextMenu, contextMenuVisible, contextMenuPosition, refreshKey, focusedItemFormData]);
288
+ const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { refreshKey: refreshKeyFormOrResult, deviceType: deviceType, focusedItem: focusedItem, onTaskCreateRequest: onTaskCreateRequest, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onRefreshSearchResults: onRefreshAllPanels }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshAfterAddDcmtToFavs, refreshKeyFormOrResult]);
104
289
  const initialPanelDimensions = {
105
290
  'tmTreeView': { width: '50%', height: '100%' },
106
291
  'tmFormOrResult': { width: '50%', height: '100%' },
@@ -177,7 +362,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
177
362
  toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
178
363
  }
179
364
  ], [tmTreeView, tmFormOrResult, focusedItem?.isDcmt, dtdMaster]);
180
- return (_jsxs("div", { style: { width: '100%', height: '100%', position: 'relative' }, children: [isCheckingFirstLoad && (_jsx(Spinner, { description: SDKUI_Localizator.Loading, flat: true })), _jsx("div", { style: isCheckingFirstLoad ? { position: 'absolute', width: 0, height: 0, overflow: 'hidden', opacity: 0, pointerEvents: 'none' } : { width: '100%', height: '100%' }, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) })] }));
365
+ return (_jsxs("div", { style: { width: '100%', height: '100%', position: 'relative' }, children: [isCheckingFirstLoad && (_jsx(Spinner, { description: SDKUI_Localizator.Loading, flat: true })), _jsxs("div", { style: isCheckingFirstLoad ? { position: 'absolute', width: 0, height: 0, overflow: 'hidden', opacity: 0, pointerEvents: 'none' } : { width: '100%', height: '100%' }, children: [_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }), renderDcmtOperations, renderFloatingBar] })] }));
181
366
  };
182
367
  export default TMMasterDetailDcmts;
183
368
  /**
@@ -186,7 +371,7 @@ export default TMMasterDetailDcmts;
186
371
  * - Panel visibility toggling
187
372
  * - Focus delay handling
188
373
  */
189
- const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound }) => {
374
+ const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound, onItemContextMenu, focusedItemFormData }) => {
190
375
  const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
191
376
  // Handle focused item changes with panel visibility management
192
377
  const handleFocusedItemChanged = useCallback((item) => {
@@ -205,15 +390,25 @@ const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndic
205
390
  setToolbarButtonVisibility('tmDcmtForm', false);
206
391
  }
207
392
  }, [onFocusedItemChanged, setPanelVisibilityById, setToolbarButtonVisibility]);
208
- return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, onNoRelationsFound: onNoRelationsFound }));
393
+ const onContextMenu = useCallback((item, e) => {
394
+ // Ferma la propagazione per evitare che l'evento arrivi al div contenitore
395
+ // (che ha il suo handler per il context menu sullo spazio bianco)
396
+ e.stopPropagation();
397
+ handleFocusedItemChanged(item);
398
+ // Il setTimeout è necessario per permettere a React di completare il re-render
399
+ // dopo il cambio di focus (handleFocusedItemChanged aggiorna stato e visibilità pannelli).
400
+ // Senza il delay, il context menu potrebbe mostrare opzioni basate sul vecchio stato.
401
+ setTimeout(() => {
402
+ onItemContextMenu?.(item, e);
403
+ }, 100);
404
+ }, [onItemContextMenu, handleFocusedItemChanged]);
405
+ return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, onNoRelationsFound: onNoRelationsFound, onItemContextMenu: onContextMenu, focusedItemFormData: focusedItemFormData }, refreshKey));
209
406
  };
210
- const TMFormOrResultWrapper = ({ deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
407
+ const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid, onRefreshSearchResults }) => {
211
408
  const { setPanelVisibilityById } = useTMPanelManagerContext();
212
409
  return (_jsx(_Fragment, { children: focusedItem?.isDcmt ?
213
- _jsx(TMDcmtForm, { groupId: 'tmFormOrResult', TID: focusedItem?.tid, DID: focusedItem.did, allowButtonsRefs: true, isClosable: deviceType !== DeviceType.MOBILE, allowNavigation: false, allowRelations: deviceType !== DeviceType.MOBILE, showDcmtFormSidebar: false, onClose: () => {
214
- setPanelVisibilityById('tmTreeView', true);
215
- }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, focusedItem?.tid, focusedItem?.did) }) :
216
- _jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => {
217
- setPanelVisibilityById('tmTreeView', true);
218
- }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }) }));
410
+ _jsx(TMDcmtForm, { groupId: 'tmFormOrResult', TID: focusedItem?.tid, DID: focusedItem.did, allowButtonsRefs: true, isClosable: deviceType !== DeviceType.MOBILE, allowNavigation: false, allowRelations: deviceType !== DeviceType.MOBILE, showDcmtFormSidebar: false, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, focusedItem?.tid, focusedItem?.did), openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, datagridUtility: {
411
+ onRefreshSearchAsyncDatagrid,
412
+ } }, refreshKey) :
413
+ _jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, enablePinIcons: false, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, showBackButton: false, onRefreshSearchAsyncDatagrid: onRefreshSearchResults }, refreshKey) }));
219
414
  };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { DcmtTypeDescriptor, SearchResultDescriptor, DataColumnDescriptor } from "@topconsultnpm/sdk-ts";
3
- import { DcmtInfo } from '../../../ts';
3
+ import { DcmtInfo, MetadataValueDescriptorEx } from '../../../ts';
4
4
  import { ITMTreeItem } from '../../base/TMTreeView';
5
5
  /**
6
6
  * Tree item structure for relations
@@ -22,6 +22,7 @@ export interface RelationTreeItem extends ITMTreeItem {
22
22
  values?: any;
23
23
  searchResult?: SearchResultDescriptor[];
24
24
  itemsCount?: number;
25
+ fileExt?: string;
25
26
  }
26
27
  /**
27
28
  * Props for TMRelationViewer component
@@ -98,6 +99,16 @@ export interface TMRelationViewerProps {
98
99
  * Useful to notify parent component that there are no correlated documents to display.
99
100
  */
100
101
  onNoRelationsFound?: () => void;
102
+ /**
103
+ * Callback invoked when user right-clicks on a tree item.
104
+ * Use to show a context menu.
105
+ */
106
+ onItemContextMenu?: (item: RelationTreeItem, e: React.MouseEvent) => void;
107
+ /**
108
+ * Metadata values for the focused item
109
+ * (used in master-detail context)
110
+ */
111
+ focusedItemFormData?: MetadataValueDescriptorEx[];
101
112
  }
102
113
  /**
103
114
  * Check if document type has detail relations
@@ -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, MetadataFormats, SystemMIDs, MetadataDataDomains, RelationCacheService, RelationTypes } from "@topconsultnpm/sdk-ts";
4
- import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo } from '../../../helper';
3
+ import { DcmtTypeListCacheService, SDK_Globals, DataColumnTypes, MetadataFormats, SystemMIDs, MetadataDataDomains, RelationCacheService, RelationTypes, UserListCacheService } from "@topconsultnpm/sdk-ts";
4
+ import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus } from '../../../helper';
5
5
  import { TMColors } from '../../../utils/theme';
6
6
  import { StyledDivHorizontal, StyledBadge } from '../../base/Styled';
7
7
  import TMTreeView from '../../base/TMTreeView';
@@ -136,7 +136,7 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata) =>
136
136
  }
137
137
  return output;
138
138
  };
139
- const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndicator = true, allowShowZeroDcmts = true, initialShowZeroDcmts = false, allowedTIDs, allowMultipleSelection = false, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onDocumentDoubleClick, customItemRender, customDocumentStyle, customMainContainerContent, customDocumentContent, showMetadataNames = false, maxDepthLevel = 2, invertMasterNavigation = true, additionalStaticItems, showMainDocument = true, labelMainContainer, onNoRelationsFound, }) => {
139
+ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndicator = true, allowShowZeroDcmts = true, initialShowZeroDcmts = false, allowedTIDs, allowMultipleSelection = false, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onDocumentDoubleClick, customItemRender, customDocumentStyle, customMainContainerContent, customDocumentContent, showMetadataNames = false, maxDepthLevel = 2, invertMasterNavigation = true, additionalStaticItems, showMainDocument = true, labelMainContainer, onNoRelationsFound, onItemContextMenu, focusedItemFormData = [] }) => {
140
140
  // State
141
141
  const [dcmtTypes, setDcmtTypes] = useState([]);
142
142
  const [treeData, setTreeData] = useState([]);
@@ -160,6 +160,16 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
160
160
  const userInteractedWithStaticItemsRef = React.useRef(false);
161
161
  // Ref to track the last inputKey for which we set the focused item
162
162
  const lastFocusedInputRef = React.useRef('');
163
+ // State for all users (used for checkout status display)
164
+ const [allUsers, setAllUsers] = useState([]);
165
+ // Load all users for checkout status resolution
166
+ useEffect(() => {
167
+ const fetchAllUsers = async () => {
168
+ const users = await UserListCacheService.GetAllAsync();
169
+ setAllUsers(users ?? []);
170
+ };
171
+ fetchAllUsers();
172
+ }, []);
163
173
  /**
164
174
  * Generate a stable key from inputDcmts to detect real changes
165
175
  */
@@ -234,6 +244,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
234
244
  dcmtDetails.push({
235
245
  tid: tid,
236
246
  did: did,
247
+ dtd: dtd,
237
248
  isLogDel: isLogDel,
238
249
  key: `${tid}_${did}_${searchResult.relationID}_${mTID}_${mDID}_${rowGUID}`,
239
250
  isDcmt: true,
@@ -246,7 +257,8 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
246
257
  // Children will be loaded lazily by calculateItemsForNode when expanded
247
258
  expanded: false,
248
259
  hidden: false,
249
- name: row?.SYS_Abstract?.value || row?.SYS_SUBJECT?.value || `Documento ${did}`
260
+ name: row?.SYS_Abstract?.value || row?.SYS_SUBJECT?.value || `Documento ${did}`,
261
+ fileExt: row?.FILEEXT?.value,
250
262
  // Note: Recursive loading on expansion is handled by calculateItemsForNode
251
263
  });
252
264
  }
@@ -259,7 +271,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
259
271
  console.error('❌ Error loading detail documents:', error);
260
272
  }
261
273
  return items;
262
- }, [allowedTIDs]);
274
+ }, [allowedTIDs, focusedItemFormData, focusedItem?.dtd?.id]);
263
275
  /**
264
276
  * Recursively retrieve master documents
265
277
  */
@@ -318,6 +330,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
318
330
  dcmtMasters.push({
319
331
  tid: tid,
320
332
  did: did,
333
+ dtd: dtd,
321
334
  isLogDel: isLogDel,
322
335
  key: `${tid}_${did}_${searchResult.relationID}_${dTID}_${dDID}_${rowGUID}`,
323
336
  isDcmt: true,
@@ -375,7 +388,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
375
388
  isContainer: false,
376
389
  isDcmt: false,
377
390
  isInfoMessage: true,
378
- isExpandible: false
391
+ isExpandible: false,
379
392
  },
380
393
  ...filteredChildren
381
394
  ];
@@ -608,17 +621,20 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
608
621
  name: docRow?.SYS_Abstract?.value || docRow?.SYS_SUBJECT?.value || `Documento ${isForMaster ? 'Dettaglio' : 'Master'}`,
609
622
  tid: dcmt.TID,
610
623
  did: dcmt.DID,
624
+ dtd: dtd,
611
625
  isDcmt: true,
612
626
  isContainer: false,
613
627
  expanded: false,
614
628
  isZero: dcmt.DID === 0,
615
629
  isMaster: !isForMaster,
616
630
  isLoaded: true,
631
+ isLogDel: docRow?.ISLOGDEL?.value,
617
632
  hidden: false,
618
633
  values: docRow,
619
634
  searchResult: result ? [result] : [],
620
635
  items: relatedDocs,
621
- itemsCount: relatedDocs.length
636
+ itemsCount: relatedDocs.length,
637
+ fileExt: docRow?.FILEEXT?.value
622
638
  };
623
639
  // Check if a type container for this TID already exists in the tree
624
640
  const existingContainer = tree.find(c => c.tid === dcmt.TID && c.isContainer);
@@ -1078,8 +1094,31 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
1078
1094
  const metadataContent = customDocumentContent
1079
1095
  ? customDocumentContent(item, defaultMetadataContent || _jsx(_Fragment, {}))
1080
1096
  : defaultMetadataContent;
1081
- 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' })), metadataContent] }));
1082
- }, [onDocumentDoubleClick, showCurrentDcmtIndicator, inputDcmts, customMainContainerContent, customDocumentStyle, customDocumentContent, showMetadataNames, showMainDocument]);
1097
+ // Calculate checkout status for non-root documents
1098
+ let checkoutStatusIcon = null;
1099
+ if (item.values && item.dtd) {
1100
+ // Convert item.values to flat format expected by getDcmtCicoStatus
1101
+ const flatValues = {};
1102
+ if (item.values) {
1103
+ for (const key of Object.keys(item.values)) {
1104
+ const entry = item.values[key];
1105
+ if (entry?.md?.id && item.tid) {
1106
+ // Create TID_MID key format for metadata
1107
+ flatValues[`${item.tid}_${entry.md.id}`] = entry.value;
1108
+ }
1109
+ // Also add direct key for system properties
1110
+ flatValues[key] = entry?.value;
1111
+ }
1112
+ flatValues.TID = item.tid;
1113
+ flatValues.DID = item.did;
1114
+ }
1115
+ const { checkoutStatus } = getDcmtCicoStatus(flatValues, allUsers, item.dtd);
1116
+ if (checkoutStatus.isCheckedOut && checkoutStatus.icon) {
1117
+ checkoutStatusIcon = checkoutStatus.icon;
1118
+ }
1119
+ }
1120
+ 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] }));
1121
+ }, [onDocumentDoubleClick, showCurrentDcmtIndicator, inputDcmts, customMainContainerContent, customDocumentStyle, customDocumentContent, showMetadataNames, showMainDocument, focusedItemFormData, focusedItem?.dtd, allUsers]);
1083
1122
  /**
1084
1123
  * Wrapper renderer that handles custom rendering if provided
1085
1124
  */
@@ -1130,7 +1169,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
1130
1169
  return null;
1131
1170
  return _jsx("div", { style: { padding: '20px', textAlign: 'center', color: '#666' }, children: "Nessuna relazione disponibile." });
1132
1171
  }
1133
- return (_jsxs(_Fragment, { children: [_jsx(TMTreeView, { dataSource: mergedTreeData, itemRender: finalItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: handleDataChanged, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, itemsPerPage: 100, onSelectionChanged: handleSelectedItemsChanged }), 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) => {
1172
+ return (_jsxs(_Fragment, { 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 }), 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) => {
1134
1173
  setTimeout(() => {
1135
1174
  abortController?.abort();
1136
1175
  }, 100);
@@ -201,7 +201,7 @@ const TMSavedQuerySelector = React.memo(({ items, selectedId, allowShowSearch =
201
201
  alignItems: 'center',
202
202
  justifyContent: 'center',
203
203
  minWidth: 0
204
- }, children: [_jsx("p", { style: {
204
+ }, children: [_jsx("p", { title: sqd.name, style: {
205
205
  fontSize: '1rem',
206
206
  fontWeight: sqd.id === 1 ? 600 : 'normal',
207
207
  whiteSpace: 'nowrap',
@@ -27,6 +27,7 @@ interface ITMSearchProps {
27
27
  openS4TViewer?: boolean;
28
28
  onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: (() => Promise<void>)) => void;
29
29
  onOpenPdfEditorRequest?: ((dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: () => Promise<void>) => void);
30
+ openFileUploaderPdfEditor?: (fromDTD?: DcmtTypeDescriptor, file?: File | null, handleFile?: (file: File) => void) => void;
30
31
  showTodoDcmtForm?: boolean;
31
32
  showToppyDraggableHelpCenter?: boolean;
32
33
  toppyHelpCenterUsePortal?: boolean;
@@ -19,7 +19,7 @@ var TMSearchViews;
19
19
  TMSearchViews[TMSearchViews["Search"] = 0] = "Search";
20
20
  TMSearchViews[TMSearchViews["Result"] = 1] = "Result";
21
21
  })(TMSearchViews || (TMSearchViews = {}));
22
- const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, editPdfForm = false, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, showTodoDcmtForm, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel, onReferenceClick }) => {
22
+ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, editPdfForm = false, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, showTodoDcmtForm, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel, onReferenceClick }) => {
23
23
  const [allSQDs, setAllSQDs] = useState([]);
24
24
  const [filteredByTIDSQDs, setFilteredByTIDSQDs] = useState([]);
25
25
  const [currentSQD, setCurrentSQD] = useState();
@@ -258,7 +258,7 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
258
258
  toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
259
259
  }
260
260
  ], [tmTreeSelectorElement, showSearchResults, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
261
- return (_jsxs(_Fragment, { children: [showSearchResults ? _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 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsyncDatagrid: onRefreshSearchAsyncDatagrid, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, 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 })] }));
261
+ return (_jsxs(_Fragment, { children: [showSearchResults ? _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 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsyncDatagrid: onRefreshSearchAsyncDatagrid, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, 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 })] }));
262
262
  };
263
263
  export default TMSearch;
264
264
  const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
@@ -45,6 +45,7 @@ interface ITMSearchResultProps {
45
45
  }>, tid?: number) => void;
46
46
  onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: () => Promise<void>) => void;
47
47
  onOpenPdfEditorRequest?: (dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: () => Promise<void>) => void;
48
+ openFileUploaderPdfEditor?: (fromDTD?: DcmtTypeDescriptor, file?: File | null, handleFile?: (file: File) => void) => void;
48
49
  openCommentFormCallback?: (documents: Array<DcmtInfo>) => void;
49
50
  openAddDocumentForm?: () => void;
50
51
  allTasks?: Array<TaskDescriptor>;
@@ -56,7 +56,7 @@ groupId, searchResults = [], context = SearchResultContext.METADATA_SEARCH, titl
56
56
  // Boolean flags to enable/disable features
57
57
  isVisible = true, allowRelations = true, openDcmtFormAsModal = false, showSearchResultSidebar = true, showDcmtFormSidebar = true, showSelector = false, isClosable = false, allowFloatingBar = true, showToolbarHeader = true, showBackButton = true, disableAccordionIfSingleCategory = false, editPdfForm = false, openS4TViewer = false, showTodoDcmtForm = false, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, showNoDcmtFoundMessage = true, enablePinIcons = true,
58
58
  // Callbacks (optional)
59
- openInOffice, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsyncDatagrid, onSelectedTIDChanged, onWFOperationCompleted, onClose, onFileOpened, onTaskCreateRequest, openWGsCopyMoveForm, openCommentFormCallback, openAddDocumentForm, onOpenS4TViewerRequest, onOpenPdfEditorRequest, passToArchiveCallback, onReferenceClick,
59
+ openInOffice, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsyncDatagrid, onSelectedTIDChanged, onWFOperationCompleted, onClose, onFileOpened, onTaskCreateRequest, openWGsCopyMoveForm, openCommentFormCallback, openAddDocumentForm, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, passToArchiveCallback, onReferenceClick,
60
60
  // Tasks
61
61
  allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback,
62
62
  // Navigation
@@ -346,12 +346,13 @@ handleNavigateToWGs, handleNavigateToDossiers, }) => {
346
346
  openWGsCopyMoveForm,
347
347
  onOpenS4TViewerRequest,
348
348
  onOpenPdfEditorRequest,
349
+ openFileUploaderPdfEditor,
349
350
  // Task related
350
351
  onTaskCreateRequest,
351
352
  openTaskFormHandler,
352
353
  },
353
354
  });
354
- const { isOpenDcmtForm, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid, showExportForm, isOpenBatchUpdate, isModifiedBatchUpdate, updateBatchUpdateForm, handleSignApprove, checkoutInfo: { showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, }, dcmtOperations: { abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, }, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
355
+ const { isOpenDcmtForm, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid, showExportForm, isOpenBatchUpdate, isModifiedBatchUpdate, updateBatchUpdateForm, handleSignApprove, checkoutInfo: { showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, }, dcmtOperations: { abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, FileSourceDialog, }, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
355
356
  const deviceType = useDeviceType();
356
357
  const isMobile = deviceType === DeviceType.MOBILE;
357
358
  const selectedDocs = getSelectedDcmtsOrFocused(selectedItems, focusedItem);
@@ -657,6 +658,7 @@ handleNavigateToWGs, handleNavigateToDossiers, }) => {
657
658
  }
658
659
  return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden', width: '100%' }, children: [_jsx("div", { style: { padding: '10px', overflow: 'auto', flex: 1 }, children: _jsx("div", { dangerouslySetInnerHTML: { __html: ftExplanation } }) }), _jsxs(StyledIndexingInfoSection, { children: [_jsxs(StyledIndexingToggle, { onClick: handleToggleIndexingInfo, disabled: loadingIndexingInfo, children: [_jsx(StyledLeftContent, { children: _jsx("span", { children: SDKUI_Localizator.IndexingInformation }) }), _jsx(StyledRightContent, { children: _jsx(StyledChevron, { "$isOpen": showIndexingInfo, children: "\u25BC" }) })] }), showIndexingInfo && indexingInfo && (_jsxs(StyledIndexingInfoBox, { children: [_jsx("div", { dangerouslySetInnerHTML: { __html: indexingInfo } }), loadingIndexingInfo && (_jsxs("div", { style: { position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', background: 'rgba(255, 255, 255, 0.9)', padding: '10px', borderRadius: '4px', boxShadow: '0 2px 8px rgba(0,0,0,0.15)' }, children: [SDKUI_Localizator.Loading, "..."] }))] }))] })] }));
659
660
  }, [selectedSearchResult, focusedItem, indexingInfo, showIndexingInfo, loadingIndexingInfo]);
661
+ const isBoardDisabled = useMemo(() => fromDTD?.hasBlog !== 1, [fromDTD?.hasBlog]);
660
662
  const allInitialPanelVisibility = {
661
663
  'tmSearchResult': true,
662
664
  'tmBlog': false,
@@ -725,9 +727,9 @@ handleNavigateToWGs, handleNavigateToDossiers, }) => {
725
727
  width: '100%',
726
728
  height: '100%',
727
729
  }, children: _jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showCicoWaitPanel, showWaitPanelPrimary: showCicoPrimaryProgress, waitPanelTitle: cicoWaitPanelTitle, waitPanelTextPrimary: cicoPrimaryProgressText, waitPanelValuePrimary: cicoPrimaryProgressValue, waitPanelMaxValuePrimary: cicoPrimaryProgressMax, isCancelable: true, abortController: abortControllerLocal, children: (groupId && groupId.length > 0) ?
728
- _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar })
730
+ _jsxs(_Fragment, { children: [_jsx(PanelDisabledStateHandler, { isBoardDisabled: isBoardDisabled }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar })] })
729
731
  :
730
- _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmSearchResult', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar }) }) }) }) }), renderDcmtOperations] }));
732
+ _jsxs(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmSearchResult', children: [_jsx(PanelDisabledStateHandler, { isBoardDisabled: isBoardDisabled }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar })] }) }) }) }), renderDcmtOperations] }));
731
733
  };
732
734
  export default TMSearchResult;
733
735
  const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, inputFocusedItem, allowMultipleSelection = true, showExportForm = false, onFocusedItemChanged, onDownloadDcmtsAsync, onVisibleItemChanged, inputSelectedItems = [], lastUpdateSearchTime, searchResult, onSelectionChanged, onDblClick, showSearchTMDatagrid, updateDataColumnsFromDataGrid, updateDataSourceFromDataGrid, updateSelectedRowKeysFromDataGrid }) => {
@@ -1237,6 +1239,18 @@ const TMSearchResultSelector = ({ searchResults = [], disableAccordionIfSingleCa
1237
1239
  return (_jsx(TMAccordionNew, { groups: accordionGroups, selectedItem: selectedResult, onSelectedItemChange: (result) => handleSelect(result) }));
1238
1240
  };
1239
1241
  //#endregion TMSearchResultSelector
1242
+ const PanelDisabledStateHandler = ({ isBoardDisabled }) => {
1243
+ const { setPanelVisibilityById, setToolbarButtonDisabled, panelVisibility } = useTMPanelManagerContext();
1244
+ useEffect(() => {
1245
+ // Aggiorna lo stato disabled del bottone toolbar
1246
+ setToolbarButtonDisabled('tmBlog', isBoardDisabled);
1247
+ // Chiude il pannello solo se è attualmente visibile e deve essere disabilitato
1248
+ if (isBoardDisabled && panelVisibility['tmBlog']) {
1249
+ setPanelVisibilityById('tmBlog', false);
1250
+ }
1251
+ }, [isBoardDisabled, setPanelVisibilityById, setToolbarButtonDisabled, panelVisibility]);
1252
+ return null;
1253
+ };
1240
1254
  const TMDcmtPreviewWrapper = ({ refreshPreviewTrigger, currentDcmt, isVisible }) => {
1241
1255
  const { setPanelVisibilityById, toggleMaximize, isResizingActive, countVisibleLeafPanels } = useTMPanelManagerContext();
1242
1256
  const deviceType = useDeviceType();