@topconsultnpm/sdkui-react 6.21.0-dev1.6 → 6.21.0-dev1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/features/documents/TMDcmtForm.js +2 -2
- package/lib/components/features/documents/TMMasterDetailDcmts.js +91 -12
- package/lib/components/features/documents/TMRelationViewer.d.ts +6 -1
- package/lib/components/features/documents/TMRelationViewer.js +43 -7
- package/lib/helper/checkinCheckoutManager.d.ts +1 -1
- package/lib/helper/checkinCheckoutManager.js +19 -4
- package/lib/hooks/useDocumentOperations.js +3 -2
- package/package.json +55 -55
|
@@ -1018,8 +1018,8 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
|
|
|
1018
1018
|
}
|
|
1019
1019
|
}, [TID, DID, triggerBlogRefresh, onRefreshBlogDatagrid]);
|
|
1020
1020
|
const checkoutBadge = useMemo(() => {
|
|
1021
|
-
const {
|
|
1022
|
-
if (!
|
|
1021
|
+
const { checkoutStatus } = getDcmtCicoStatus(formData, allUsers, fromDTD);
|
|
1022
|
+
if (!checkoutStatus.isCheckedOut)
|
|
1023
1023
|
return null;
|
|
1024
1024
|
return (_jsx(Ribbon, { "$isMobile": isMobile, children: _jsx(TMTooltip, { content: checkoutStatus.editLockTooltipText, position: "right", children: _jsx("span", { children: checkoutStatus.mode === 'editMode' ? SDKUI_Localizator.CheckOut : 'Locked' }) }) }));
|
|
1025
1025
|
}, [formData, fromDTD, isMobile]);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { DcmtTypeListCacheService, LayoutModes, SDK_Localizator } from '@topconsultnpm/sdk-ts';
|
|
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, isApprovalWorkflowView } from '../../../helper';
|
|
6
|
+
import { IconMultipleSelection, IconCheckFile, IconDetailDcmts, SDKUI_Localizator, IconMenuVertical, IconDataList, IconPreview, IconSearchCheck, IconBoard, IconDcmtTypeSys, IconShow, getMoreInfoTasksForDocument, isApprovalWorkflowView, searchResultToMetadataValues } from '../../../helper';
|
|
7
7
|
import { FormModes, SearchResultContext } from '../../../ts';
|
|
8
8
|
import { TMColors } from '../../../utils/theme';
|
|
9
9
|
import ShowAlert from '../../base/TMAlert';
|
|
@@ -29,11 +29,60 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
29
29
|
const [contextMenuPosition, setContextMenuPosition] = useState({ x: 0, y: 0 });
|
|
30
30
|
const [dtdFocused, setDtdFocused] = useState();
|
|
31
31
|
const [refreshKey, setRefreshKey] = useState(0);
|
|
32
|
+
// Stato per gestire la transizione fluida durante il refresh
|
|
33
|
+
const [isRefreshing, setIsRefreshing] = useState(false);
|
|
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 con transizione fluida: fade-out -> update -> fade-in
|
|
32
43
|
const onRefreshSearch = async () => {
|
|
33
44
|
await dcmtUtility?.onRefreshPreviewForm?.();
|
|
34
|
-
//
|
|
35
|
-
|
|
45
|
+
// Avvia fade-out
|
|
46
|
+
setIsRefreshing(true);
|
|
47
|
+
// Attendi che il fade-out sia completato, poi aggiorna
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
setRefreshKey(prev => prev + 1);
|
|
50
|
+
onRefreshOperationsDatagrid();
|
|
51
|
+
// Attendi un po' per dare tempo al re-render, poi fade-in
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
setIsRefreshing(false);
|
|
54
|
+
}, 300); // Durata extra dell'overlay dopo l'update
|
|
55
|
+
}, 200); // Durata del fade-out
|
|
36
56
|
};
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
const fetchFocusedItemMetadata = async () => {
|
|
59
|
+
if (!focusedItem?.tid || !focusedItem?.did) {
|
|
60
|
+
setFocusedItemFormData([]);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const tid = focusedItem?.tid;
|
|
65
|
+
const did = focusedItem?.did;
|
|
66
|
+
const metadata = await SDK_Globals.tmSession?.NewSearchEngine().GetMetadataAsync(tid, did, true);
|
|
67
|
+
// Transform metadata to MetadataValueDescriptorEx[] (similar to setMetadataList in TMDcmtForm)
|
|
68
|
+
if (metadata) {
|
|
69
|
+
const dtdResult = metadata.dtdResult;
|
|
70
|
+
const rows = dtdResult?.rows ? dtdResult.rows[0] : [];
|
|
71
|
+
const mids = metadata.selectMIDs;
|
|
72
|
+
// Get DTD with metadata descriptors
|
|
73
|
+
const dtdWithMetadata = await DcmtTypeListCacheService.GetWithNotGrantedAsync(tid, did, metadata);
|
|
74
|
+
const mdList = dtdWithMetadata?.metadata ?? [];
|
|
75
|
+
const metadataList = searchResultToMetadataValues(tid, dtdResult, rows, mids, mdList, LayoutModes.Update);
|
|
76
|
+
setFocusedItemFormData(structuredClone(metadataList));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error('Error fetching focusedItem metadata:', error);
|
|
81
|
+
setFocusedItemFormData([]);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
fetchFocusedItemMetadata();
|
|
85
|
+
}, [focusedItem?.tid, focusedItem?.did, refreshOperationsTrigger]);
|
|
37
86
|
// Load dtdFocused when focusedItem changes
|
|
38
87
|
useEffect(() => {
|
|
39
88
|
const loadDtdFocused = async () => {
|
|
@@ -83,14 +132,23 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
83
132
|
currentMetadataValues: [],
|
|
84
133
|
allUsers: [],
|
|
85
134
|
// searchResult: selectedSearchResult,
|
|
86
|
-
datagridUtility
|
|
135
|
+
datagridUtility: {
|
|
136
|
+
visibleItems: [],
|
|
137
|
+
onRefreshSearchAsyncDatagrid: datagridUtility?.onRefreshSearchAsyncDatagrid,
|
|
138
|
+
onRefreshDataRowsAsync: datagridUtility?.onRefreshDataRowsAsync,
|
|
139
|
+
refreshFocusedDataRowAsync: datagridUtility?.refreshFocusedDataRowAsync,
|
|
140
|
+
onRefreshBlogDatagrid: datagridUtility?.onRefreshBlogDatagrid,
|
|
141
|
+
onRefreshPreviewDatagrid: datagridUtility?.onRefreshPreviewDatagrid,
|
|
142
|
+
refreshOperationsTrigger,
|
|
143
|
+
onRefreshOperationsDatagrid,
|
|
144
|
+
},
|
|
87
145
|
dcmtUtility: {
|
|
88
146
|
approvalVID: dcmtUtility?.approvalVID,
|
|
89
|
-
dcmtDataRowForCicoStatus:
|
|
147
|
+
dcmtDataRowForCicoStatus: focusedItemFormData, // Passa i metadata trasformati del focusedItem per le operazioni di CICO
|
|
90
148
|
selectedDcmtSearchResultRelations: dcmtUtility?.selectedDcmtSearchResultRelations,
|
|
91
149
|
dcmtTIDHasDetailRelations: dcmtUtility?.dcmtTIDHasDetailRelations,
|
|
92
150
|
dcmtTIDHasMasterRelations: dcmtUtility?.dcmtTIDHasMasterRelations,
|
|
93
|
-
updateCurrentDcmt:
|
|
151
|
+
updateCurrentDcmt: onRefreshSearch,
|
|
94
152
|
onCloseDcmtForm: dcmtUtility?.onCloseDcmtForm,
|
|
95
153
|
onRefreshBlogForm: dcmtUtility?.onRefreshBlogForm,
|
|
96
154
|
onRefreshPreviewForm: onRefreshSearch,
|
|
@@ -227,11 +285,11 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
227
285
|
setContextMenuVisible(true);
|
|
228
286
|
}, children: [_jsx(TMRelationViewerWrapper, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, showZeroDcmts: showZeroDcmts,
|
|
229
287
|
// customItemRender={customItemRender}
|
|
230
|
-
allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound, onItemContextMenu: onItemContextMenu }, refreshKey), _jsx(TMContextMenu, { items: operationItems, externalControl: {
|
|
288
|
+
allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound, onItemContextMenu: onItemContextMenu, focusedItemFormData: focusedItemFormData }, refreshKey), _jsx(TMContextMenu, { items: operationItems, externalControl: {
|
|
231
289
|
visible: contextMenuVisible,
|
|
232
290
|
position: contextMenuPosition,
|
|
233
291
|
onClose: () => setContextMenuVisible(false)
|
|
234
|
-
} })] }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound, onItemContextMenu, contextMenuVisible, contextMenuPosition, refreshKey]);
|
|
292
|
+
} })] }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound, onItemContextMenu, contextMenuVisible, contextMenuPosition, refreshKey, focusedItemFormData]);
|
|
235
293
|
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, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest }, refreshKey), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshAfterAddDcmtToFavs, refreshKey]);
|
|
236
294
|
const initialPanelDimensions = {
|
|
237
295
|
'tmTreeView': { width: '50%', height: '100%' },
|
|
@@ -309,7 +367,28 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
309
367
|
toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
|
|
310
368
|
}
|
|
311
369
|
], [tmTreeView, tmFormOrResult, focusedItem?.isDcmt, dtdMaster]);
|
|
312
|
-
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 }) }),
|
|
370
|
+
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 }) }), _jsxs("div", { style: {
|
|
371
|
+
position: 'absolute',
|
|
372
|
+
top: 0,
|
|
373
|
+
left: 0,
|
|
374
|
+
right: 0,
|
|
375
|
+
bottom: 0,
|
|
376
|
+
backgroundColor: 'rgba(255, 255, 255, 0.7)',
|
|
377
|
+
display: 'flex',
|
|
378
|
+
alignItems: 'center',
|
|
379
|
+
justifyContent: 'center',
|
|
380
|
+
opacity: isRefreshing ? 1 : 0,
|
|
381
|
+
pointerEvents: isRefreshing ? 'auto' : 'none',
|
|
382
|
+
transition: 'opacity 200ms ease-in-out',
|
|
383
|
+
zIndex: 10,
|
|
384
|
+
}, children: [_jsx("div", { style: {
|
|
385
|
+
width: 40,
|
|
386
|
+
height: 40,
|
|
387
|
+
border: '3px solid #e0e0e0',
|
|
388
|
+
borderTopColor: TMColors.primaryColor,
|
|
389
|
+
borderRadius: '50%',
|
|
390
|
+
animation: 'spin 0.8s linear infinite',
|
|
391
|
+
} }), _jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })] }), renderDcmtOperations, renderFloatingBar] })] }));
|
|
313
392
|
};
|
|
314
393
|
export default TMMasterDetailDcmts;
|
|
315
394
|
/**
|
|
@@ -318,7 +397,7 @@ export default TMMasterDetailDcmts;
|
|
|
318
397
|
* - Panel visibility toggling
|
|
319
398
|
* - Focus delay handling
|
|
320
399
|
*/
|
|
321
|
-
const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound, onItemContextMenu }) => {
|
|
400
|
+
const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound, onItemContextMenu, focusedItemFormData }) => {
|
|
322
401
|
const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
|
|
323
402
|
// Handle focused item changes with panel visibility management
|
|
324
403
|
const handleFocusedItemChanged = useCallback((item) => {
|
|
@@ -349,7 +428,7 @@ const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndic
|
|
|
349
428
|
onItemContextMenu?.(item, e);
|
|
350
429
|
}, 100);
|
|
351
430
|
}, [onItemContextMenu, handleFocusedItemChanged]);
|
|
352
|
-
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 }));
|
|
431
|
+
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 }));
|
|
353
432
|
};
|
|
354
433
|
const TMFormOrResultWrapper = ({ deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid }) => {
|
|
355
434
|
const { setPanelVisibilityById } = useTMPanelManagerContext();
|
|
@@ -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
|
|
@@ -104,6 +104,11 @@ export interface TMRelationViewerProps {
|
|
|
104
104
|
* Use to show a context menu.
|
|
105
105
|
*/
|
|
106
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[];
|
|
107
112
|
}
|
|
108
113
|
/**
|
|
109
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, onItemContextMenu, }) => {
|
|
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,
|
|
@@ -247,7 +258,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
247
258
|
expanded: false,
|
|
248
259
|
hidden: false,
|
|
249
260
|
name: row?.SYS_Abstract?.value || row?.SYS_SUBJECT?.value || `Documento ${did}`,
|
|
250
|
-
fileExt: row?.FILEEXT?.value
|
|
261
|
+
fileExt: row?.FILEEXT?.value,
|
|
251
262
|
// Note: Recursive loading on expansion is handled by calculateItemsForNode
|
|
252
263
|
});
|
|
253
264
|
}
|
|
@@ -260,7 +271,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
260
271
|
console.error('❌ Error loading detail documents:', error);
|
|
261
272
|
}
|
|
262
273
|
return items;
|
|
263
|
-
}, [allowedTIDs]);
|
|
274
|
+
}, [allowedTIDs, focusedItemFormData, focusedItem?.dtd?.id]);
|
|
264
275
|
/**
|
|
265
276
|
* Recursively retrieve master documents
|
|
266
277
|
*/
|
|
@@ -319,6 +330,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
319
330
|
dcmtMasters.push({
|
|
320
331
|
tid: tid,
|
|
321
332
|
did: did,
|
|
333
|
+
dtd: dtd,
|
|
322
334
|
isLogDel: isLogDel,
|
|
323
335
|
key: `${tid}_${did}_${searchResult.relationID}_${dTID}_${dDID}_${rowGUID}`,
|
|
324
336
|
isDcmt: true,
|
|
@@ -609,6 +621,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
609
621
|
name: docRow?.SYS_Abstract?.value || docRow?.SYS_SUBJECT?.value || `Documento ${isForMaster ? 'Dettaglio' : 'Master'}`,
|
|
610
622
|
tid: dcmt.TID,
|
|
611
623
|
did: dcmt.DID,
|
|
624
|
+
dtd: dtd,
|
|
612
625
|
isDcmt: true,
|
|
613
626
|
isContainer: false,
|
|
614
627
|
expanded: false,
|
|
@@ -1080,8 +1093,31 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1080
1093
|
const metadataContent = customDocumentContent
|
|
1081
1094
|
? customDocumentContent(item, defaultMetadataContent || _jsx(_Fragment, {}))
|
|
1082
1095
|
: defaultMetadataContent;
|
|
1083
|
-
|
|
1084
|
-
|
|
1096
|
+
// Calculate checkout status for non-root documents
|
|
1097
|
+
let checkoutStatusIcon = null;
|
|
1098
|
+
if (item.values && item.dtd) {
|
|
1099
|
+
// Convert item.values to flat format expected by getDcmtCicoStatus
|
|
1100
|
+
const flatValues = {};
|
|
1101
|
+
if (item.values) {
|
|
1102
|
+
for (const key of Object.keys(item.values)) {
|
|
1103
|
+
const entry = item.values[key];
|
|
1104
|
+
if (entry?.md?.id && item.tid) {
|
|
1105
|
+
// Create TID_MID key format for metadata
|
|
1106
|
+
flatValues[`${item.tid}_${entry.md.id}`] = entry.value;
|
|
1107
|
+
}
|
|
1108
|
+
// Also add direct key for system properties
|
|
1109
|
+
flatValues[key] = entry?.value;
|
|
1110
|
+
}
|
|
1111
|
+
flatValues.TID = item.tid;
|
|
1112
|
+
flatValues.DID = item.did;
|
|
1113
|
+
}
|
|
1114
|
+
const { checkoutStatus } = getDcmtCicoStatus(flatValues, allUsers, item.dtd);
|
|
1115
|
+
if (checkoutStatus.isCheckedOut && checkoutStatus.icon) {
|
|
1116
|
+
checkoutStatusIcon = checkoutStatus.icon;
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
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] }));
|
|
1120
|
+
}, [onDocumentDoubleClick, showCurrentDcmtIndicator, inputDcmts, customMainContainerContent, customDocumentStyle, customDocumentContent, showMetadataNames, showMainDocument, focusedItemFormData, focusedItem?.dtd, allUsers]);
|
|
1085
1121
|
/**
|
|
1086
1122
|
* Wrapper renderer that handles custom rendering if provided
|
|
1087
1123
|
*/
|
|
@@ -259,13 +259,15 @@ export const getDcmtCicoStatus = (dcmt, allUsers, dtd) => {
|
|
|
259
259
|
let checkoutDate;
|
|
260
260
|
let version = 1;
|
|
261
261
|
let fileExt;
|
|
262
|
+
let isMetadata = false;
|
|
262
263
|
// ========================================================================
|
|
263
|
-
// CASO 1: Documento come Array di MetadataValueDescriptorEx
|
|
264
|
+
// CASO 1: Documento come Array di MetadataValueDescriptorEx: Form del documento
|
|
264
265
|
// ========================================================================
|
|
265
266
|
// Questo formato viene utilizzato quando il documento proviene da query
|
|
266
267
|
// o liste dove ogni metadato è un oggetto separato con proprietà 'md' e 'value'
|
|
267
268
|
if (Array.isArray(dcmt) && dcmt.length > 0 && dcmt[0]?.md !== undefined) {
|
|
268
269
|
const dcmtsArray = dcmt;
|
|
270
|
+
console.log("dcmtsArray:", dcmtsArray);
|
|
269
271
|
// Estrai l'ID dell'utente che ha effettuato il checkout
|
|
270
272
|
const checkoutUserIdProperty = dcmtsArray.find((item) => item.md?.name === CICO_MetadataNames.CICO_CheckoutUserID);
|
|
271
273
|
const checkoutUserIdValue = checkoutUserIdProperty?.value;
|
|
@@ -279,9 +281,11 @@ export const getDcmtCicoStatus = (dcmt, allUsers, dtd) => {
|
|
|
279
281
|
version = (versionRaw != null && !isNaN(Number(versionRaw))) ? Number(versionRaw) : 1;
|
|
280
282
|
const fileExtProperty = dcmtsArray.find((item) => item.mid === SystemMIDsAsNumber.FileExt);
|
|
281
283
|
fileExt = fileExtProperty?.value ? fileExtProperty.value.toString() : null;
|
|
284
|
+
const fileCountProperty = dcmtsArray.find((item) => item.mid === SystemMIDsAsNumber.FileCount);
|
|
285
|
+
isMetadata = !(fileCountProperty?.value && Number(fileCountProperty.value) > 0);
|
|
282
286
|
}
|
|
283
287
|
// ========================================================================
|
|
284
|
-
// CASO 2: Documento come Oggetto Piatto (formato standard)
|
|
288
|
+
// CASO 2: Documento come Oggetto Piatto (formato standard): Risultato della ricerca
|
|
285
289
|
// ========================================================================
|
|
286
290
|
// Questo formato viene utilizzato quando il documento ha proprietà dirette
|
|
287
291
|
// nel formato chiave-valore: TID, DID, e "TID_MetadataID" per i metadati
|
|
@@ -290,6 +294,8 @@ export const getDcmtCicoStatus = (dcmt, allUsers, dtd) => {
|
|
|
290
294
|
const CICO_CheckoutUserID_Meta = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_CheckoutUserID);
|
|
291
295
|
const CICO_CheckoutDate_Meta = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_CheckoutDate);
|
|
292
296
|
const CICO_Version_Meta = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_Version);
|
|
297
|
+
const fileCountValue = dcmt.FILECOUNT != null ? Number(dcmt.FILECOUNT) : NaN;
|
|
298
|
+
isMetadata = isNaN(fileCountValue) || fileCountValue <= 0;
|
|
293
299
|
fileExt = dcmt.FILEEXT ? dcmt.FILEEXT.toString() : null;
|
|
294
300
|
// Estrai l'ID dell'utente che ha effettuato il checkout
|
|
295
301
|
if (CICO_CheckoutUserID_Meta?.id) {
|
|
@@ -310,6 +316,15 @@ export const getDcmtCicoStatus = (dcmt, allUsers, dtd) => {
|
|
|
310
316
|
}
|
|
311
317
|
}
|
|
312
318
|
// ========================================================================
|
|
319
|
+
// EARLY RETURN: Documento di soli metadati (senza file)
|
|
320
|
+
// ========================================================================
|
|
321
|
+
if (isMetadata) {
|
|
322
|
+
return {
|
|
323
|
+
cicoEnabled: false,
|
|
324
|
+
checkoutStatus: { isCheckedOut: false, mode: '', version: 1, icon: null, editLockTooltipText: null }
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
// ========================================================================
|
|
313
328
|
// COSTRUZIONE DELLO STATO DI CHECKOUT
|
|
314
329
|
// ========================================================================
|
|
315
330
|
let checkoutStatus = {
|
|
@@ -345,8 +360,8 @@ export const getDcmtCicoStatus = (dcmt, allUsers, dtd) => {
|
|
|
345
360
|
// RESTITUZIONE RISULTATO FINALE
|
|
346
361
|
// ========================================================================
|
|
347
362
|
return {
|
|
348
|
-
// CICO è abilitato se configurato nel DTD
|
|
349
|
-
cicoEnabled: cicoInfo.CICO === 1 && cicoInfo.CanCICO === AccessLevels.Yes && fileExt !== null && fileExt !== '',
|
|
363
|
+
// CICO è abilitato se configurato nel DTD, l'utente ha i permessi e il documento non è di soli metadati
|
|
364
|
+
cicoEnabled: cicoInfo.CICO === 1 && cicoInfo.CanCICO === AccessLevels.Yes && fileExt !== null && fileExt !== '' && !isMetadata,
|
|
350
365
|
checkoutStatus: checkoutStatus
|
|
351
366
|
};
|
|
352
367
|
};
|
|
@@ -105,6 +105,7 @@ export const useDocumentOperations = (props) => {
|
|
|
105
105
|
}, [refreshOperationsTrigger]);
|
|
106
106
|
// Context helpers
|
|
107
107
|
const isDcmtFormContext = context === SearchResultContext.DCMT_FORM;
|
|
108
|
+
const isMasterDetailContext = context === SearchResultContext.MASTER_DETAIL;
|
|
108
109
|
const { showHistory, showHistoryCallback, hideHistoryCallback, showCheckoutInformationForm, commentFormState, hideCommentFormCallback, showCheckoutInformationFormCallback, hideCheckoutInformationFormCallback, copyCheckoutPathToClipboardCallback, handleCheckOutCallback, handleCheckInCallback, showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, } = useCheckInOutOperations({
|
|
109
110
|
onRefreshPreview: onRefreshPreviewCallback
|
|
110
111
|
});
|
|
@@ -632,7 +633,7 @@ export const useDocumentOperations = (props) => {
|
|
|
632
633
|
const checkinMenuItem = () => {
|
|
633
634
|
// Take the first document (used for validation checks)
|
|
634
635
|
let dcmt = focusedItem;
|
|
635
|
-
if (isDcmtFormContext) {
|
|
636
|
+
if (isDcmtFormContext || isMasterDetailContext) {
|
|
636
637
|
dcmt = dcmtDataRowForCicoStatus;
|
|
637
638
|
}
|
|
638
639
|
const { cicoEnabled, checkoutStatus } = getDcmtCicoStatus(dcmt, allUsers, dtd);
|
|
@@ -1059,7 +1060,6 @@ export const useDocumentOperations = (props) => {
|
|
|
1059
1060
|
disabled: isDisabledForSingleRow() && isDisabledForMultiRow(),
|
|
1060
1061
|
submenu: [
|
|
1061
1062
|
addToFavoriteOperation(),
|
|
1062
|
-
openFormOperation(),
|
|
1063
1063
|
downloadFileMenuItem(),
|
|
1064
1064
|
downloadXMLAttachmentsMenuItem(),
|
|
1065
1065
|
]
|
|
@@ -1090,6 +1090,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1090
1090
|
]
|
|
1091
1091
|
},
|
|
1092
1092
|
signatureMenuItem(),
|
|
1093
|
+
checkinMenuItem(),
|
|
1093
1094
|
...((inputDcmtFormLayoutMode === LayoutModes.Update) ? [fullTextSearchMenuItem()] : []),
|
|
1094
1095
|
];
|
|
1095
1096
|
};
|
package/package.json
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name":
|
|
3
|
-
"version":
|
|
4
|
-
"description":
|
|
5
|
-
"scripts":
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"author":
|
|
17
|
-
"license":
|
|
18
|
-
"devDependencies":
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"main":
|
|
36
|
-
"types":
|
|
37
|
-
"module":
|
|
38
|
-
"files":
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"dependencies":
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"overrides":
|
|
55
|
-
|
|
56
|
-
|
|
2
|
+
"name": "@topconsultnpm/sdkui-react",
|
|
3
|
+
"version": "6.21.0-dev1.8",
|
|
4
|
+
"description": "",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
7
|
+
"clean": "powershell Remove-Item lib/ -recurse",
|
|
8
|
+
"copy-files": "copyfiles -u 1 src/assets/*.* src/assets/ImageLibrary/*.* src/assets/thumbnails/*.* src/assets/IconsS4t/*.* src/assets/Metadata/*.* src/css/tm-sdkui.css lib/",
|
|
9
|
+
"tm-build": "npm run clean && tsc && npm run copy-files",
|
|
10
|
+
"tm-watch": "tsc -w",
|
|
11
|
+
"tm-publish": "npm publish --tag latest",
|
|
12
|
+
"tm-publish_wl": "npm publish",
|
|
13
|
+
"storybook": "storybook dev -p 6006",
|
|
14
|
+
"build-storybook": "storybook build"
|
|
15
|
+
},
|
|
16
|
+
"author": "TopConsult",
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@chromatic-com/storybook": "^4.1.3",
|
|
20
|
+
"@storybook/addon-docs": "^10.1.0",
|
|
21
|
+
"@storybook/addon-onboarding": "^10.1.0",
|
|
22
|
+
"@storybook/react-vite": "^10.1.0",
|
|
23
|
+
"@types/htmlparser2": "^3.10.7",
|
|
24
|
+
"@types/node": "^20.2.5",
|
|
25
|
+
"@types/react": "^18.3.3",
|
|
26
|
+
"@types/react-dom": "^18.3.3",
|
|
27
|
+
"copyfiles": "^2.4.1",
|
|
28
|
+
"esbuild": "^0.25.0",
|
|
29
|
+
"react": "^18.3.1",
|
|
30
|
+
"react-dom": "^18.3.1",
|
|
31
|
+
"storybook": "^10.1.0",
|
|
32
|
+
"typescript": "^5.9.3",
|
|
33
|
+
"vite": "^6.1.1"
|
|
34
|
+
},
|
|
35
|
+
"main": "dist/cjs/index.js",
|
|
36
|
+
"types": "./index.d.ts",
|
|
37
|
+
"module": "lib/esm/index.js",
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"lib"
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@topconsultnpm/sdk-ts": "6.21.0-dev1.2",
|
|
44
|
+
"buffer": "^6.0.3",
|
|
45
|
+
"devextreme": "25.2.4",
|
|
46
|
+
"devextreme-react": "25.2.4",
|
|
47
|
+
"exceljs": "^4.4.0",
|
|
48
|
+
"htmlparser2": "^10.0.0",
|
|
49
|
+
"pdfjs-dist": "5.4.296",
|
|
50
|
+
"react-pdf": "^10.3.0",
|
|
51
|
+
"react-router-dom": "^6.15.0",
|
|
52
|
+
"styled-components": "^6.1.1"
|
|
53
|
+
},
|
|
54
|
+
"overrides": {
|
|
55
|
+
"esbuild": "^0.25.0"
|
|
56
|
+
}
|
|
57
57
|
}
|