@topconsultnpm/sdkui-react 6.20.0 → 6.21.0-dev1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +7 -1
- package/lib/components/base/TMTreeView.d.ts +2 -1
- package/lib/components/base/TMTreeView.js +8 -3
- package/lib/components/base/TMWaitPanel.js +6 -5
- package/lib/components/choosers/TMUserChooser.js +3 -1
- package/lib/components/features/archive/TMArchive.d.ts +1 -1
- package/lib/components/features/archive/TMArchive.js +2 -2
- package/lib/components/features/documents/TMDcmtBlog.d.ts +1 -0
- package/lib/components/features/documents/TMDcmtBlog.js +2 -1
- package/lib/components/features/documents/TMDcmtForm.d.ts +42 -34
- package/lib/components/features/documents/TMDcmtForm.js +282 -641
- package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +34 -0
- package/lib/components/features/documents/TMDcmtFormActionButtons.js +124 -0
- package/lib/components/features/documents/TMFileUploader.d.ts +1 -1
- package/lib/components/features/documents/TMFileUploader.js +3 -3
- package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +27 -2
- package/lib/components/features/documents/TMMasterDetailDcmts.js +239 -18
- package/lib/components/features/documents/TMRelationViewer.d.ts +12 -1
- package/lib/components/features/documents/TMRelationViewer.js +48 -10
- package/lib/components/features/search/TMSearch.d.ts +3 -2
- package/lib/components/features/search/TMSearch.js +3 -3
- package/lib/components/features/search/TMSearchResult.d.ts +28 -26
- package/lib/components/features/search/TMSearchResult.js +350 -486
- package/lib/components/features/tasks/TMTaskForm.d.ts +2 -1
- package/lib/components/features/tasks/TMTaskForm.js +2 -2
- package/lib/helper/checkinCheckoutManager.d.ts +1 -1
- package/lib/helper/checkinCheckoutManager.js +25 -6
- package/lib/hooks/useCheckInOutOperations.d.ts +7 -6
- package/lib/hooks/useCheckInOutOperations.js +9 -16
- package/lib/hooks/useDcmtOperations.d.ts +3 -2
- package/lib/hooks/useDcmtOperations.js +2 -2
- package/lib/hooks/useDocumentOperations.d.ts +140 -0
- package/lib/hooks/useDocumentOperations.js +1307 -0
- package/lib/hooks/useRelatedDocuments.d.ts +1 -1
- package/lib/ts/types.d.ts +2 -1
- package/lib/ts/types.js +1 -0
- package/package.json +2 -2
- package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +0 -11
- 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
|
-
|
|
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,
|
|
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) &&
|
|
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: () =>
|
|
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
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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 })),
|
|
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
|
-
|
|
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
|
-
|
|
215
|
-
}
|
|
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
|