@topconsultnpm/sdkui-react 6.20.0-t2 → 6.20.0-t3
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/base/TMPopUp.js +4 -0
- package/lib/components/base/TMTreeView.js +12 -8
- package/lib/components/choosers/TMDataListItemChooser.js +1 -1
- package/lib/components/choosers/TMDataListItemFields.js +1 -1
- package/lib/components/choosers/TMDataListItemPicker.d.ts +1 -0
- package/lib/components/choosers/TMDataListItemPicker.js +5 -1
- package/lib/components/choosers/TMUserChooser.js +1 -1
- package/lib/components/editors/TMMetadataValues.js +200 -40
- package/lib/components/editors/TMTextArea.d.ts +1 -0
- package/lib/components/editors/TMTextArea.js +6 -6
- package/lib/components/features/archive/TMArchive.d.ts +1 -0
- package/lib/components/features/archive/TMArchive.js +2 -2
- package/lib/components/features/documents/TMDcmtForm.d.ts +1 -0
- package/lib/components/features/documents/TMDcmtForm.js +16 -7
- package/lib/components/features/documents/TMFileUploader.d.ts +2 -0
- package/lib/components/features/documents/TMFileUploader.js +16 -8
- package/lib/components/features/documents/TMMasterDetailDcmts.js +25 -63
- package/lib/components/features/documents/TMRelationViewer.js +109 -40
- package/lib/components/features/search/TMSearchQueryPanel.js +3 -3
- package/lib/components/features/search/TMSearchResult.js +5 -13
- package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +1 -1
- package/lib/components/features/search/TMSearchResultsMenuItems.js +4 -16
- package/lib/components/features/search/TMSignatureInfoContent.js +10 -6
- package/lib/components/features/search/TMTreeSelector.js +1 -1
- package/lib/components/features/tasks/TMTaskFormUtils.js +1 -1
- package/lib/components/features/workflow/TMWorkflowPopup.js +9 -19
- package/lib/components/features/workflow/diagram/DiagramItemForm.d.ts +2 -0
- package/lib/components/features/workflow/diagram/DiagramItemForm.js +32 -25
- package/lib/components/features/workflow/diagram/RecipientList.d.ts +3 -1
- package/lib/components/features/workflow/diagram/RecipientList.js +13 -9
- package/lib/components/features/workflow/diagram/WFDiagram.js +29 -2
- package/lib/components/features/workflow/diagram/workflowHelpers.js +31 -19
- package/lib/components/grids/TMRecentsManager.js +1 -1
- package/lib/components/viewers/TMMidViewer.js +2 -1
- package/lib/components/viewers/TMTidViewer.js +2 -1
- package/lib/helper/SDKUI_Globals.d.ts +4 -0
- package/lib/helper/SDKUI_Globals.js +9 -1
- package/lib/helper/SDKUI_Localizator.d.ts +12 -4
- package/lib/helper/SDKUI_Localizator.js +104 -24
- package/lib/helper/TMUtils.d.ts +9 -41
- package/lib/helper/TMUtils.js +79 -167
- package/lib/hooks/useDataUserIdItem.js +2 -2
- package/package.json +2 -2
- package/lib/components/features/search/TMSignSettingsForm.d.ts +0 -9
- package/lib/components/features/search/TMSignSettingsForm.js +0 -621
|
@@ -1,7 +1,7 @@
|
|
|
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
3
|
import TMDcmtPreview from './TMDcmtPreview';
|
|
4
|
-
import { AccessLevels, AppModules, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, UserListCacheService, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import { AccessLevels, AccessLevelsEx, AppModules, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataDomains, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, UserListCacheService, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
5
5
|
import { WorkFlowApproveRejectPopUp, WorkFlowMoreInfoPopUp, WorkFlowOperationButtons, WorkFlowReAssignPopUp } from '../workflow/TMWorkflowPopup';
|
|
6
6
|
import { DownloadTypes, FormModes, DcmtOperationTypes } from '../../../ts';
|
|
7
7
|
import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
@@ -65,7 +65,7 @@ export var InvocationContext;
|
|
|
65
65
|
let abortControllerLocal = new AbortController();
|
|
66
66
|
;
|
|
67
67
|
//#endregion
|
|
68
|
-
const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, showHeader = true, onSaveRecents, layoutMode = LayoutModes.Update, showBackButton = true, onClose, onSavedAsyncCallback, TID, DID, formMode = FormModes.Update, canNext, canPrev, count, itemIndex, onNext, onPrev, allowNavigation = true, allowRelations = true, isClosable = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, showDcmtFormSidebar = true, invocationContext = InvocationContext.Default, titleModal, isModal = false, widthModal = "100%", heightModal = "100%", groupId, onWFOperationCompleted, onTaskCompleted, onTaskCreateRequest, inputFile = null, taskFormDialogComponent, moreInfoTasks, connectorFileSave = undefined, inputMids = [], openS4TViewer = false, onOpenS4TViewerRequest, s4TViewerDialogComponent, enableDragDropOverlay = false, openPdfEditor, passToSearch, isSharedDcmt = false, sharedSourceTID, sharedSourceDID, allowButtonsRefs = false, onReferenceClick, }) => {
|
|
68
|
+
const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, showHeader = true, onSaveRecents, layoutMode = LayoutModes.Update, showBackButton = true, onClose, onSavedAsyncCallback, TID, DID, formMode = FormModes.Update, canNext, canPrev, count, itemIndex, onNext, onPrev, allowNavigation = true, allowRelations = true, isClosable = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, showDcmtFormSidebar = true, invocationContext = InvocationContext.Default, titleModal, isModal = false, widthModal = "100%", heightModal = "100%", groupId, onWFOperationCompleted, onTaskCompleted, onTaskCreateRequest, inputFile = null, taskFormDialogComponent, moreInfoTasks, connectorFileSave = undefined, inputMids = [], openS4TViewer = false, onOpenS4TViewerRequest, s4TViewerDialogComponent, enableDragDropOverlay = false, onScanRequest, openPdfEditor, passToSearch, isSharedDcmt = false, sharedSourceTID, sharedSourceDID, allowButtonsRefs = false, onReferenceClick, }) => {
|
|
69
69
|
const { showHistory, showHistoryCallback, hideHistoryCallback, showCheckoutInformationForm, commentFormState, hideCommentFormCallback, showCheckoutInformationFormCallback, hideCheckoutInformationFormCallback, copyCheckoutPathToClipboardCallback, handleCheckOutCallback, handleCheckInCallback, refreshPreviewTrigger, showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, } = useCheckInOutOperations();
|
|
70
70
|
const [id, setID] = useState('');
|
|
71
71
|
const [showWaitPanelLocal, setShowWaitPanelLocal] = useState(false);
|
|
@@ -633,11 +633,15 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
|
|
|
633
633
|
const handlePassToSearch = useCallback(() => {
|
|
634
634
|
if (!passToSearch)
|
|
635
635
|
return;
|
|
636
|
+
if (fromDTD?.perm?.canSearch !== AccessLevelsEx.Yes && fromDTD?.perm?.canSearch !== AccessLevelsEx.Mixed) {
|
|
637
|
+
ShowAlert({ title: SDKUI_Localizator.PassToSearch, message: 'Non hai i permessi per effettuare la ricerca.', mode: 'warning', duration: 3000 });
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
636
640
|
const outputMids = formData
|
|
637
641
|
.filter(md => md.mid && md.mid > 100 && md.value && md.value.length > 0)
|
|
638
642
|
.map(md => ({ mid: md.mid, value: md.value }));
|
|
639
643
|
passToSearch(outputMids, TID);
|
|
640
|
-
}, [passToSearch, formData, TID]);
|
|
644
|
+
}, [passToSearch, formData, TID, fromDTD?.perm?.canSearch]);
|
|
641
645
|
const isPreviewDisabled = useMemo(() => layoutMode === LayoutModes.Ark && fromDTD?.archiveConstraint === ArchiveConstraints.OnlyMetadata, [layoutMode, fromDTD?.archiveConstraint]);
|
|
642
646
|
const isBoardDisabled = useMemo(() => layoutMode !== LayoutModes.Update || fromDTD?.hasBlog !== 1, [layoutMode, fromDTD?.hasBlog]);
|
|
643
647
|
const isSysMetadataDisabled = useMemo(() => layoutMode !== LayoutModes.Update, [layoutMode]);
|
|
@@ -1275,7 +1279,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
|
|
|
1275
1279
|
]);
|
|
1276
1280
|
const tmBlog = useMemo(() => _jsx(TMDcmtBlog, { tid: TID, did: DID, allTasks: allTasks, fetchBlogDataTrigger: refreshBlogTrigger, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), [TID, DID, allTasks, refreshBlogTrigger, handleNavigateToWGs, handleNavigateToDossiers]);
|
|
1277
1281
|
const tmSysMetadata = useMemo(() => _jsx(TMMetadataValues, { layoutMode: layoutMode, openChooserBySingleClick: !isOpenDistinctValues, TID: TID, isReadOnly: true, deviceType: deviceType, metadataValues: formData.filter(o => (o.mid != undefined && o.mid <= 100)), metadataValuesOrig: formData.filter(o => (o.mid != undefined && o.mid <= 100)), validationItems: [], inputMids: inputMids }), [TID, layoutMode, formData, deviceType, inputMids]);
|
|
1278
|
-
const tmDcmtPreview = useMemo(() => _jsx(TMDcmtPreviewWrapper, { currentDcmt: currentDcmt, dcmtFile: dcmtFile ?? inputFile, deviceType: deviceType, fromDTD: fromDTD, layoutMode: layoutMode, onFileUpload: (file) => { setDcmtFile(file); }, openPdfEditor: openPdfEditor, enableDragDropOverlay: enableDragDropOverlay }, refreshPreviewTrigger), [currentDcmt, dcmtFile, deviceType, fromDTD, layoutMode, inputFile, enableDragDropOverlay, setDcmtFile, openPdfEditor]);
|
|
1282
|
+
const tmDcmtPreview = useMemo(() => _jsx(TMDcmtPreviewWrapper, { currentDcmt: currentDcmt, dcmtFile: dcmtFile ?? inputFile, deviceType: deviceType, fromDTD: fromDTD, layoutMode: layoutMode, onFileUpload: (file) => { setDcmtFile(file); }, openPdfEditor: openPdfEditor, enableDragDropOverlay: enableDragDropOverlay, onScanRequest: onScanRequest }, refreshPreviewTrigger), [currentDcmt, dcmtFile, deviceType, fromDTD, layoutMode, inputFile, enableDragDropOverlay, setDcmtFile, onScanRequest, openPdfEditor]);
|
|
1279
1283
|
const tmWF = useMemo(() => {
|
|
1280
1284
|
if (isWFDataLoading) {
|
|
1281
1285
|
return (_jsx("div", { style: {
|
|
@@ -1745,7 +1749,12 @@ export const validateMetadataList = (mvdList = []) => {
|
|
|
1745
1749
|
return validationItems;
|
|
1746
1750
|
}, []);
|
|
1747
1751
|
};
|
|
1748
|
-
const isValidForValidation = (mvd) => {
|
|
1752
|
+
const isValidForValidation = (mvd) => {
|
|
1753
|
+
// I campi Computed non vanno validati (sono calcolati automaticamente)
|
|
1754
|
+
if (mvd.md?.dataDomain === MetadataDataDomains.Computed)
|
|
1755
|
+
return false;
|
|
1756
|
+
return mvd.mid > 99;
|
|
1757
|
+
};
|
|
1749
1758
|
const validateRequiredField = (mvd, value, validationItems) => {
|
|
1750
1759
|
if (mvd.isRequired === '1' && !value.trim()) {
|
|
1751
1760
|
const message = SDKUI_Localizator.RequiredField;
|
|
@@ -1772,12 +1781,12 @@ const WfButtonStateHandler = ({ isWFDisabled }) => {
|
|
|
1772
1781
|
}, [isWFDisabled, setToolbarButtonDisabled]);
|
|
1773
1782
|
return null; // Non renderizza elementi nel DOM
|
|
1774
1783
|
};
|
|
1775
|
-
const TMDcmtPreviewWrapper = ({ currentDcmt, layoutMode, fromDTD, dcmtFile, deviceType, isVisible, onFileUpload, openPdfEditor, enableDragDropOverlay = false }) => {
|
|
1784
|
+
const TMDcmtPreviewWrapper = ({ currentDcmt, layoutMode, fromDTD, dcmtFile, deviceType, isVisible, onFileUpload, openPdfEditor, enableDragDropOverlay = false, onScanRequest }) => {
|
|
1776
1785
|
const { setPanelVisibilityById, toggleMaximize, isResizingActive, countVisibleLeafPanels, panelVisibility } = useTMPanelManagerContext();
|
|
1777
1786
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
1778
1787
|
return (layoutMode === LayoutModes.Update ?
|
|
1779
1788
|
_jsx(TMDcmtPreview, { isVisible: isVisible, onClosePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('tmDcmtPreview', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => toggleMaximize("tmDcmtPreview") : undefined, dcmtData: currentDcmt, isResizingActive: isResizingActive }) :
|
|
1780
|
-
_jsx(TMFileUploader, { fromDTD: fromDTD, onFileUpload: onFileUpload, openPdfEditor: openPdfEditor, onClose: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('tmDcmtPreview', false) : undefined, isRequired: fromDTD?.archiveConstraint === ArchiveConstraints.ContentCompulsory && dcmtFile === null, defaultBlob: dcmtFile, deviceType: deviceType, isResizingActive: isResizingActive, enableDragDropOverlay: panelVisibility['tmDcmtPreview'] && enableDragDropOverlay }));
|
|
1789
|
+
_jsx(TMFileUploader, { fromDTD: fromDTD, onFileUpload: onFileUpload, openPdfEditor: openPdfEditor, onClose: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('tmDcmtPreview', false) : undefined, isRequired: fromDTD?.archiveConstraint === ArchiveConstraints.ContentCompulsory && dcmtFile === null, defaultBlob: dcmtFile, deviceType: deviceType, isResizingActive: isResizingActive, enableDragDropOverlay: panelVisibility['tmDcmtPreview'] && enableDragDropOverlay, onScanRequest: onScanRequest }));
|
|
1781
1790
|
};
|
|
1782
1791
|
const Ribbon = styled.div `
|
|
1783
1792
|
font-size: 0.85rem;
|
|
@@ -6,12 +6,14 @@ interface ITMFileUploader {
|
|
|
6
6
|
onFileUpload?: (file: File | null) => void;
|
|
7
7
|
openPdfEditor?: (fromDTD?: DcmtTypeDescriptor, file?: File | null, handleFile?: (file: File) => void) => void;
|
|
8
8
|
onClose?: () => void;
|
|
9
|
+
onScanRequest?: (onFileScanned: (file: File) => void) => void;
|
|
9
10
|
isRequired?: boolean;
|
|
10
11
|
defaultBlob?: File | null;
|
|
11
12
|
deviceType?: DeviceType;
|
|
12
13
|
isResizingActive?: boolean;
|
|
13
14
|
showTMPanel?: boolean;
|
|
14
15
|
enableDragDropOverlay?: boolean;
|
|
16
|
+
showScannerIcon?: boolean;
|
|
15
17
|
}
|
|
16
18
|
declare const TMFileUploader: React.FC<ITMFileUploader>;
|
|
17
19
|
export default TMFileUploader;
|
|
@@ -1,7 +1,7 @@
|
|
|
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
3
|
import styled from 'styled-components';
|
|
4
|
-
import { IconFolderOpen, IconScanner, SDKUI_Localizator, formatBytes, IconClear, extensionHandler, IconCloseOutline, IconMenuVertical, TMCommandsContextMenu, IconEdit } from '../../../helper';
|
|
4
|
+
import { IconFolderOpen, IconScanner, SDKUI_Localizator, formatBytes, IconClear, extensionHandler, IconCloseOutline, IconMenuVertical, TMCommandsContextMenu, IconEdit, isPdfEditorAvailable, SDKUI_Globals } from '../../../helper';
|
|
5
5
|
import { useBetaFeatures } from '../../../hooks/useBetaFeatures';
|
|
6
6
|
import usePreventFileDrop from '../../../hooks/usePreventFileDrop';
|
|
7
7
|
import { FileExtensionHandler } from '../../../ts';
|
|
@@ -13,8 +13,17 @@ import TMTooltip from '../../base/TMTooltip';
|
|
|
13
13
|
import { TMFileViewer, StyledHeaderIcon } from './TMDcmtPreview';
|
|
14
14
|
import TMPanel from '../../base/TMPanel';
|
|
15
15
|
import TMDragDropOverlay from './TMDragDropOverlay';
|
|
16
|
-
|
|
17
|
-
const
|
|
16
|
+
// Helper per verificare se la licenza scanner è disponibile
|
|
17
|
+
const isScannerLicenseConfigured = () => {
|
|
18
|
+
try {
|
|
19
|
+
const scannerLicense = SDKUI_Globals.userSettings.advancedSettings.scannerLicense;
|
|
20
|
+
return scannerLicense && scannerLicense.trim() !== '';
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const TMFileUploader = ({ fromDTD, deviceType = DeviceType.DESKTOP, onClose, onFileUpload, openPdfEditor, onScanRequest, isRequired = false, defaultBlob = null, isResizingActive, showTMPanel = true, enableDragDropOverlay = false, showScannerIcon = true }) => {
|
|
18
27
|
const isBetaFeaturesEnabled = useBetaFeatures();
|
|
19
28
|
const [dragOver, setDragOver] = useState(false);
|
|
20
29
|
const [uploadedFile, setUploadedFile] = useState(defaultBlob);
|
|
@@ -87,20 +96,19 @@ const TMFileUploader = ({ fromDTD, deviceType = DeviceType.DESKTOP, onClose, onF
|
|
|
87
96
|
document.getElementById('fileInput')?.click();
|
|
88
97
|
}, []);
|
|
89
98
|
let content = !uploadedFile ?
|
|
90
|
-
_jsxs("div", { style: { display: 'flex', gap: 10, width: '100%', height: '100%' }, children: [_jsx(HiddenInput, { id: "fileInput", type: "file", onChange: handleInputChange }), _jsxs(UploadContainer, { ref: uploaderRef, tabIndex: 0, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, style: { backgroundColor: dragOver ? '#76b1e6' : 'white' }, onDoubleClick: browseHandler, "$isRequired": isRequired, children: [_jsxs("div", { style: { display: 'flex', gap: '10px', flexDirection: 'column', position: 'absolute', right: 5, top: 5 }, children: [_jsx(TMButton, { btnStyle: 'icon', caption: 'Sfoglia', color: isRequired && !uploadedFile ? 'error' : 'primary', onClick: browseHandler, icon: _jsx(IconFolderOpen, { fontSize: 22 }) }), isBetaFeaturesEnabled && _jsx(TMButton, { btnStyle: 'icon', caption: 'Scanner', color: 'primary', onClick: () => { ShowAlert({ message: 'Funzionalità scanner in
|
|
99
|
+
_jsxs("div", { style: { display: 'flex', gap: 10, width: '100%', height: '100%' }, children: [_jsx(HiddenInput, { id: "fileInput", type: "file", onChange: handleInputChange }), _jsxs(UploadContainer, { ref: uploaderRef, tabIndex: 0, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, style: { backgroundColor: dragOver ? '#76b1e6' : 'white' }, onDoubleClick: browseHandler, "$isRequired": isRequired, children: [_jsxs("div", { style: { display: 'flex', gap: '10px', flexDirection: 'column', position: 'absolute', right: 5, top: 5 }, children: [_jsx(TMButton, { btnStyle: 'icon', caption: 'Sfoglia', color: isRequired && !uploadedFile ? 'error' : 'primary', onClick: browseHandler, icon: _jsx(IconFolderOpen, { fontSize: 22 }) }), isBetaFeaturesEnabled && showScannerIcon && isScannerLicenseConfigured() && onScanRequest && _jsx(TMButton, { btnStyle: 'icon', caption: 'Scanner', color: 'primary', onClick: () => { onScanRequest((file) => { onFileUpload?.(file); }); }, icon: _jsx(IconScanner, { fontSize: 22 }) }), isBetaFeaturesEnabled && showScannerIcon && isScannerLicenseConfigured() && !onScanRequest && _jsx(TMButton, { btnStyle: 'icon', caption: 'Scanner', color: 'primary', onClick: () => { ShowAlert({ message: 'Funzionalità scanner non disponibile in questo contesto.', mode: 'info', duration: 3000, title: 'Scanner' }); }, icon: _jsx(IconScanner, { fontSize: 22 }) })] }), _jsx("p", { style: { fontSize: '1.2rem', fontWeight: 'bold' }, children: deviceType === DeviceType.MOBILE ? 'Clicca per sfogliare il tuo file' : 'Trascina il tuo file o fai doppio click per sfogliarlo' }), isRequired && _jsxs("p", { style: { fontWeight: 'bold' }, children: [" ", SDKUI_Localizator.RequiredField, " "] })] })] }) :
|
|
91
100
|
_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 10, width: '100%', height: '100%' }, children: [_jsxs("div", { style: { backgroundColor: 'white', padding: '5px 10px', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: TMColors.primaryColor }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 5 }, children: [_jsx("p", { children: "File name:" }), _jsxs("div", { style: { fontWeight: 'bold' }, children: [fileName, " ", _jsxs("span", { children: [" ", ` (${formatBytes(fileSize)})`, " "] })] })] }), uploadedFile && _jsx(TMButton, { btnStyle: 'icon', color: 'error', caption: 'Pulisci', onClick: () => clearFile(true), icon: _jsx(IconClear, { fontSize: 22 }) })] }), extensionHandler(fileExt) === FileExtensionHandler.READY_TO_SHOW ? _jsx(TMFileViewer, { fileBlob: uploadedFile, isResizingActive: isResizingActive }) :
|
|
92
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})` })] }) })] });
|
|
93
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] }));
|
|
94
103
|
const toolbar = useMemo(() => {
|
|
95
|
-
|
|
96
|
-
return (_jsxs(_Fragment, { children: [(isPdfEditorLicensed && fileExt && fileExt.toLowerCase() === 'pdf') && (_jsx(TMCommandsContextMenu, { target: "#TMPanel-FileUploader-Commands-Header", menuItems: [
|
|
104
|
+
return (_jsxs(_Fragment, { children: [(isPdfEditorAvailable(fromDTD, fileExt) && openPdfEditor) && (_jsx(TMCommandsContextMenu, { target: "#TMPanel-FileUploader-Commands-Header", menuItems: [
|
|
97
105
|
{
|
|
98
106
|
icon: _jsx(IconEdit, {}),
|
|
99
107
|
text: 'PDF Editor',
|
|
100
|
-
onClick: () => openPdfEditor
|
|
108
|
+
onClick: () => openPdfEditor(fromDTD, uploadedFile, handleFile)
|
|
101
109
|
}
|
|
102
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, {}) }) }))] }));
|
|
103
|
-
}, [deviceType, onClose]);
|
|
111
|
+
}, [deviceType, fromDTD, onClose]);
|
|
104
112
|
return showTMPanel ? (_jsx(TMPanel, { ref: fileUploaderPanelRef, panelID: 'file-uploader-panel', title: SDKUI_Localizator.FileUpload, onBack: deviceType === DeviceType.MOBILE ? () => onClose?.() : undefined, toolbar: toolbar, children: innerContent })) : (innerContent);
|
|
105
113
|
};
|
|
106
114
|
const UploadContainer = styled.div `
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useMemo,
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import { DcmtTypeListCacheService, SDK_Localizator } from '@topconsultnpm/sdk-ts';
|
|
4
|
-
import styled from 'styled-components';
|
|
5
4
|
import TMRelationViewer from './TMRelationViewer';
|
|
6
5
|
import TMContextMenu from '../../NewComponents/ContextMenu/TMContextMenu';
|
|
7
|
-
import {
|
|
6
|
+
import { IconMultipleSelection, IconCheckFile, IconDetailDcmts, SDKUI_Localizator, IconMenuVertical, IconDataList, IconPreview, IconSearchCheck, IconBoard, IconDcmtTypeSys, IconShow, getMoreInfoTasksForDocument } from '../../../helper';
|
|
8
7
|
import { FormModes, SearchResultContext } from '../../../ts';
|
|
9
8
|
import { TMColors } from '../../../utils/theme';
|
|
9
|
+
import ShowAlert from '../../base/TMAlert';
|
|
10
10
|
import { DeviceType } from '../../base/TMDeviceProvider';
|
|
11
11
|
import { TMSaveFormButtonPrevious, TMSaveFormButtonNext } from '../../forms/TMSaveForm';
|
|
12
12
|
import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
|
|
@@ -14,56 +14,15 @@ import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/p
|
|
|
14
14
|
import TMSearchResult from '../search/TMSearchResult';
|
|
15
15
|
import TMDcmtForm from './TMDcmtForm';
|
|
16
16
|
import { TMNothingToShow } from './TMDcmtPreview';
|
|
17
|
-
import
|
|
18
|
-
const StyledNoRelationsOverlay = styled.div `
|
|
19
|
-
width: 100%;
|
|
20
|
-
height: 100%;
|
|
21
|
-
position: fixed;
|
|
22
|
-
top: 0;
|
|
23
|
-
left: 0;
|
|
24
|
-
z-index: 1501;
|
|
25
|
-
overflow: visible;
|
|
26
|
-
background-color: rgba(0, 0, 0, 0.5);
|
|
27
|
-
backdrop-filter: blur(8px);
|
|
28
|
-
`;
|
|
29
|
-
const StyledNoRelationsPanel = styled.div `
|
|
30
|
-
position: absolute;
|
|
31
|
-
top: 50%;
|
|
32
|
-
left: 50%;
|
|
33
|
-
transform: translate(-50%, -50%);
|
|
34
|
-
width: 400px;
|
|
35
|
-
background: white;
|
|
36
|
-
border-radius: 8px;
|
|
37
|
-
padding: 20px;
|
|
38
|
-
text-align: center;
|
|
39
|
-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
40
|
-
display: flex;
|
|
41
|
-
flex-direction: column;
|
|
42
|
-
align-items: center;
|
|
43
|
-
`;
|
|
44
|
-
const StyledNoRelationsTitle = styled.h2 `
|
|
45
|
-
margin: 0 0 20px 0;
|
|
46
|
-
font-size: 1.3em;
|
|
47
|
-
color: #333;
|
|
48
|
-
`;
|
|
49
|
-
const StyledNoRelationsMessage = styled.p `
|
|
50
|
-
color: #666;
|
|
51
|
-
font-size: 1em;
|
|
52
|
-
margin: 0 0 25px 0;
|
|
53
|
-
line-height: 1.4;
|
|
54
|
-
`;
|
|
17
|
+
import { Spinner } from '../..';
|
|
55
18
|
const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, appendMasterDcmts, onTaskCreateRequest }) => {
|
|
56
|
-
const [id, setID] = useState('');
|
|
57
19
|
const [focusedItem, setFocusedItem] = useState();
|
|
58
20
|
const [selectedItems, setSelectedItems] = useState([]);
|
|
59
21
|
const [showZeroDcmts, setShowZeroDcmts] = useState(false);
|
|
60
22
|
const [allowMultipleSelection, setAllowMultipleSelection] = useState(false);
|
|
61
23
|
const [dtdMaster, setDtdMaster] = useState();
|
|
62
|
-
const [
|
|
63
|
-
const [
|
|
64
|
-
// Ref to track if this is the first load (vs navigation with onPrev/onNext)
|
|
65
|
-
const isFirstLoadRef = useRef(true);
|
|
66
|
-
useEffect(() => { setID(genUniqueId()); }, []);
|
|
24
|
+
const [noRelationsOnFirstLoad, setNoRelationsOnFirstLoad] = useState(false);
|
|
25
|
+
const [isCheckingFirstLoad, setIsCheckingFirstLoad] = useState(true);
|
|
67
26
|
// Load dtdMaster when inputDcmts changes
|
|
68
27
|
useEffect(() => {
|
|
69
28
|
const loadDtdMaster = async () => {
|
|
@@ -82,23 +41,31 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
82
41
|
}, [inputDcmts?.length, inputDcmts?.[0]?.TID, isForMaster]);
|
|
83
42
|
const handleFocusedItemChanged = useCallback((item) => {
|
|
84
43
|
setFocusedItem(item);
|
|
85
|
-
// When data is loaded and an item is focused, mark as no longer first load
|
|
86
44
|
if (item) {
|
|
87
|
-
|
|
45
|
+
setIsCheckingFirstLoad(false);
|
|
88
46
|
}
|
|
89
47
|
}, []);
|
|
90
48
|
const handleSelectedItemsChanged = useCallback((items) => {
|
|
91
49
|
setSelectedItems(items);
|
|
92
50
|
}, []);
|
|
93
51
|
const handleNoRelationsFound = useCallback(() => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
setShowNoRelationsModal(true);
|
|
97
|
-
setShouldGoBackOnClose(true);
|
|
52
|
+
if (isCheckingFirstLoad) {
|
|
53
|
+
setNoRelationsOnFirstLoad(true);
|
|
98
54
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
55
|
+
}, [isCheckingFirstLoad]);
|
|
56
|
+
// Show warning alert and navigate back when no relations found on first load
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (noRelationsOnFirstLoad) {
|
|
59
|
+
setNoRelationsOnFirstLoad(false);
|
|
60
|
+
ShowAlert({
|
|
61
|
+
message: SDKUI_Localizator.RelatedDcmtsNotFound,
|
|
62
|
+
title: SDKUI_Localizator.RelationsNotFound,
|
|
63
|
+
duration: 3000,
|
|
64
|
+
mode: 'warning',
|
|
65
|
+
});
|
|
66
|
+
onBack?.();
|
|
67
|
+
}
|
|
68
|
+
}, [noRelationsOnFirstLoad, onBack]);
|
|
102
69
|
const commandsMenuItems = [
|
|
103
70
|
{
|
|
104
71
|
icon: _jsx(IconMultipleSelection, { color: allowMultipleSelection ? TMColors.tertiary : TMColors.text_normal }),
|
|
@@ -123,7 +90,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
123
90
|
}
|
|
124
91
|
}
|
|
125
92
|
];
|
|
126
|
-
const toolbar = _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [allowMultipleSelection && _jsx("p", { style: { color: TMColors.colorHeader, textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${selectedItems.length} selezionati` }), allowNavigation && canPrev != undefined && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', iconColor: 'white', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), allowNavigation && canNext != undefined && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', iconColor: 'white', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(TMContextMenu, { items: commandsMenuItems, trigger: 'left', children: _jsx(IconMenuVertical, { color: 'white', cursor: 'pointer' }) })] });
|
|
93
|
+
const toolbar = _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [allowMultipleSelection && _jsx("p", { style: { color: TMColors.colorHeader, textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${selectedItems.filter(item => item.isDcmt).length} selezionati` }), allowNavigation && canPrev != undefined && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', iconColor: 'white', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), allowNavigation && canNext != undefined && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', iconColor: 'white', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(TMContextMenu, { items: commandsMenuItems, trigger: 'left', children: _jsx(IconMenuVertical, { color: 'white', cursor: 'pointer' }) })] });
|
|
127
94
|
const getTitle = () => isForMaster ? `${SDKUI_Localizator.DcmtsMaster} - ${dtdMaster?.nameLoc}` : SDKUI_Localizator.DcmtsDetail;
|
|
128
95
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
129
96
|
const tmTreeView = useMemo(() => _jsx(_Fragment, { children: !inputDcmts || inputDcmts.length === 0
|
|
@@ -210,12 +177,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
210
177
|
toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
|
|
211
178
|
}
|
|
212
179
|
], [tmTreeView, tmFormOrResult, focusedItem?.isDcmt, dtdMaster]);
|
|
213
|
-
return (_jsxs(
|
|
214
|
-
setShowNoRelationsModal(false);
|
|
215
|
-
if (shouldGoBackOnClose) {
|
|
216
|
-
onBack?.();
|
|
217
|
-
}
|
|
218
|
-
}, btnStyle: "normal" })] }) }))] }));
|
|
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 }) }) })] }));
|
|
219
181
|
};
|
|
220
182
|
export default TMMasterDetailDcmts;
|
|
221
183
|
/**
|
|
@@ -399,7 +399,8 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
399
399
|
/**
|
|
400
400
|
* Helper function to set up initial tree expansion state.
|
|
401
401
|
* Called after all data is loaded but before setTreeData.
|
|
402
|
-
* Ensures: root container expanded, first document expanded with isRoot=true (for focus),
|
|
402
|
+
* Ensures: root container expanded, first document expanded with isRoot=true (for focus),
|
|
403
|
+
* first correlation folder expanded ONLY if it's the only one (single correlation type)
|
|
403
404
|
* Returns a NEW tree with the modifications (immutable approach)
|
|
404
405
|
*/
|
|
405
406
|
const setupInitialTreeExpansion = (tree) => {
|
|
@@ -426,9 +427,10 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
426
427
|
expanded: true,
|
|
427
428
|
isRoot: true
|
|
428
429
|
};
|
|
429
|
-
// 3. Expand first correlation folder
|
|
430
|
+
// 3. Expand first correlation folder ONLY if there's exactly one
|
|
430
431
|
const docItems = newFirstDoc.items;
|
|
431
|
-
|
|
432
|
+
const containerChildren = docItems?.filter(child => child.isContainer) ?? [];
|
|
433
|
+
if (containerChildren.length === 1 && docItems && docItems.length > 0 && docItems[0].isContainer) {
|
|
432
434
|
const newFirstCorrelation = { ...docItems[0], expanded: true };
|
|
433
435
|
newFirstDoc = {
|
|
434
436
|
...newFirstDoc,
|
|
@@ -442,10 +444,13 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
442
444
|
};
|
|
443
445
|
}
|
|
444
446
|
else if (firstDocOrContainer.isContainer) {
|
|
445
|
-
// First item is a container (correlation folder)
|
|
447
|
+
// First item is a container (correlation folder)
|
|
448
|
+
// Count how many sibling containers there are
|
|
449
|
+
const siblingContainers = firstRootItems.filter(child => child.isContainer);
|
|
450
|
+
const shouldExpand = siblingContainers.length === 1;
|
|
446
451
|
let newFirstCorrelation = {
|
|
447
452
|
...firstDocOrContainer,
|
|
448
|
-
expanded:
|
|
453
|
+
expanded: shouldExpand
|
|
449
454
|
};
|
|
450
455
|
// Find first document inside this container and mark for focus
|
|
451
456
|
const containerItems = newFirstCorrelation.items;
|
|
@@ -517,8 +522,25 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
517
522
|
}
|
|
518
523
|
}
|
|
519
524
|
}
|
|
520
|
-
// Aggiungi i master come root
|
|
521
|
-
|
|
525
|
+
// Aggiungi i master come root, raggruppando per TID e relationId
|
|
526
|
+
for (const masterContainer of masterDocs) {
|
|
527
|
+
const existingContainer = tree.find(c => c.tid === masterContainer.tid && c.relationId === masterContainer.relationId && c.isContainer);
|
|
528
|
+
if (existingContainer) {
|
|
529
|
+
// Merge documents into existing container, deduplicating by DID
|
|
530
|
+
const existingItems = existingContainer.items ?? [];
|
|
531
|
+
const existingDIDs = new Set(existingItems.map(item => item.did));
|
|
532
|
+
const newItems = (masterContainer.items ?? []).filter(item => !existingDIDs.has(item.did));
|
|
533
|
+
existingContainer.items = [...existingItems, ...newItems];
|
|
534
|
+
existingContainer.itemsCount = existingContainer.items.length;
|
|
535
|
+
existingContainer.isZero = existingContainer.items.length === 0;
|
|
536
|
+
if (masterContainer.searchResult) {
|
|
537
|
+
existingContainer.searchResult = [...(existingContainer.searchResult ?? []), ...masterContainer.searchResult];
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
tree.push(masterContainer);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
522
544
|
}
|
|
523
545
|
// ========================================================================
|
|
524
546
|
// MODALITÀ STANDARD (detail o master invertito)
|
|
@@ -530,22 +552,53 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
530
552
|
: await getDetailDcmtsAsync(dcmt.TID, dcmt.DID, maxDepthLevel);
|
|
531
553
|
// Se showMainDocument è false, mostra i container dei dettagli direttamente sotto il container principale
|
|
532
554
|
if (!showMainDocument) {
|
|
533
|
-
//
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
555
|
+
// Check if a container for this TID already exists in the tree
|
|
556
|
+
const existingContainer = tree.find(c => c.tid === dcmt.TID && c.isContainer);
|
|
557
|
+
if (existingContainer) {
|
|
558
|
+
// Merge relatedDocs into existing container, grouping sub-containers by TID+relationId
|
|
559
|
+
const existingItems = existingContainer.items ?? [];
|
|
560
|
+
for (const relDoc of relatedDocs) {
|
|
561
|
+
const existingSub = existingItems.find(s => s.tid === relDoc.tid && s.relationId === relDoc.relationId && s.isContainer);
|
|
562
|
+
if (existingSub) {
|
|
563
|
+
// Merge documents into existing sub-container, deduplicating by DID
|
|
564
|
+
const subItems = existingSub.items ?? [];
|
|
565
|
+
const existingDIDs = new Set(subItems.map(item => item.did));
|
|
566
|
+
const newItems = (relDoc.items ?? []).filter(item => !existingDIDs.has(item.did));
|
|
567
|
+
existingSub.items = [...subItems, ...newItems];
|
|
568
|
+
existingSub.itemsCount = existingSub.items.length;
|
|
569
|
+
existingSub.isZero = existingSub.items.length === 0;
|
|
570
|
+
if (relDoc.searchResult) {
|
|
571
|
+
existingSub.searchResult = [...(existingSub.searchResult ?? []), ...relDoc.searchResult];
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
existingItems.push(relDoc);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
existingContainer.items = existingItems;
|
|
579
|
+
existingContainer.itemsCount = existingItems.length;
|
|
580
|
+
if (result) {
|
|
581
|
+
existingContainer.searchResult = [...(existingContainer.searchResult ?? []), result];
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
// Create type container that contains detail containers directly
|
|
586
|
+
const typeContainer = {
|
|
587
|
+
key: `${isForMaster ? 'detail' : 'master'}-type-${dcmt.TID}-${containerGUID}`,
|
|
588
|
+
name: labelMainContainer || result?.fromName || dtd?.name || `TID: ${dcmt.TID}`,
|
|
589
|
+
tid: dcmt.TID,
|
|
590
|
+
dtd,
|
|
591
|
+
isContainer: true,
|
|
592
|
+
isLoaded: true,
|
|
593
|
+
isZero: false,
|
|
594
|
+
searchResult: result ? [result] : [],
|
|
595
|
+
items: relatedDocs, // Directly show detail containers
|
|
596
|
+
itemsCount: relatedDocs.length,
|
|
597
|
+
expanded: false,
|
|
598
|
+
hidden: false
|
|
599
|
+
};
|
|
600
|
+
tree.push(typeContainer);
|
|
601
|
+
}
|
|
549
602
|
}
|
|
550
603
|
else {
|
|
551
604
|
// MODALITÀ ORIGINALE: mostra il documento master come nodo intermedio
|
|
@@ -567,22 +620,35 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
567
620
|
items: relatedDocs,
|
|
568
621
|
itemsCount: relatedDocs.length
|
|
569
622
|
};
|
|
570
|
-
//
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
623
|
+
// Check if a type container for this TID already exists in the tree
|
|
624
|
+
const existingContainer = tree.find(c => c.tid === dcmt.TID && c.isContainer);
|
|
625
|
+
if (existingContainer) {
|
|
626
|
+
// Add document to existing container
|
|
627
|
+
const existingItems = existingContainer.items ?? [];
|
|
628
|
+
existingContainer.items = [...existingItems, docNode];
|
|
629
|
+
existingContainer.itemsCount = existingContainer.items.length;
|
|
630
|
+
if (result) {
|
|
631
|
+
existingContainer.searchResult = [...(existingContainer.searchResult ?? []), result];
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
else {
|
|
635
|
+
// Create type container with unique key
|
|
636
|
+
const typeContainer = {
|
|
637
|
+
key: `${isForMaster ? 'detail' : 'master'}-type-${dcmt.TID}-${containerGUID}`,
|
|
638
|
+
name: labelMainContainer || result?.fromName || dtd?.name || `TID: ${dcmt.TID}`,
|
|
639
|
+
tid: dcmt.TID,
|
|
640
|
+
dtd,
|
|
641
|
+
isContainer: true,
|
|
642
|
+
isLoaded: true,
|
|
643
|
+
isZero: false, // Type container is never zero (contains documents)
|
|
644
|
+
searchResult: result ? [result] : [],
|
|
645
|
+
items: [docNode],
|
|
646
|
+
itemsCount: 1,
|
|
647
|
+
expanded: false,
|
|
648
|
+
hidden: false
|
|
649
|
+
};
|
|
650
|
+
tree.push(typeContainer);
|
|
651
|
+
}
|
|
586
652
|
}
|
|
587
653
|
}
|
|
588
654
|
// Update progress counter
|
|
@@ -1012,7 +1078,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1012
1078
|
const metadataContent = customDocumentContent
|
|
1013
1079
|
? customDocumentContent(item, defaultMetadataContent || _jsx(_Fragment, {}))
|
|
1014
1080
|
: defaultMetadataContent;
|
|
1015
|
-
return (_jsxs("div", { onDoubleClick: handleDoubleClick, style: documentStyle, children: [item.did && showCurrentDcmtIndicator && item.did ===
|
|
1081
|
+
return (_jsxs("div", { onDoubleClick: handleDoubleClick, style: documentStyle, children: [item.did && item.tid && showCurrentDcmtIndicator && inputDcmts?.some(d => d.DID === item.did && d.TID === item.tid) ? _jsx(IconBackhandIndexPointingRight, { fontSize: 22, overflow: 'visible' }) : _jsx(_Fragment, {}), item.values && (_jsx(TMDcmtIcon, { tid: item.values?.TID?.value, did: item.values?.DID?.value, fileExtension: item.values?.FILEEXT?.value, fileCount: item.values?.FILECOUNT?.value, isLexProt: item.values?.IsLexProt?.value, isMail: item.values?.ISMAIL?.value, isShared: item.values?.ISSHARED?.value, isSigned: item.values?.ISSIGNED?.value, downloadMode: 'openInNewWindow' })), metadataContent] }));
|
|
1016
1082
|
}, [onDocumentDoubleClick, showCurrentDcmtIndicator, inputDcmts, customMainContainerContent, customDocumentStyle, customDocumentContent, showMetadataNames, showMainDocument]);
|
|
1017
1083
|
/**
|
|
1018
1084
|
* Wrapper renderer that handles custom rendering if provided
|
|
@@ -1059,6 +1125,9 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1059
1125
|
return _jsx("div", { style: { padding: '20px', textAlign: 'center' }, children: _jsx(TMWaitPanel, { title: 'Caricamento documenti dettaglio', showPrimary: true, textPrimary: waitPanelTextPrimary, valuePrimary: waitPanelValuePrimary, maxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); } }) });
|
|
1060
1126
|
}
|
|
1061
1127
|
if (mergedTreeData.length === 0) {
|
|
1128
|
+
// If parent handles no-relations via callback, render nothing to avoid UI flash
|
|
1129
|
+
if (onNoRelationsFound)
|
|
1130
|
+
return null;
|
|
1062
1131
|
return _jsx("div", { style: { padding: '20px', textAlign: 'center', color: '#666' }, children: "Nessuna relazione disponibile." });
|
|
1063
1132
|
}
|
|
1064
1133
|
return (_jsxs(_Fragment, { children: [_jsx(TMTreeView, { dataSource: mergedTreeData, itemRender: finalItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: handleDataChanged, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, itemsPerPage: 100, onSelectionChanged: handleSelectedItemsChanged }), showExpansionWaitPanel && (_jsx(TMWaitPanel, { title: isForMaster ? 'Caricamento documenti master' : 'Caricamento documenti dettaglio', showPrimary: true, textPrimary: expansionWaitPanelText, valuePrimary: expansionWaitPanelValue, maxValuePrimary: expansionWaitPanelMaxValue, isCancelable: true, abortController: expansionAbortController, onAbortClick: (abortController) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
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 { PlatformObjectValidator, QueryDescriptor, WhereItem, SDK_Localizator, OrderByItem, SelectItem, SelectItemVisibilities, SDK_Globals, SavedQueryCacheService, SearchEngine, QueryOperators } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { PlatformObjectValidator, QueryDescriptor, WhereItem, SDK_Localizator, OrderByItem, SelectItem, SelectItemVisibilities, SDK_Globals, SavedQueryCacheService, SearchEngine, QueryOperators, AccessLevelsEx } from '@topconsultnpm/sdk-ts';
|
|
4
4
|
import styled from 'styled-components';
|
|
5
5
|
import TMSearchQueryEditor from './TMSearchQueryEditor';
|
|
6
6
|
import { getDcmtTypesByQdAsync, SDKUI_Localizator, getQD, IconMenuVertical, IconAddCircleOutline, IconEdit, IconEasy, IconAdvanced, deepCompare, IconSearch, IconClear, getDefaultOperator, prepareQdForSearchAsync, IsParametricQuery, SDKUI_Globals, IconArrowRight, IconMenuCAArchive, getListMaxItems, DEFAULT_MAX_DCMTS_TO_BE_RETURNED } from '../../../helper';
|
|
@@ -319,8 +319,8 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
319
319
|
{ icon: _jsx(IconEdit, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QueryWhere}`, beginGroup: true, onClick: () => { setShowFiltersConfig(true); } },
|
|
320
320
|
{ icon: _jsx(IconEdit, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QuerySelect}`, onClick: () => { setShowOutputConfig(true); } },
|
|
321
321
|
{ icon: _jsx(IconEdit, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QueryOrderBy}`, onClick: () => { setShowOrderByConfig(true); } },
|
|
322
|
-
{ icon: _jsx(IconMenuCAArchive, { viewBox: '11 11.5 26 27', fontSize: 16, strokeWidth: 2, color: 'black' }), beginGroup: true, name: SDKUI_Localizator.PassToArchive, onClick: handlePassToArchive }
|
|
323
|
-
], [showBackToResultButton, showAdvancedSearch, SQD, onBackToResult, openSqdForm, changeAdvancedSearchAsync, setShowFiltersConfig, setShowOutputConfig, setShowOrderByConfig, handlePassToArchive]);
|
|
322
|
+
{ icon: _jsx(IconMenuCAArchive, { viewBox: '11 11.5 26 27', fontSize: 16, strokeWidth: 2, color: 'black' }), beginGroup: true, name: SDKUI_Localizator.PassToArchive, disabled: fromDTD?.perm?.canArchive !== AccessLevelsEx.Yes && fromDTD?.perm?.canArchive !== AccessLevelsEx.Mixed, onClick: handlePassToArchive }
|
|
323
|
+
], [showBackToResultButton, showAdvancedSearch, SQD, onBackToResult, openSqdForm, changeAdvancedSearchAsync, setShowFiltersConfig, setShowOutputConfig, setShowOrderByConfig, handlePassToArchive, fromDTD?.perm?.canArchive]);
|
|
324
324
|
const captionText = showAllMdWhere ? SDKUI_Localizator.ShowLess : SDKUI_Localizator.ShowAll;
|
|
325
325
|
let maxItems = getListMaxItems(deviceType ?? DeviceType.DESKTOP);
|
|
326
326
|
const diff = (qd?.where?.length ?? 0) - maxItems;
|