@topconsultnpm/sdkui-react 6.20.0 → 6.21.0-dev1.11

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 (41) hide show
  1. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +7 -1
  2. package/lib/components/base/TMTreeView.d.ts +2 -1
  3. package/lib/components/base/TMTreeView.js +8 -3
  4. package/lib/components/base/TMWaitPanel.js +6 -5
  5. package/lib/components/choosers/TMUserChooser.js +3 -1
  6. package/lib/components/features/archive/TMArchive.d.ts +1 -1
  7. package/lib/components/features/archive/TMArchive.js +2 -2
  8. package/lib/components/features/documents/TMDcmtBlog.d.ts +1 -0
  9. package/lib/components/features/documents/TMDcmtBlog.js +2 -1
  10. package/lib/components/features/documents/TMDcmtForm.d.ts +42 -34
  11. package/lib/components/features/documents/TMDcmtForm.js +282 -641
  12. package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +34 -0
  13. package/lib/components/features/documents/TMDcmtFormActionButtons.js +124 -0
  14. package/lib/components/features/documents/TMFileUploader.d.ts +1 -1
  15. package/lib/components/features/documents/TMFileUploader.js +3 -3
  16. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +27 -2
  17. package/lib/components/features/documents/TMMasterDetailDcmts.js +239 -18
  18. package/lib/components/features/documents/TMRelationViewer.d.ts +12 -1
  19. package/lib/components/features/documents/TMRelationViewer.js +48 -10
  20. package/lib/components/features/search/TMSavedQuerySelector.js +1 -1
  21. package/lib/components/features/search/TMSearch.d.ts +3 -2
  22. package/lib/components/features/search/TMSearch.js +3 -3
  23. package/lib/components/features/search/TMSearchResult.d.ts +28 -26
  24. package/lib/components/features/search/TMSearchResult.js +364 -487
  25. package/lib/components/features/search/TMViewHistoryDcmt.js +6 -0
  26. package/lib/components/features/tasks/TMTaskForm.d.ts +2 -1
  27. package/lib/components/features/tasks/TMTaskForm.js +2 -2
  28. package/lib/helper/checkinCheckoutManager.d.ts +1 -1
  29. package/lib/helper/checkinCheckoutManager.js +25 -6
  30. package/lib/hooks/useCheckInOutOperations.d.ts +7 -6
  31. package/lib/hooks/useCheckInOutOperations.js +9 -16
  32. package/lib/hooks/useDcmtOperations.d.ts +3 -2
  33. package/lib/hooks/useDcmtOperations.js +2 -2
  34. package/lib/hooks/useDocumentOperations.d.ts +140 -0
  35. package/lib/hooks/useDocumentOperations.js +1307 -0
  36. package/lib/hooks/useRelatedDocuments.d.ts +1 -1
  37. package/lib/ts/types.d.ts +2 -1
  38. package/lib/ts/types.js +1 -0
  39. package/package.json +2 -2
  40. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +0 -11
  41. package/lib/components/features/search/TMSearchResultsMenuItems.js +0 -758
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+ import { DcmtTypeDescriptor, TaskDescriptor, ObjectRef } from "@topconsultnpm/sdk-ts";
3
+ import { IWorkItemData } from "../../../ts";
4
+ import { DeviceType } from "../../base/TMDeviceProvider";
5
+ interface TMDcmtFormActionButtonsProps {
6
+ showToppyForApprove: boolean;
7
+ workItems: Array<IWorkItemData>;
8
+ deviceType: DeviceType | undefined;
9
+ isMobile: boolean;
10
+ handleSignApprove: () => void;
11
+ updateShowApprovePopup: (value: boolean) => void;
12
+ updateShowRejectPopup: (value: boolean) => void;
13
+ updateShowReAssignPopup: (value: boolean) => void;
14
+ updateShowMoreInfoPopup: (value: boolean) => void;
15
+ fromDTD: DcmtTypeDescriptor | undefined;
16
+ showToppyForCompleteMoreInfo: boolean;
17
+ moreInfoTasks?: Array<TaskDescriptor>;
18
+ setShowCommentForm: React.Dispatch<React.SetStateAction<boolean>>;
19
+ showToppyForReferences: boolean;
20
+ dcmtReferences: ObjectRef[] | undefined;
21
+ referenceActionMap: {
22
+ Dossier: {
23
+ label: string;
24
+ };
25
+ WorkingGroup: {
26
+ label: string;
27
+ };
28
+ };
29
+ handleNavigateToReference: (ref: ObjectRef) => void;
30
+ setShowMoreInfoTaskPopup: React.Dispatch<React.SetStateAction<boolean>>;
31
+ setShowMoreInfoTaskTask: React.Dispatch<React.SetStateAction<TaskDescriptor | undefined>>;
32
+ }
33
+ declare const TMDcmtFormActionButtons: (props: TMDcmtFormActionButtonsProps) => import("react/jsx-runtime").JSX.Element;
34
+ export default TMDcmtFormActionButtons;
@@ -0,0 +1,124 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo, useRef } from "react";
3
+ import { ObjectClasses, SDK_Globals } from "@topconsultnpm/sdk-ts";
4
+ import { TASK_MORE_INFO_PREFIX_NAME, SDKUI_Localizator, PDGS_COLORS } from "../../../helper";
5
+ import { TMColors } from "../../../utils/theme";
6
+ import { ReferencesContainer, StyledReferenceButton } from "../../base/Styled";
7
+ import TMButton from "../../base/TMButton";
8
+ import TMTooltip from "../../base/TMTooltip";
9
+ import { WorkFlowOperationButtons } from "../workflow/TMWorkflowPopup";
10
+ const TMDcmtFormActionButtons = (props) => {
11
+ const { showToppyForApprove, workItems, deviceType, isMobile, handleSignApprove, updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup, fromDTD, showToppyForCompleteMoreInfo, moreInfoTasks, setShowCommentForm, showToppyForReferences, dcmtReferences, referenceActionMap, handleNavigateToReference, setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask } = props;
12
+ const tasksNumber = useMemo(() => moreInfoTasks?.length ?? 0, [moreInfoTasks]);
13
+ const currentTask = useMemo(() => {
14
+ if (!moreInfoTasks || moreInfoTasks.length === 0)
15
+ return null;
16
+ if (moreInfoTasks.length === 1)
17
+ return moreInfoTasks[0];
18
+ // If there are multiple tasks, we cannot determine which one is relevant, so we return null
19
+ return null;
20
+ }, [moreInfoTasks]);
21
+ const { hasMoreInfo, hasApprove, hasReferences } = useMemo(() => {
22
+ const referencesExist = showToppyForReferences && dcmtReferences?.some(ref => ref.objClass === ObjectClasses.Dossier || ref.objClass === ObjectClasses.WorkingGroup);
23
+ return {
24
+ hasMoreInfo: Boolean(showToppyForCompleteMoreInfo),
25
+ hasApprove: Boolean(showToppyForApprove),
26
+ hasReferences: Boolean(referencesExist)
27
+ };
28
+ }, [
29
+ showToppyForCompleteMoreInfo,
30
+ showToppyForApprove,
31
+ showToppyForReferences,
32
+ dcmtReferences
33
+ ]);
34
+ const Divider = () => (_jsx("div", { style: { height: '1px', width: '100%', background: 'linear-gradient(to right, transparent, rgba(255,255,255,0.4), transparent)', margin: '3px 0', opacity: 0.8, } }));
35
+ return _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: [hasMoreInfo && (tasksNumber === 1 ? (_jsx("div", { style: { display: 'flex', gap: "10px", flexDirection: 'column', alignItems: 'center' }, children: _jsx("div", { style: {
36
+ padding: '10px',
37
+ color: '#FFFFFF',
38
+ maxWidth: '240px',
39
+ background: 'linear-gradient(135deg, #1E90FF 0%, #0077BE 60%, #00509E 100%)',
40
+ border: '1px solid rgba(255,255,255,0.15)',
41
+ boxShadow: '0 8px 20px rgba(0, 0, 50, 0.4)',
42
+ backdropFilter: 'blur(6px)',
43
+ display: 'flex',
44
+ flexDirection: 'column',
45
+ alignItems: 'center',
46
+ textAlign: 'center',
47
+ gap: '10px',
48
+ cursor: 'default',
49
+ }, children: (() => {
50
+ const userID = SDK_Globals.tmSession?.SessionDescr?.userID;
51
+ const isSender = currentTask?.fromID !== undefined && currentTask.fromID === userID;
52
+ const isRecipient = currentTask?.toID !== undefined && currentTask.toID === userID;
53
+ const truncate = (str, maxLength) => str && str.length > maxLength ? str.substring(0, maxLength) + '...' : str;
54
+ const senderNameTruncated = currentTask?.fromName ? truncate(currentTask.fromName, 30) : 'N/A';
55
+ const recipientNameTruncated = currentTask?.toName ? truncate(currentTask.toName, 30) : 'N/A';
56
+ const taskNameTrunc = currentTask?.name ? truncate(currentTask.name.replace(TASK_MORE_INFO_PREFIX_NAME ?? '', ''), 30) : 'N/A';
57
+ return (_jsxs(_Fragment, { children: [(isSender && !isRecipient) && (_jsx(TaskLink, { messagePrefix: `Hai richiesto maggiori informazioni a "${recipientNameTruncated}" tramite l'attività`, name: currentTask.name ?? 'N/A', taskNameTrunc: taskNameTrunc ?? 'N/A', description: currentTask.description ?? 'N/A', currentTask: currentTask, setShowMoreInfoTaskPopup: setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask: setShowMoreInfoTaskTask })), (isRecipient && !isSender) && (_jsxs("div", { style: {
58
+ display: 'flex',
59
+ flexDirection: 'column',
60
+ alignItems: 'center',
61
+ gap: '10px'
62
+ }, children: [_jsx(TaskLink, { messagePrefix: `"${senderNameTruncated}" ti ha richiesto maggiori informazioni tramite l'attività`, name: currentTask.name ?? 'N/A', taskNameTrunc: taskNameTrunc ?? 'N/A', description: currentTask.description ?? 'N/A', currentTask: currentTask, setShowMoreInfoTaskPopup: setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask: setShowMoreInfoTaskTask }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx("span", { className: "dx-icon-chat" }), caption: SDKUI_Localizator.CommentAndComplete, width: "180px", disabled: false, onClick: () => setShowCommentForm(true), onMouseDown: e => e.stopPropagation(), advancedColor: TMColors.success, color: "success" })] }))] }));
63
+ })() }) })) : (_jsx("div", { style: {
64
+ padding: '10px',
65
+ color: '#FFFFFF',
66
+ maxWidth: '240px',
67
+ background: 'linear-gradient(135deg, #1E90FF 0%, #0077BE 60%, #00509E 100%)',
68
+ border: '1px solid rgba(255,255,255,0.15)',
69
+ boxShadow: '0 8px 20px rgba(0, 0, 50, 0.4)',
70
+ backdropFilter: 'blur(6px)',
71
+ display: 'flex',
72
+ flexDirection: 'column',
73
+ alignItems: 'center',
74
+ textAlign: 'center',
75
+ gap: '10px',
76
+ cursor: 'default',
77
+ }, children: `Ci sono ${moreInfoTasks?.length ?? 0} richieste di maggiori informazioni. ${SDKUI_Localizator.ManageFromTaskPanel}` }))), hasMoreInfo && hasApprove && _jsx(Divider, {}), hasApprove && (workItems.length === 1 ?
78
+ _jsx(WorkFlowOperationButtons, { dtd: fromDTD, deviceType: deviceType, onApprove: () => updateShowApprovePopup(true), onSignApprove: handleSignApprove, onReject: () => updateShowRejectPopup(true), onReAssign: () => updateShowReAssignPopup(true), onMoreInfo: () => updateShowMoreInfoPopup(true) })
79
+ :
80
+ _jsxs("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: [`Questo documento è associato a ${workItems.length} workitem.`, _jsx("br", {}), `Per approvare, vai alla pagina "Approvazione workflow".`] })), (hasApprove && hasReferences) || (hasMoreInfo && !hasApprove && hasReferences) ? (_jsx(Divider, {})) : null, hasReferences && (_jsx(ReferencesContainer, { children: dcmtReferences?.filter(ref => ref.objClass === ObjectClasses.Dossier || ref.objClass === ObjectClasses.WorkingGroup)
81
+ .map((ref, index) => {
82
+ const mapEntry = referenceActionMap[String(ref.objClass)];
83
+ const label = mapEntry?.label ?? 'Vai a riferimento';
84
+ let backgroundColor;
85
+ switch (ref.objClass) {
86
+ case ObjectClasses.WorkingGroup:
87
+ backgroundColor = PDGS_COLORS.WORKING_GROUP;
88
+ break;
89
+ case ObjectClasses.Dossier:
90
+ backgroundColor = PDGS_COLORS.DOSSIER;
91
+ break;
92
+ case ObjectClasses.Document:
93
+ backgroundColor = PDGS_COLORS.DOCUMENT;
94
+ break;
95
+ default:
96
+ backgroundColor = "#C2388B";
97
+ break;
98
+ }
99
+ return (_jsxs(StyledReferenceButton, { onClick: () => handleNavigateToReference(ref), onDoubleClick: (e) => { e.preventDefault(); e.stopPropagation(); }, "$bgColor": backgroundColor, children: [_jsx("span", { children: label }), _jsx("span", { children: `"${ref.objName}"` })] }, `ref-${index}-${ref.objID}`));
100
+ }) }))] });
101
+ };
102
+ export default TMDcmtFormActionButtons;
103
+ const TaskLink = (props) => {
104
+ const { messagePrefix, name, taskNameTrunc, description, currentTask, setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask } = props;
105
+ const mouseMoved = useRef(false);
106
+ const handleMouseDown = () => {
107
+ mouseMoved.current = false;
108
+ };
109
+ const handleMouseMove = () => {
110
+ mouseMoved.current = true;
111
+ };
112
+ return (_jsx(_Fragment, { children: _jsx("div", { style: { display: 'inline-flex', alignItems: 'center', gap: '4px' }, children: _jsxs("div", { onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, style: { display: 'inline' }, children: [messagePrefix, ' "', _jsx("span", { style: {
113
+ cursor: 'pointer',
114
+ fontWeight: 500,
115
+ textDecoration: 'none',
116
+ transition: 'text-decoration 0.2s',
117
+ }, onClick: () => {
118
+ setShowMoreInfoTaskPopup(true);
119
+ setShowMoreInfoTaskTask(currentTask);
120
+ }, onMouseEnter: e => e.currentTarget.style.textDecoration = 'underline', onMouseLeave: e => e.currentTarget.style.textDecoration = 'none', children: taskNameTrunc }), '" ', _jsx(TMTooltip, { parentStyle: { display: 'inline' }, childStyle: { display: 'inline' }, content: _jsxs("div", { style: { whiteSpace: 'pre-line', textAlign: 'left' }, children: [_jsxs("div", { children: [_jsx("b", { children: SDKUI_Localizator.Name }), ": ", name] }), _jsxs("div", { children: [_jsx("b", { children: SDKUI_Localizator.Description }), ": ", description] })] }), children: _jsx("i", { className: "dx-icon dx-icon-info", onClick: () => {
121
+ setShowMoreInfoTaskPopup(true);
122
+ setShowMoreInfoTaskTask(currentTask);
123
+ }, style: { fontSize: '16px', lineHeight: 1, cursor: 'pointer' } }) })] }) }) }));
124
+ };
@@ -4,7 +4,7 @@ import { DcmtTypeDescriptor } from '@topconsultnpm/sdk-ts';
4
4
  interface ITMFileUploader {
5
5
  fromDTD?: DcmtTypeDescriptor;
6
6
  onFileUpload?: (file: File | null) => void;
7
- openPdfEditor?: (fromDTD?: DcmtTypeDescriptor, file?: File | null, handleFile?: (file: File) => void) => void;
7
+ openFileUploaderPdfEditor?: (fromDTD?: DcmtTypeDescriptor, file?: File | null, handleFile?: (file: File) => void) => void;
8
8
  onClose?: () => void;
9
9
  onScanRequest?: (onFileScanned: (file: File) => void) => void;
10
10
  isRequired?: boolean;
@@ -23,7 +23,7 @@ const isScannerLicenseConfigured = () => {
23
23
  return false;
24
24
  }
25
25
  };
26
- const TMFileUploader = ({ fromDTD, deviceType = DeviceType.DESKTOP, onClose, onFileUpload, openPdfEditor, onScanRequest, isRequired = false, defaultBlob = null, isResizingActive, showTMPanel = true, enableDragDropOverlay = false, showScannerIcon = true }) => {
26
+ const TMFileUploader = ({ fromDTD, deviceType = DeviceType.DESKTOP, onClose, onFileUpload, openFileUploaderPdfEditor, onScanRequest, isRequired = false, defaultBlob = null, isResizingActive, showTMPanel = true, enableDragDropOverlay = false, showScannerIcon = true }) => {
27
27
  const isBetaFeaturesEnabled = useBetaFeatures();
28
28
  const [dragOver, setDragOver] = useState(false);
29
29
  const [uploadedFile, setUploadedFile] = useState(defaultBlob);
@@ -101,11 +101,11 @@ const TMFileUploader = ({ fromDTD, deviceType = DeviceType.DESKTOP, onClose, onF
101
101
  _jsx("div", { style: { backgroundColor: '#f6dbdb', padding: '5px 10px', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: TMColors.error }, children: _jsxs("div", { children: [" ", 'Anteprima non disponibile.', fileExt && _jsx("b", { children: ` (*.${fileExt})` })] }) })] });
102
102
  const innerContent = (_jsxs("div", { style: { width: '100%', height: '100%', padding: '2px', display: 'flex', flexDirection: 'column', gap: 10 }, children: [enableDragDropOverlay && _jsx(TMDragDropOverlay, { handleFile: handleFile, refocusAfterFileInput: refocusAfterFileInput }), content] }));
103
103
  const toolbar = useMemo(() => {
104
- return (_jsxs(_Fragment, { children: [(isPdfEditorAvailable(fromDTD, fileExt) && openPdfEditor) && (_jsx(TMCommandsContextMenu, { target: "#TMPanel-FileUploader-Commands-Header", menuItems: [
104
+ return (_jsxs(_Fragment, { children: [(isPdfEditorAvailable(fromDTD, fileExt) && openFileUploaderPdfEditor) && (_jsx(TMCommandsContextMenu, { target: "#TMPanel-FileUploader-Commands-Header", menuItems: [
105
105
  {
106
106
  icon: _jsx(IconEdit, {}),
107
107
  text: 'PDF Editor',
108
- onClick: () => openPdfEditor(fromDTD, uploadedFile, handleFile)
108
+ onClick: () => openFileUploaderPdfEditor(fromDTD, uploadedFile, handleFile)
109
109
  }
110
110
  ], showEvent: "click", children: _jsx(IconMenuVertical, { id: "TMPanel-FileUploader-Commands-Header", color: "white", cursor: "pointer" }) })), deviceType !== DeviceType.MOBILE && (_jsx(StyledHeaderIcon, { onClick: onClose, "$color": "white", children: _jsx(TMTooltip, { content: SDKUI_Localizator.Close, children: _jsx(IconCloseOutline, {}) }) }))] }));
111
111
  }, [deviceType, fromDTD, onClose]);
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { HomeBlogPost, TaskDescriptor } from '@topconsultnpm/sdk-ts';
3
- import { DcmtInfo, TaskContext } from '../../../ts';
2
+ import { HomeBlogPost, SearchResultDescriptor, TaskDescriptor } from '@topconsultnpm/sdk-ts';
3
+ import { DcmtInfo, TaskContext, MetadataValueDescriptorEx } from '../../../ts';
4
4
  import { DeviceContextProps } from '../../base/TMDeviceProvider';
5
5
  interface ITMMasterDetailDcmtsProps extends DeviceContextProps {
6
6
  allTasks?: Array<TaskDescriptor>;
@@ -21,6 +21,31 @@ interface ITMMasterDetailDcmtsProps extends DeviceContextProps {
21
21
  onBack?: () => void;
22
22
  appendMasterDcmts?: (tid: number | undefined, did: number | undefined) => void;
23
23
  onTaskCreateRequest?: (taskContext: TaskContext, onTaskCreated?: (task?: TaskDescriptor) => void) => void;
24
+ onRefreshAfterAddDcmtToFavs?: () => void;
25
+ editPdfForm?: boolean;
26
+ openS4TViewer?: boolean;
27
+ onOpenS4TViewerRequest?: (dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: (() => Promise<void>)) => void;
28
+ onOpenPdfEditorRequest?: ((dcmtInfo: Array<DcmtInfo>, refreshDocumentPreview?: () => Promise<void>) => void);
29
+ datagridUtility?: {
30
+ onRefreshSearchAsyncDatagrid?: () => Promise<void>;
31
+ onRefreshDataRowsAsync?: (() => Promise<void>);
32
+ refreshFocusedDataRowAsync?: (tid: number | undefined, did: number | undefined, refreshUI?: boolean, metadataResult?: SearchResultDescriptor | null) => Promise<void>;
33
+ onRefreshBlogDatagrid?: () => Promise<void>;
34
+ onRefreshPreviewDatagrid?: () => Promise<void>;
35
+ };
36
+ dcmtUtility?: {
37
+ approvalVID?: number;
38
+ dcmtDataRowForCicoStatus?: Array<MetadataValueDescriptorEx> | any;
39
+ selectedDcmtSearchResultRelations?: SearchResultDescriptor;
40
+ dcmtTIDHasDetailRelations?: boolean;
41
+ dcmtTIDHasMasterRelations?: boolean;
42
+ updateCurrentDcmt?: () => Promise<void>;
43
+ onCloseDcmtForm?: () => void;
44
+ onRefreshBlogForm?: () => Promise<void>;
45
+ onRefreshPreviewForm?: () => Promise<void>;
46
+ taskFormDialogComponent?: React.ReactNode;
47
+ s4TViewerDialogComponent?: React.ReactNode;
48
+ };
24
49
  }
25
50
  declare const TMMasterDetailDcmts: React.FC<ITMMasterDetailDcmtsProps>;
26
51
  export default TMMasterDetailDcmts;
@@ -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 } from '../../../helper';
7
7
  import { FormModes, SearchResultContext } from '../../../ts';
8
8
  import { TMColors } from '../../../utils/theme';
9
9
  import ShowAlert from '../../base/TMAlert';
@@ -15,7 +15,9 @@ import TMSearchResult from '../search/TMSearchResult';
15
15
  import TMDcmtForm from './TMDcmtForm';
16
16
  import { TMNothingToShow } from './TMDcmtPreview';
17
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 }) => {
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,179 @@ 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
+ // 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
43
+ const onRefreshSearch = async () => {
44
+ await dcmtUtility?.onRefreshPreviewForm?.();
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
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]);
86
+ // Load dtdFocused when focusedItem changes
87
+ useEffect(() => {
88
+ const loadDtdFocused = async () => {
89
+ if (!focusedItem?.tid) {
90
+ setDtdFocused(undefined);
91
+ return;
92
+ }
93
+ const dtd = await DcmtTypeListCacheService.GetAsync(focusedItem.tid);
94
+ setDtdFocused(dtd);
95
+ };
96
+ loadDtdFocused();
97
+ }, [focusedItem?.tid]);
98
+ const openTaskFormHandler = (onTaskCreated) => {
99
+ if (selectedItems.length > 1)
100
+ return;
101
+ const item = selectedItems.length === 1 ? selectedItems[0] : focusedItem;
102
+ if (item && item.tid && item.did) {
103
+ const createTaskFromDocumentOrWorkItem = async () => {
104
+ try {
105
+ const dtd = await DcmtTypeListCacheService.GetWithNotGrantedAsync(item.tid, item?.did);
106
+ if (dtd) {
107
+ const isWorkItem = isApprovalWorkflowView(dtd);
108
+ if (item.tid === undefined || item.did === undefined) {
109
+ console.error("TID or DID is undefined for the selected item.");
110
+ return;
111
+ }
112
+ const name = `${dtd.name ?? '-'} (DID: ${item.did})`;
113
+ onTaskCreateRequest?.(isWorkItem
114
+ ? { workItem: { tid: item.tid, did: item.did, name } }
115
+ : { document: { tid: item.tid, did: item.did, name } }, onTaskCreated);
116
+ }
117
+ }
118
+ catch (error) {
119
+ console.error("Error fetching data:", error);
120
+ }
121
+ };
122
+ createTaskFromDocumentOrWorkItem();
123
+ }
124
+ };
125
+ const { operationItems, renderFloatingBar, renderDcmtOperations, features } = useDocumentOperations({
126
+ context: SearchResultContext.MASTER_DETAIL,
127
+ documentData: {
128
+ dtd: dtdFocused,
129
+ selectedItems: selectedItems ? selectedItems.map(item => ({ TID: item.tid, DID: item.did, FILEEXT: item.fileExt })) : [],
130
+ focusedItem: focusedItem ? { TID: focusedItem.tid, DID: focusedItem.did, FILEEXT: focusedItem.fileExt } : undefined,
131
+ currentSearchResults: [],
132
+ currentMetadataValues: [],
133
+ allUsers: [],
134
+ // searchResult: selectedSearchResult,
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
+ },
145
+ dcmtUtility: {
146
+ approvalVID: dcmtUtility?.approvalVID,
147
+ dcmtDataRowForCicoStatus: focusedItemFormData, // Passa i metadata trasformati del focusedItem per le operazioni di CICO
148
+ selectedDcmtSearchResultRelations: dcmtUtility?.selectedDcmtSearchResultRelations,
149
+ dcmtTIDHasDetailRelations: dcmtUtility?.dcmtTIDHasDetailRelations,
150
+ dcmtTIDHasMasterRelations: dcmtUtility?.dcmtTIDHasMasterRelations,
151
+ updateCurrentDcmt: onRefreshSearch,
152
+ onCloseDcmtForm: dcmtUtility?.onCloseDcmtForm,
153
+ onRefreshBlogForm: dcmtUtility?.onRefreshBlogForm,
154
+ onRefreshPreviewForm: onRefreshSearch,
155
+ taskFormDialogComponent: dcmtUtility?.taskFormDialogComponent,
156
+ s4TViewerDialogComponent: dcmtUtility?.s4TViewerDialogComponent
157
+ },
158
+ },
159
+ uiConfig: {
160
+ floatingBarContainerRef,
161
+ openS4TViewer,
162
+ showDcmtFormSidebar: true,
163
+ openDcmtFormAsModal: true,
164
+ allowFloatingBar: false,
165
+ enablePinIcons: false,
166
+ allowRelations: true,
167
+ inputDcmtFormLayoutMode: LayoutModes.Update,
168
+ },
169
+ tasks: {
170
+ allTasks: allTasks,
171
+ getAllTasks: getAllTasks,
172
+ deleteTaskByIdsCallback: deleteTaskByIdsCallback,
173
+ addTaskCallback: addTaskCallback,
174
+ editTaskCallback: editTaskCallback
175
+ },
176
+ callbacks: {
177
+ // Refresh operations (data consistency)
178
+ /* onSavedAsyncCallback, */
179
+ // Workflow operations
180
+ /* onWFOperationCompleted, */
181
+ // Navigation
182
+ /* canNavigateHandler,
183
+ onNavigateHandler, */
184
+ handleNavigateToWGs,
185
+ handleNavigateToDossiers,
186
+ /* onReferenceClick, */
187
+ // Document forms/operations
188
+ /* openAddDocumentForm,
189
+ openCommentFormCallback,
190
+ onFileOpened,
191
+ passToArchiveCallback,
192
+ openWGsCopyMoveForm, */
193
+ onOpenS4TViewerRequest,
194
+ onOpenPdfEditorRequest,
195
+ // Task related
196
+ onTaskCreateRequest,
197
+ openTaskFormHandler,
198
+ onRefreshAfterAddDcmtToFavs,
199
+ },
200
+ });
26
201
  // Load dtdMaster when inputDcmts changes
27
202
  useEffect(() => {
28
203
  const loadDtdMaster = async () => {
@@ -53,6 +228,12 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
53
228
  setNoRelationsOnFirstLoad(true);
54
229
  }
55
230
  }, [isCheckingFirstLoad]);
231
+ const onItemContextMenu = useCallback((item, e) => {
232
+ if (!item.isDcmt)
233
+ return; // Show context menu only for document items
234
+ setContextMenuPosition({ x: e.clientX, y: e.clientY });
235
+ setContextMenuVisible(true);
236
+ }, []);
56
237
  // Show warning alert and navigate back when no relations found on first load
57
238
  useEffect(() => {
58
239
  if (noRelationsOnFirstLoad) {
@@ -97,10 +278,19 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
97
278
  ?
98
279
  _jsx(TMNothingToShow, { text: getTitle(), secondText: SDKUI_Localizator.NoDataToDisplay, icon: isForMaster ? _jsx(IconDetailDcmts, { fontSize: 96, transform: 'scale(-1, 1)' }) : _jsx(IconDetailDcmts, { fontSize: 96 }) })
99
280
  :
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]);
281
+ _jsxs("div", { ref: floatingBarContainerRef, style: { width: "100%", height: "100%" }, onContextMenu: (e) => {
282
+ // Mostra context menu anche sullo spazio bianco (quando non si clicca su un item)
283
+ e.preventDefault();
284
+ setContextMenuPosition({ x: e.clientX, y: e.clientY });
285
+ setContextMenuVisible(true);
286
+ }, children: [_jsx(TMRelationViewerWrapper, { refreshKey: refreshKey, inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, showZeroDcmts: showZeroDcmts,
287
+ // customItemRender={customItemRender}
288
+ allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound, onItemContextMenu: onItemContextMenu, focusedItemFormData: focusedItemFormData }), _jsx(TMContextMenu, { items: operationItems, externalControl: {
289
+ visible: contextMenuVisible,
290
+ position: contextMenuPosition,
291
+ onClose: () => setContextMenuVisible(false)
292
+ } })] }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound, onItemContextMenu, contextMenuVisible, contextMenuPosition, refreshKey, focusedItemFormData]);
293
+ const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { refreshKey: refreshKey, 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 }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshAfterAddDcmtToFavs, refreshKey]);
104
294
  const initialPanelDimensions = {
105
295
  'tmTreeView': { width: '50%', height: '100%' },
106
296
  'tmFormOrResult': { width: '50%', height: '100%' },
@@ -177,7 +367,28 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
177
367
  toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
178
368
  }
179
369
  ], [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 }) }) })] }));
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] })] }));
181
392
  };
182
393
  export default TMMasterDetailDcmts;
183
394
  /**
@@ -186,7 +397,7 @@ export default TMMasterDetailDcmts;
186
397
  * - Panel visibility toggling
187
398
  * - Focus delay handling
188
399
  */
189
- const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound }) => {
400
+ const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound, onItemContextMenu, focusedItemFormData }) => {
190
401
  const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
191
402
  // Handle focused item changes with panel visibility management
192
403
  const handleFocusedItemChanged = useCallback((item) => {
@@ -205,15 +416,25 @@ const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndic
205
416
  setToolbarButtonVisibility('tmDcmtForm', false);
206
417
  }
207
418
  }, [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 }));
419
+ const onContextMenu = useCallback((item, e) => {
420
+ // Ferma la propagazione per evitare che l'evento arrivi al div contenitore
421
+ // (che ha il suo handler per il context menu sullo spazio bianco)
422
+ e.stopPropagation();
423
+ handleFocusedItemChanged(item);
424
+ // Il setTimeout è necessario per permettere a React di completare il re-render
425
+ // dopo il cambio di focus (handleFocusedItemChanged aggiorna stato e visibilità pannelli).
426
+ // Senza il delay, il context menu potrebbe mostrare opzioni basate sul vecchio stato.
427
+ setTimeout(() => {
428
+ onItemContextMenu?.(item, e);
429
+ }, 100);
430
+ }, [onItemContextMenu, handleFocusedItemChanged]);
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 }, refreshKey));
209
432
  };
210
- const TMFormOrResultWrapper = ({ deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
433
+ const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid }) => {
211
434
  const { setPanelVisibilityById } = useTMPanelManagerContext();
212
435
  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 }) }));
436
+ _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: {
437
+ onRefreshSearchAsyncDatagrid,
438
+ } }, refreshKey) :
439
+ _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 }, refreshKey) }));
219
440
  };
@@ -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