@topconsultnpm/sdkui-react 6.21.0-dev2.9 → 6.21.0-dev3.3
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/TMAccordionNew.js +1 -0
- package/lib/components/base/TMAreaManager.js +19 -3
- package/lib/components/base/TMDataGrid.js +2 -2
- package/lib/components/base/TMModal.d.ts +1 -0
- package/lib/components/base/TMModal.js +2 -2
- package/lib/components/base/TMPanel.d.ts +7 -4
- package/lib/components/base/TMPanel.js +58 -26
- package/lib/components/base/TMTreeView.js +12 -2
- package/lib/components/base/TMWaitPanel.d.ts +3 -1
- package/lib/components/base/TMWaitPanel.js +14 -9
- package/lib/components/choosers/TMDistinctValues.js +35 -21
- package/lib/components/choosers/TMDynDataListItemChooser.js +31 -3
- package/lib/components/choosers/TMUserChooser.d.ts +4 -0
- package/lib/components/choosers/TMUserChooser.js +7 -5
- package/lib/components/editors/TMFormulaEditor.d.ts +2 -0
- package/lib/components/editors/TMFormulaEditor.js +75 -21
- package/lib/components/editors/TMMetadataValues.js +2 -1
- package/lib/components/editors/TMRadioButton.js +7 -5
- package/lib/components/editors/TMTextBox.d.ts +2 -0
- package/lib/components/editors/TMTextBox.js +3 -3
- package/lib/components/features/archive/TMArchive.js +1 -1
- package/lib/components/features/documents/TMCopyToFolderForm.d.ts +24 -0
- package/lib/components/features/documents/TMCopyToFolderForm.js +401 -0
- package/lib/components/features/documents/TMDcmtForm.d.ts +1 -0
- package/lib/components/features/documents/TMDcmtForm.js +126 -38
- package/lib/components/features/documents/TMDcmtPreview.d.ts +1 -0
- package/lib/components/features/documents/TMDcmtPreview.js +2 -2
- package/lib/components/features/documents/TMDcmtTasks.d.ts +1 -0
- package/lib/components/features/documents/TMDcmtTasks.js +2 -2
- package/lib/components/features/documents/TMDownloadRelationViewerSection.d.ts +23 -0
- package/lib/components/features/documents/TMDownloadRelationViewerSection.js +173 -0
- package/lib/components/features/documents/TMFileUploader.js +1 -1
- package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
- package/lib/components/features/documents/TMMasterDetailDcmts.js +28 -9
- package/lib/components/features/documents/TMMergeToPdfForm.d.ts +24 -0
- package/lib/components/features/documents/TMMergeToPdfForm.js +309 -0
- package/lib/components/features/documents/TMRelationViewer.d.ts +13 -0
- package/lib/components/features/documents/TMRelationViewer.js +75 -6
- package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +71 -0
- package/lib/components/features/documents/copyAndMergeDcmtsShared.js +304 -0
- package/lib/components/features/search/SignatureParamsManager.d.ts +70 -0
- package/lib/components/features/search/SignatureParamsManager.js +145 -0
- package/lib/components/features/search/TMSavedQuerySelector.d.ts +2 -2
- package/lib/components/features/search/TMSavedQuerySelector.js +3 -2
- package/lib/components/features/search/TMSearch.d.ts +4 -1
- package/lib/components/features/search/TMSearch.js +16 -10
- package/lib/components/features/search/TMSearchQueryPanel.js +1 -1
- package/lib/components/features/search/TMSearchResult.d.ts +2 -0
- package/lib/components/features/search/TMSearchResult.js +117 -22
- package/lib/components/features/workflow/diagram/queryDescriptorParser.js +3 -6
- package/lib/components/forms/Login/TMLoginForm.d.ts +9 -0
- package/lib/components/forms/Login/TMLoginForm.js +61 -0
- package/lib/components/forms/TMResultDialog.d.ts +1 -1
- package/lib/components/forms/TMResultDialog.js +4 -2
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.js +1 -0
- package/lib/components/pages/TMPage.js +3 -1
- package/lib/components/query/TMQueryEditor.js +1 -1
- package/lib/components/viewers/TMTidViewer.js +1 -1
- package/lib/helper/MergePdfManager.d.ts +45 -0
- package/lib/helper/MergePdfManager.js +148 -0
- package/lib/helper/SDKUI_Globals.d.ts +15 -0
- package/lib/helper/SDKUI_Globals.js +16 -1
- package/lib/helper/SDKUI_Localizator.d.ts +108 -2
- package/lib/helper/SDKUI_Localizator.js +1080 -12
- package/lib/helper/TMPdfViewer.js +25 -24
- package/lib/helper/TMUtils.d.ts +1 -0
- package/lib/helper/TMUtils.js +17 -0
- package/lib/helper/ZipManager.d.ts +56 -0
- package/lib/helper/ZipManager.js +127 -0
- package/lib/helper/index.d.ts +1 -0
- package/lib/helper/index.js +1 -0
- package/lib/hooks/useDataUserIdItem.js +6 -4
- package/lib/hooks/useDcmtOperations.d.ts +9 -2
- package/lib/hooks/useDcmtOperations.js +77 -34
- package/lib/hooks/useDocumentOperations.d.ts +3 -0
- package/lib/hooks/useDocumentOperations.js +233 -24
- package/lib/hooks/useForm.js +5 -2
- package/lib/hooks/useResizeObserver.d.ts +1 -1
- package/lib/hooks/useResizeObserver.js +16 -15
- package/package.json +4 -2
|
@@ -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 { DcmtTypeListCacheService, LayoutModes, SDK_Globals, SDK_Localizator } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { DcmtTypeListCacheService, LayoutModes, ObjectClasses, SDK_Globals, SDK_Localizator } from '@topconsultnpm/sdk-ts';
|
|
4
4
|
import TMRelationViewer from './TMRelationViewer';
|
|
5
5
|
import TMContextMenu from '../../NewComponents/ContextMenu/TMContextMenu';
|
|
6
6
|
import { IconMultipleSelection, IconCheckFile, IconDetailDcmts, SDKUI_Localizator, IconMenuVertical, IconDataList, IconPreview, IconSearchCheck, IconBoard, IconDcmtTypeSys, IconShow, getMoreInfoTasksForDocument, isApprovalWorkflowView, searchResultToMetadataValues, IconRefresh } from '../../../helper';
|
|
@@ -16,7 +16,7 @@ import TMDcmtForm from './TMDcmtForm';
|
|
|
16
16
|
import { TMNothingToShow } from './TMDcmtPreview';
|
|
17
17
|
import { Spinner, TMButton } 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 }) => {
|
|
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
20
|
const floatingBarContainerRef = useRef(null);
|
|
21
21
|
const [focusedItem, setFocusedItem] = useState();
|
|
22
22
|
const [selectedItems, setSelectedItems] = useState([]);
|
|
@@ -117,7 +117,26 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
117
117
|
createTaskFromDocumentOrWorkItem();
|
|
118
118
|
}
|
|
119
119
|
};
|
|
120
|
-
const
|
|
120
|
+
const handleNavigateToReference = useCallback((ref) => {
|
|
121
|
+
switch (ref.objClass) {
|
|
122
|
+
case ObjectClasses.Dossier:
|
|
123
|
+
if (handleNavigateToDossiers && ref.objID)
|
|
124
|
+
handleNavigateToDossiers(ref.objID);
|
|
125
|
+
else
|
|
126
|
+
console.log("Dossier reference missing objID");
|
|
127
|
+
break;
|
|
128
|
+
case ObjectClasses.WorkingGroup:
|
|
129
|
+
if (handleNavigateToWGs && ref.objID)
|
|
130
|
+
handleNavigateToWGs(ref.objID);
|
|
131
|
+
else
|
|
132
|
+
console.log("Working Group reference missing objID");
|
|
133
|
+
break;
|
|
134
|
+
// Handle other object types as needed
|
|
135
|
+
default:
|
|
136
|
+
console.warn(`Unhandled object type: ${ref.objClass}`);
|
|
137
|
+
}
|
|
138
|
+
}, [handleNavigateToDossiers, handleNavigateToWGs]);
|
|
139
|
+
const { operationItems, renderFloatingBar, renderDcmtOperations, features, } = useDocumentOperations({
|
|
121
140
|
context: SearchResultContext.MASTER_DETAIL,
|
|
122
141
|
documentData: {
|
|
123
142
|
dtd: dtdFocused,
|
|
@@ -178,7 +197,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
178
197
|
onNavigateHandler, */
|
|
179
198
|
handleNavigateToWGs,
|
|
180
199
|
handleNavigateToDossiers,
|
|
181
|
-
|
|
200
|
+
onReferenceClick: handleNavigateToReference,
|
|
182
201
|
// Document forms/operations
|
|
183
202
|
/* openAddDocumentForm,
|
|
184
203
|
openCommentFormCallback,
|
|
@@ -285,7 +304,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
285
304
|
position: contextMenuPosition,
|
|
286
305
|
onClose: () => setContextMenuVisible(false)
|
|
287
306
|
} })] }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound, onItemContextMenu, contextMenuVisible, contextMenuPosition, refreshKey, focusedItemFormData]);
|
|
288
|
-
const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { refreshKey: refreshKeyFormOrResult, deviceType: deviceType, focusedItem: focusedItem, onTaskCreateRequest: onTaskCreateRequest, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onRefreshSearchResults: onRefreshAllPanels }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshAfterAddDcmtToFavs, refreshKeyFormOrResult]);
|
|
307
|
+
const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { refreshKey: refreshKeyFormOrResult, deviceType: deviceType, focusedItem: focusedItem, onTaskCreateRequest: onTaskCreateRequest, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, handleNavigateToReference: handleNavigateToReference, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, editPdfForm: editPdfForm, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, onRefreshSearchResults: onRefreshAllPanels }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers, handleNavigateToReference, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshAfterAddDcmtToFavs, refreshKeyFormOrResult]);
|
|
289
308
|
const initialPanelDimensions = {
|
|
290
309
|
'tmTreeView': { width: '50%', height: '100%' },
|
|
291
310
|
'tmFormOrResult': { width: '50%', height: '100%' },
|
|
@@ -402,13 +421,13 @@ const TMRelationViewerWrapper = ({ refreshKey, inputDcmts, isForMaster, showCurr
|
|
|
402
421
|
onItemContextMenu?.(item, e);
|
|
403
422
|
}, 100);
|
|
404
423
|
}, [onItemContextMenu, handleFocusedItemChanged]);
|
|
405
|
-
return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, onNoRelationsFound: onNoRelationsFound, onItemContextMenu: onContextMenu, focusedItemFormData: focusedItemFormData }, refreshKey));
|
|
424
|
+
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, showExpandAllButton: true, onNoRelationsFound: onNoRelationsFound, onItemContextMenu: onContextMenu, focusedItemFormData: focusedItemFormData }, refreshKey));
|
|
406
425
|
};
|
|
407
|
-
const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid, onRefreshSearchResults }) => {
|
|
426
|
+
const TMFormOrResultWrapper = ({ refreshKey, deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, onRefreshAfterAddDcmtToFavs, editPdfForm, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onRefreshSearchAsyncDatagrid, onRefreshSearchResults, handleNavigateToReference }) => {
|
|
408
427
|
const { setPanelVisibilityById } = useTMPanelManagerContext();
|
|
409
428
|
return (_jsx(_Fragment, { children: focusedItem?.isDcmt ?
|
|
410
|
-
_jsx(TMDcmtForm, { groupId: 'tmFormOrResult', TID: focusedItem?.tid, DID: focusedItem.did, allowButtonsRefs: true, isClosable: deviceType !== DeviceType.MOBILE, allowNavigation: false, allowRelations: deviceType !== DeviceType.MOBILE, showDcmtFormSidebar: false, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, focusedItem?.tid, focusedItem?.did), openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, datagridUtility: {
|
|
429
|
+
_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, onReferenceClick: handleNavigateToReference, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, focusedItem?.tid, focusedItem?.did), openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, onOpenPdfEditorRequest: onOpenPdfEditorRequest, datagridUtility: {
|
|
411
430
|
onRefreshSearchAsyncDatagrid,
|
|
412
431
|
} }, refreshKey) :
|
|
413
|
-
_jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, enablePinIcons: false, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, showBackButton: false, onRefreshSearchAsyncDatagrid: onRefreshSearchResults }, refreshKey) }));
|
|
432
|
+
_jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setPanelVisibilityById('tmTreeView', true); }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, enablePinIcons: false, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, showBackButton: false, onRefreshSearchAsyncDatagrid: onRefreshSearchResults, onReferenceClick: handleNavigateToReference }, refreshKey) }));
|
|
414
433
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DcmtInfo } from '../../../ts';
|
|
3
|
+
import { HomeBlogPost, TaskDescriptor } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import { TMCopyToFolderMode } from '../../../hooks/useDocumentOperations';
|
|
5
|
+
interface ITMMergeToPdfFormProps {
|
|
6
|
+
mode: TMCopyToFolderMode;
|
|
7
|
+
selectedDcmtInfos: Array<DcmtInfo>;
|
|
8
|
+
onClose: () => void;
|
|
9
|
+
showTMRelationViewer: boolean;
|
|
10
|
+
allTasks?: Array<TaskDescriptor>;
|
|
11
|
+
getAllTasks?: () => Promise<void>;
|
|
12
|
+
deleteTaskByIdsCallback?: (deletedTaskIds: Array<number>) => Promise<void>;
|
|
13
|
+
addTaskCallback?: (task: TaskDescriptor) => Promise<void>;
|
|
14
|
+
editTaskCallback?: (task: TaskDescriptor) => Promise<void>;
|
|
15
|
+
handleNavigateToWGs?: (value: HomeBlogPost | number) => Promise<void>;
|
|
16
|
+
handleNavigateToDossiers?: (value: HomeBlogPost | number) => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Form per l'unione di più documenti PDF in un singolo file.
|
|
20
|
+
* Condivide TMDownloadRelationViewerSection e gli helper in copyAndMergeDcmtsShared
|
|
21
|
+
* con TMCopyToFolderForm.
|
|
22
|
+
*/
|
|
23
|
+
declare const TMMergeToPdfForm: React.FC<ITMMergeToPdfFormProps>;
|
|
24
|
+
export default TMMergeToPdfForm;
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import { DownloadTypes } from '../../../ts';
|
|
4
|
+
import { calcResponsiveSizes, IconFolderOpen, IconPlay, IconUndo, isConvertibleToPdfExt, SDKUI_Globals, SDKUI_Localizator, } from '../../../helper';
|
|
5
|
+
import { DcmtOpers, FileFormats, GeneralRetrieveFormats, ResultTypes, RetrieveFileOptions, ValidationItem, } from '@topconsultnpm/sdk-ts';
|
|
6
|
+
import TMModal from '../../base/TMModal';
|
|
7
|
+
import { useDeviceType } from '../../base/TMDeviceProvider';
|
|
8
|
+
import TMTextBox from '../../editors/TMTextBox';
|
|
9
|
+
import { ButtonNames, TMMessageBoxManager } from '../../base/TMPopUp';
|
|
10
|
+
import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
|
|
11
|
+
import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
|
|
12
|
+
import { TMSplitterLayout } from '../../base/TMLayout';
|
|
13
|
+
import { TMColors } from '../../../utils/theme';
|
|
14
|
+
import TMDownloadRelationViewerSection from './TMDownloadRelationViewerSection';
|
|
15
|
+
import { getDcmtInfosToDownload, getFloatingLabelStyle, isDirectoryPickerSupported, isPdfExt, MIN_PDF_FOR_MERGE, } from './copyAndMergeDcmtsShared';
|
|
16
|
+
import ShowAlert from '../../base/TMAlert';
|
|
17
|
+
import TMTooltip from '../../base/TMTooltip';
|
|
18
|
+
import MergePdfManager from '../../../helper/MergePdfManager';
|
|
19
|
+
/**
|
|
20
|
+
* Form per l'unione di più documenti PDF in un singolo file.
|
|
21
|
+
* Condivide TMDownloadRelationViewerSection e gli helper in copyAndMergeDcmtsShared
|
|
22
|
+
* con TMCopyToFolderForm.
|
|
23
|
+
*/
|
|
24
|
+
const TMMergeToPdfForm = ({ mode, selectedDcmtInfos, onClose, showTMRelationViewer, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
|
|
25
|
+
const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, } = useDcmtOperations();
|
|
26
|
+
const deviceType = useDeviceType();
|
|
27
|
+
const [pdfFileName, setPdfFileName] = useState(`${SDKUI_Localizator.Result.toLowerCase()}.pdf`);
|
|
28
|
+
const [destinationFolder, setDestinationFolder] = useState('Download');
|
|
29
|
+
const [selectedItemsRelationViewer, setSelectedItemsRelationViewer] = useState([]);
|
|
30
|
+
// ---- Stato per il merge PDF (progress bar) ----
|
|
31
|
+
const [isMergingPdf, setIsMergingPdf] = useState(false);
|
|
32
|
+
const [mergeProgressText, setMergeProgressText] = useState('');
|
|
33
|
+
const [mergeProgressValue, setMergeProgressValue] = useState(0);
|
|
34
|
+
const [mergeProgressMax, setMergeProgressMax] = useState(0);
|
|
35
|
+
// ---- Ref per la selezione cartella (File System Access API) ----
|
|
36
|
+
const folderHandleRef = useRef(null);
|
|
37
|
+
const skipSelectFolderRef = useRef(false);
|
|
38
|
+
const isPickerActiveRef = useRef(false);
|
|
39
|
+
const isUsingDefaultDownloads = destinationFolder === 'Download' && !folderHandleRef.current;
|
|
40
|
+
// ---- Handler dei campi cartella ----
|
|
41
|
+
const handleFolderValueChange = (e) => {
|
|
42
|
+
setDestinationFolder(e.target.value);
|
|
43
|
+
folderHandleRef.current = null;
|
|
44
|
+
};
|
|
45
|
+
const handleSelectFolder = async () => {
|
|
46
|
+
if (skipSelectFolderRef.current) {
|
|
47
|
+
skipSelectFolderRef.current = false;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (isPickerActiveRef.current)
|
|
51
|
+
return;
|
|
52
|
+
try {
|
|
53
|
+
isPickerActiveRef.current = true;
|
|
54
|
+
const dirHandle = await window.showDirectoryPicker({ mode: 'readwrite' });
|
|
55
|
+
folderHandleRef.current = dirHandle;
|
|
56
|
+
setDestinationFolder(dirHandle.name);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (err.name !== 'AbortError') {
|
|
60
|
+
console.error('Error selecting folder::', err);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
isPickerActiveRef.current = false;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const getTitle = () => {
|
|
68
|
+
const count = ` (${selectedDcmtInfos.length})`;
|
|
69
|
+
const modeLabelMap = {
|
|
70
|
+
onlySelected: SDKUI_Localizator.SelectedDocuments,
|
|
71
|
+
customized: SDKUI_Localizator.SelectedDocumentsAndRelated,
|
|
72
|
+
};
|
|
73
|
+
const modeLabel = modeLabelMap[mode] || modeLabelMap.onlySelected;
|
|
74
|
+
return `${SDKUI_Localizator.MergeToPdf} - ${modeLabel}${count}`;
|
|
75
|
+
};
|
|
76
|
+
// ---- Validazione ----
|
|
77
|
+
const pdfValidationItems = [];
|
|
78
|
+
if (!pdfFileName.trim()) {
|
|
79
|
+
pdfValidationItems.push(new ValidationItem(ResultTypes.ERROR, SDKUI_Localizator.PdfFileName, SDKUI_Localizator.RequiredField));
|
|
80
|
+
}
|
|
81
|
+
// ---- Statistiche selezione PDF / convertibili / non-PDF ----
|
|
82
|
+
const convertibleSelectedItems = (() => {
|
|
83
|
+
if (showTMRelationViewer) {
|
|
84
|
+
return selectedItemsRelationViewer
|
|
85
|
+
.filter(i => i.isDcmt && isConvertibleToPdfExt(i.fileExt))
|
|
86
|
+
.map(i => ({ key: `${i.tid}_${i.did}`, ext: i.fileExt ?? undefined }));
|
|
87
|
+
}
|
|
88
|
+
return selectedDcmtInfos
|
|
89
|
+
.filter(d => isConvertibleToPdfExt(d.FILEEXT))
|
|
90
|
+
.map(d => ({ key: `${d.TID}_${d.DID}`, ext: d.FILEEXT }));
|
|
91
|
+
})();
|
|
92
|
+
const hasConvertibleSelected = convertibleSelectedItems.length > 0;
|
|
93
|
+
const nonPdfSelectedItems = (() => {
|
|
94
|
+
if (showTMRelationViewer) {
|
|
95
|
+
return selectedItemsRelationViewer
|
|
96
|
+
.filter(i => i.isDcmt && !isPdfExt(i.fileExt) && !isConvertibleToPdfExt(i.fileExt))
|
|
97
|
+
.map(i => ({ key: `${i.tid}_${i.did}`, ext: i.fileExt ?? undefined }));
|
|
98
|
+
}
|
|
99
|
+
return selectedDcmtInfos
|
|
100
|
+
.filter(d => !isPdfExt(d.FILEEXT) && !isConvertibleToPdfExt(d.FILEEXT))
|
|
101
|
+
.map(d => ({ key: `${d.TID}_${d.DID}`, ext: d.FILEEXT }));
|
|
102
|
+
})();
|
|
103
|
+
const hasNonPdfSelected = nonPdfSelectedItems.length > 0;
|
|
104
|
+
// Conteggio file unibili: PDF nativi + file convertibili
|
|
105
|
+
const mergeableSelectedCount = (() => {
|
|
106
|
+
if (showTMRelationViewer) {
|
|
107
|
+
return selectedItemsRelationViewer.filter(i => i.isDcmt && (isPdfExt(i.fileExt) || isConvertibleToPdfExt(i.fileExt))).length;
|
|
108
|
+
}
|
|
109
|
+
return selectedDcmtInfos.filter(d => isPdfExt(d.FILEEXT) || isConvertibleToPdfExt(d.FILEEXT)).length;
|
|
110
|
+
})();
|
|
111
|
+
const hasEnoughPdfForMerge = mergeableSelectedCount >= MIN_PDF_FOR_MERGE;
|
|
112
|
+
const isFormValid = () => pdfValidationItems.length === 0;
|
|
113
|
+
// ---- Recupero dei file PDF da unire (condiviso tra Esegui e Anteprima) ----
|
|
114
|
+
const collectPdfFilesToMerge = async () => {
|
|
115
|
+
const dcmtInfosToDownload = getDcmtInfosToDownload(selectedDcmtInfos, selectedItemsRelationViewer, showTMRelationViewer);
|
|
116
|
+
if (dcmtInfosToDownload.length === 0) {
|
|
117
|
+
TMMessageBoxManager.show({ message: SDKUI_Localizator.NoDcmtSelected, buttons: [ButtonNames.OK] });
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const nonPdfKeys = new Set(nonPdfSelectedItems.map(i => i.key));
|
|
121
|
+
const pdfDcmtInfosToDownload = dcmtInfosToDownload.filter(d => !nonPdfKeys.has(`${d.TID}_${d.DID}`));
|
|
122
|
+
if (pdfDcmtInfosToDownload.length === 0) {
|
|
123
|
+
TMMessageBoxManager.show({
|
|
124
|
+
message: SDKUI_Localizator.NoPdfOrConvertibleFilesAmongSelectedMergeBlocked,
|
|
125
|
+
buttons: [ButtonNames.OK]
|
|
126
|
+
});
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
if (pdfDcmtInfosToDownload.length < MIN_PDF_FOR_MERGE) {
|
|
130
|
+
TMMessageBoxManager.show({
|
|
131
|
+
message: SDKUI_Localizator.OnlyOnePdfOrConvertibleFileMergeBlocked.replaceParams(MIN_PDF_FOR_MERGE.toString()),
|
|
132
|
+
buttons: [ButtonNames.OK]
|
|
133
|
+
});
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const pdfFiles = [];
|
|
137
|
+
const rfo = new RetrieveFileOptions();
|
|
138
|
+
rfo.retrieveReason = DcmtOpers.None;
|
|
139
|
+
rfo.generalRetrieveFormat = GeneralRetrieveFormats.OriginalUnsigned;
|
|
140
|
+
rfo.cvtFormat = FileFormats.PDF;
|
|
141
|
+
rfo.invoiceRetrieveFormat = SDKUI_Globals.userSettings?.searchSettings.invoiceRetrieveFormat;
|
|
142
|
+
rfo.orderRetrieveFormat = SDKUI_Globals.userSettings?.searchSettings.orderRetrieveFormat;
|
|
143
|
+
const collectFileForMerge = async (file, _dcmtInfo) => {
|
|
144
|
+
pdfFiles.push(file);
|
|
145
|
+
};
|
|
146
|
+
await downloadDcmtsAsync(pdfDcmtInfosToDownload, DownloadTypes.Dcmt, 'download', collectFileForMerge, undefined, true, rfo, false);
|
|
147
|
+
if (pdfFiles.length === 0) {
|
|
148
|
+
TMMessageBoxManager.show({ message: SDKUI_Localizator.NoFilesAvailableForMerge, buttons: [ButtonNames.OK] });
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
return pdfFiles;
|
|
152
|
+
};
|
|
153
|
+
// ---- Esecuzione: scarica i PDF e li unisce ----
|
|
154
|
+
const run = async () => {
|
|
155
|
+
if (pdfValidationItems.length > 0) {
|
|
156
|
+
TMMessageBoxManager.show({ message: SDKUI_Localizator.PleaseCorrectErrorsBeforeProceeding, buttons: [ButtonNames.OK] });
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const pdfFiles = await collectPdfFilesToMerge();
|
|
160
|
+
if (!pdfFiles)
|
|
161
|
+
return;
|
|
162
|
+
const finalName = pdfFileName.trim().toLowerCase().endsWith('.pdf') ? pdfFileName.trim() : pdfFileName.trim() + '.pdf';
|
|
163
|
+
// Inizializza progress bar per il merge
|
|
164
|
+
setIsMergingPdf(true);
|
|
165
|
+
setMergeProgressMax(pdfFiles.length);
|
|
166
|
+
setMergeProgressValue(0);
|
|
167
|
+
setMergeProgressText(SDKUI_Localizator.MergeToPdf);
|
|
168
|
+
try {
|
|
169
|
+
const mergeOptions = {
|
|
170
|
+
onProgress: (current, total, file) => {
|
|
171
|
+
setMergeProgressValue(current);
|
|
172
|
+
setMergeProgressText(`${SDKUI_Localizator.MergeToPdf}: ${file.name}`);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
// Se c'è una cartella selezionata (non Download di default), salva direttamente nella cartella
|
|
176
|
+
if (folderHandleRef.current) {
|
|
177
|
+
const mergedFile = await MergePdfManager.mergeToFile(pdfFiles, finalName, mergeOptions);
|
|
178
|
+
const fileHandle = await folderHandleRef.current.getFileHandle(finalName, { create: true });
|
|
179
|
+
const writable = await fileHandle.createWritable();
|
|
180
|
+
await writable.write(mergedFile);
|
|
181
|
+
await writable.close();
|
|
182
|
+
ShowAlert({ message: SDKUI_Localizator.PdfMergedSavedInFolder.replaceParams(folderHandleRef.current.name), mode: 'success', duration: 5000, title: SDKUI_Localizator.MergeToPdf });
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
// Altrimenti usa il download standard del browser
|
|
186
|
+
await MergePdfManager.mergeAndDownload(pdfFiles, finalName, mergeOptions);
|
|
187
|
+
ShowAlert({ message: SDKUI_Localizator.PdfMergedSavedInFolder.replaceParams('Download'), mode: 'success', duration: 5000, title: SDKUI_Localizator.MergeToPdf });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
console.error('Error merging PDF or convertible files:', err);
|
|
192
|
+
TMMessageBoxManager.show({ message: SDKUI_Localizator.PdfMergeError, buttons: [ButtonNames.OK] });
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
setIsMergingPdf(false);
|
|
197
|
+
}
|
|
198
|
+
onClose();
|
|
199
|
+
};
|
|
200
|
+
// ---- Render della sezione configurazione (solo PDF file name + warning) ----
|
|
201
|
+
const configSection = (_jsxs("div", { style: {
|
|
202
|
+
position: 'relative',
|
|
203
|
+
border: `1px solid ${TMColors.border_normal}`,
|
|
204
|
+
borderRadius: '8px',
|
|
205
|
+
padding: '8px',
|
|
206
|
+
height: showTMRelationViewer ? 'calc(100% - 7px)' : undefined,
|
|
207
|
+
marginTop: '7px',
|
|
208
|
+
flex: showTMRelationViewer ? undefined : 1,
|
|
209
|
+
minHeight: 0,
|
|
210
|
+
display: 'flex',
|
|
211
|
+
flexDirection: 'column',
|
|
212
|
+
boxSizing: 'border-box'
|
|
213
|
+
}, children: [_jsx("span", { style: getFloatingLabelStyle(), title: `${SDKUI_Localizator.ConfigurationParameters} (${SDKUI_Localizator.MergeToPdf})`, children: SDKUI_Localizator.ConfigurationParameters }), _jsxs("div", { style: {
|
|
214
|
+
display: 'flex',
|
|
215
|
+
flexDirection: 'column',
|
|
216
|
+
flex: 1,
|
|
217
|
+
overflowY: 'auto',
|
|
218
|
+
minHeight: 0,
|
|
219
|
+
}, children: [_jsxs("div", { style: { display: 'flex', flexWrap: 'wrap', columnGap: '10px' }, children: [isDirectoryPickerSupported() ? (_jsx("div", { style: { flex: '1 1 280px', minWidth: '280px' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.FolderName, value: destinationFolder, onValueChanged: handleFolderValueChange, readOnly: true, placeHolder: "Download", onClick: handleSelectFolder, buttons: [
|
|
220
|
+
{
|
|
221
|
+
icon: _jsx(IconFolderOpen, {}),
|
|
222
|
+
text: SDKUI_Localizator.SelectFolder,
|
|
223
|
+
onClick: handleSelectFolder
|
|
224
|
+
},
|
|
225
|
+
...(!isUsingDefaultDownloads ? [{
|
|
226
|
+
icon: _jsx(IconUndo, {}),
|
|
227
|
+
text: SDKUI_Localizator.RestoreDownload,
|
|
228
|
+
onClick: () => {
|
|
229
|
+
skipSelectFolderRef.current = true;
|
|
230
|
+
setDestinationFolder('Download');
|
|
231
|
+
folderHandleRef.current = null;
|
|
232
|
+
}
|
|
233
|
+
}] : [])
|
|
234
|
+
] }) })) : (_jsx("div", { style: { flex: '1 1 280px', minWidth: '280px' }, children: _jsxs("div", { style: { position: 'relative', marginTop: '16px' }, children: [_jsx("span", { style: {
|
|
235
|
+
position: 'absolute',
|
|
236
|
+
top: '-10px',
|
|
237
|
+
left: '12px',
|
|
238
|
+
fontSize: '0.9rem',
|
|
239
|
+
color: TMColors.label_normal,
|
|
240
|
+
padding: '0 3px',
|
|
241
|
+
userSelect: 'none',
|
|
242
|
+
WebkitTouchCallout: 'none',
|
|
243
|
+
WebkitUserSelect: 'none',
|
|
244
|
+
width: 'max-content',
|
|
245
|
+
backgroundColor: TMColors.default_background,
|
|
246
|
+
zIndex: 1,
|
|
247
|
+
}, children: SDKUI_Localizator.Path }), _jsxs("div", { style: { border: `1px solid ${TMColors.border_normal}`, borderRadius: '5px', padding: '4px 10px 4px 13px', display: 'flex', alignItems: 'center', gap: '8px', backgroundColor: '#fafafa' }, children: [_jsx(IconFolderOpen, {}), _jsx("span", { style: { fontSize: '0.9rem', color: '#333' }, children: "Download" })] }), _jsx("span", { style: { fontSize: '0.8rem', color: '#888', fontStyle: 'italic', marginTop: '4px', display: 'block' }, children: SDKUI_Localizator.BrowserDoesNotSupportFolderSelection })] }) })), _jsx("div", { style: { flex: '1.5 1 420px', minWidth: '350px', width: '100%' }, children: _jsx(TMTextBox, { label: SDKUI_Localizator.PdfFileName, value: pdfFileName, validationItems: pdfValidationItems, autoComplete: "one-time-code", onValueChanged: (e) => setPdfFileName(e.target.value) }) })] }), (hasConvertibleSelected || !hasEnoughPdfForMerge || hasNonPdfSelected) && (_jsxs("div", { style: {
|
|
248
|
+
display: 'flex',
|
|
249
|
+
flexDirection: 'column',
|
|
250
|
+
gap: '6px',
|
|
251
|
+
padding: '8px 12px',
|
|
252
|
+
border: '1px solid #c0c0c0',
|
|
253
|
+
borderRadius: '5px',
|
|
254
|
+
backgroundColor: '#f8f8f8',
|
|
255
|
+
fontSize: '0.85rem',
|
|
256
|
+
marginTop: '12px',
|
|
257
|
+
}, children: [_jsx("div", { style: {
|
|
258
|
+
display: 'flex',
|
|
259
|
+
alignItems: 'center',
|
|
260
|
+
gap: '6px',
|
|
261
|
+
fontWeight: 600,
|
|
262
|
+
color: '#555',
|
|
263
|
+
fontSize: '0.9rem',
|
|
264
|
+
borderBottom: '1px solid #e0e0e0',
|
|
265
|
+
paddingBottom: '6px',
|
|
266
|
+
marginBottom: '2px'
|
|
267
|
+
}, children: SDKUI_Localizator.NotesAndWarnings }), _jsxs("ul", { style: { margin: 0, paddingLeft: '18px', display: 'flex', flexDirection: 'column', gap: '4px' }, children: [hasConvertibleSelected && (_jsx("li", { style: { color: '#00527a' }, children: (() => {
|
|
268
|
+
const extSet = Array.from(new Set(convertibleSelectedItems.map(i => (i.ext ?? '').toString().trim().toLowerCase().replace(/^\./, '')).filter(e => e.length > 0)));
|
|
269
|
+
const extLabel = extSet.length > 0
|
|
270
|
+
? ` (${extSet.map(e => '.' + e).join(', ')})`
|
|
271
|
+
: '';
|
|
272
|
+
return convertibleSelectedItems.length === 1
|
|
273
|
+
? SDKUI_Localizator.DocumentWillBeConvertedDuringMerge.replaceParams(extLabel)
|
|
274
|
+
: SDKUI_Localizator.DocumentsWillBeConvertedDuringMerge.replaceParams(convertibleSelectedItems.length.toString(), extLabel);
|
|
275
|
+
})() })), !hasEnoughPdfForMerge && (_jsx("li", { style: { color: '#7a5d00' }, children: mergeableSelectedCount === 0
|
|
276
|
+
? SDKUI_Localizator.NoPdfOrConvertibleFilesSelected_Param.replaceParams(MIN_PDF_FOR_MERGE.toString())
|
|
277
|
+
: SDKUI_Localizator.OnlyOnePdfOrConvertibleFileSelected.replaceParams(MIN_PDF_FOR_MERGE.toString()) })), hasNonPdfSelected && (_jsx("li", { style: { color: '#7a5d00' }, children: (() => {
|
|
278
|
+
const extSet = Array.from(new Set(nonPdfSelectedItems.map(i => (i.ext ?? '').toString().trim().toLowerCase().replace(/^\./, '')).filter(e => e.length > 0)));
|
|
279
|
+
const extLabel = extSet.length > 0 ? ` (${extSet.map(e => '.' + e).join(', ')})` : '';
|
|
280
|
+
return nonPdfSelectedItems.length === 1
|
|
281
|
+
? SDKUI_Localizator.FileNotPdfWillBeExcluded.replaceParams(extLabel)
|
|
282
|
+
: SDKUI_Localizator.FilesNotPdfWillBeExcluded.replaceParams(nonPdfSelectedItems.length.toString(), extLabel);
|
|
283
|
+
})() }))] })] }))] })] }));
|
|
284
|
+
return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel || isMergingPdf, showWaitPanelPrimary: isMergingPdf ? true : showPrimary, showWaitPanelSecondary: isMergingPdf ? false : showSecondary, waitPanelTitle: isMergingPdf ? SDKUI_Localizator.MergeToPdf : waitPanelTitle, waitPanelTextPrimary: isMergingPdf ? mergeProgressText : waitPanelTextPrimary, waitPanelValuePrimary: isMergingPdf ? mergeProgressValue : waitPanelValuePrimary, waitPanelMaxValuePrimary: isMergingPdf ? mergeProgressMax : waitPanelMaxValuePrimary, waitPanelTextSecondary: isMergingPdf ? '' : waitPanelTextSecondary, waitPanelValueSecondary: isMergingPdf ? 0 : waitPanelValueSecondary, waitPanelMaxValueSecondary: isMergingPdf ? 0 : waitPanelMaxValueSecondary, isCancelable: !isMergingPdf, abortController: abortController, usePortal: true, children: _jsx(TMModal, { width: calcResponsiveSizes(deviceType, showTMRelationViewer ? '90%' : '500px', showTMRelationViewer ? '90%' : '500px', '95%'), height: showTMRelationViewer ? '95%' : 'auto', title: getTitle(), onClose: onClose, showCloseButton: true, children: _jsxs("div", { onContextMenu: (e) => e.preventDefault(), style: { display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px', width: '100%', height: '100%', boxSizing: 'border-box', overflow: 'hidden' }, children: [showTMRelationViewer ? (_jsx("div", { style: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }, children: _jsxs(TMSplitterLayout, { direction: 'vertical', showSeparator: true, separatorSize: 8, separatorColor: 'transparent', separatorActiveColor: 'transparent', overflow: 'hidden', min: ["50", "50"], start: ["70%", "30%"], children: [_jsx(TMDownloadRelationViewerSection, { selectedDcmtInfos: selectedDcmtInfos, onSelectionChanged: setSelectedItemsRelationViewer, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), configSection] }, "TMMergeToPdf-relation-config") })) : (configSection), _jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', flexShrink: 0, marginTop: '12px' }, children: _jsxs("button", { disabled: !isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0) || !hasEnoughPdfForMerge, onClick: run, style: {
|
|
285
|
+
display: 'flex',
|
|
286
|
+
alignItems: 'center',
|
|
287
|
+
justifyContent: 'center',
|
|
288
|
+
gap: '6px',
|
|
289
|
+
padding: '8px 20px',
|
|
290
|
+
fontSize: '0.95rem',
|
|
291
|
+
fontWeight: 600,
|
|
292
|
+
color: '#fff',
|
|
293
|
+
background: (!isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0) || !hasEnoughPdfForMerge)
|
|
294
|
+
? '#b0b0b0'
|
|
295
|
+
: 'linear-gradient(135deg, #28a745 0%, #218838 100%)',
|
|
296
|
+
border: 'none',
|
|
297
|
+
borderRadius: '6px',
|
|
298
|
+
cursor: (!isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0) || !hasEnoughPdfForMerge) ? 'not-allowed' : 'pointer',
|
|
299
|
+
boxShadow: (!isFormValid() || (showTMRelationViewer && selectedItemsRelationViewer.filter(i => i.isDcmt).length === 0) || !hasEnoughPdfForMerge)
|
|
300
|
+
? 'none'
|
|
301
|
+
: '0 2px 8px rgba(40, 167, 69, 0.35)',
|
|
302
|
+
transition: 'all 0.2s ease',
|
|
303
|
+
}, children: [_jsx(IconPlay, {}), _jsx("span", { children: mergeableSelectedCount === 0
|
|
304
|
+
? SDKUI_Localizator.MergeToPdf
|
|
305
|
+
: mergeableSelectedCount > 999
|
|
306
|
+
? _jsx(TMTooltip, { content: mergeableSelectedCount.toString(), children: SDKUI_Localizator.MergeFilesToPdf.replaceParams('999+') })
|
|
307
|
+
: SDKUI_Localizator.MergeFilesToPdf.replaceParams(mergeableSelectedCount.toString()) })] }) })] }) }) }));
|
|
308
|
+
};
|
|
309
|
+
export default TMMergeToPdfForm;
|
|
@@ -50,6 +50,8 @@ export interface TMRelationViewerProps {
|
|
|
50
50
|
onFocusedItemChanged?: (item: RelationTreeItem | null) => void;
|
|
51
51
|
/** Callback when selected items change */
|
|
52
52
|
onSelectedItemsChanged?: (items: RelationTreeItem[]) => void;
|
|
53
|
+
/** Callback fired when the internal tree data changes, providing a flattened list of all items currently rendered */
|
|
54
|
+
onAllItemsChanged?: (items: RelationTreeItem[]) => void;
|
|
53
55
|
/** Callback when a document is double-clicked */
|
|
54
56
|
onDocumentDoubleClick?: (tid: number, did: number, name?: string) => void;
|
|
55
57
|
/** Custom item renderer (full control). Return undefined to use default renderer. */
|
|
@@ -109,6 +111,17 @@ export interface TMRelationViewerProps {
|
|
|
109
111
|
* (used in master-detail context)
|
|
110
112
|
*/
|
|
111
113
|
focusedItemFormData?: MetadataValueDescriptorEx[];
|
|
114
|
+
/**
|
|
115
|
+
* If true, shows a toolbar button to expand/collapse all tree nodes.
|
|
116
|
+
* Default: false
|
|
117
|
+
*/
|
|
118
|
+
showExpandAllButton?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* If true, all tree nodes are expanded by default on initial load.
|
|
121
|
+
* If false (default), uses the standard initial expansion behavior
|
|
122
|
+
* (root container + first document + first correlation folder).
|
|
123
|
+
*/
|
|
124
|
+
defaultExpandAll?: boolean;
|
|
112
125
|
}
|
|
113
126
|
/**
|
|
114
127
|
* Check if document type has detail relations
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import { DcmtTypeListCacheService, SDK_Globals, DataColumnTypes, MetadataFormats, SystemMIDs, MetadataDataDomains, RelationCacheService, RelationTypes, UserListCacheService } from "@topconsultnpm/sdk-ts";
|
|
4
|
-
import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus } from '../../../helper';
|
|
4
|
+
import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus, IconChevronDown, IconChevronRight, SDKUI_Localizator } from '../../../helper';
|
|
5
5
|
import { TMColors } from '../../../utils/theme';
|
|
6
|
-
import { StyledDivHorizontal, StyledBadge } from '../../base/Styled';
|
|
6
|
+
import { StyledDivHorizontal, StyledBadge, StyledToolbarForm } from '../../base/Styled';
|
|
7
7
|
import TMTreeView from '../../base/TMTreeView';
|
|
8
8
|
import { TMWaitPanel } from '../../base/TMWaitPanel';
|
|
9
9
|
import TMDataListItemViewer from '../../viewers/TMDataListItemViewer';
|
|
@@ -136,12 +136,14 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata) =>
|
|
|
136
136
|
}
|
|
137
137
|
return output;
|
|
138
138
|
};
|
|
139
|
-
const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndicator = true, allowShowZeroDcmts = true, initialShowZeroDcmts = false, allowedTIDs, allowMultipleSelection = false, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onDocumentDoubleClick, customItemRender, customDocumentStyle, customMainContainerContent, customDocumentContent, showMetadataNames = false, maxDepthLevel = 2, invertMasterNavigation = true, additionalStaticItems, showMainDocument = true, labelMainContainer, onNoRelationsFound, onItemContextMenu, focusedItemFormData = [] }) => {
|
|
139
|
+
const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndicator = true, allowShowZeroDcmts = true, initialShowZeroDcmts = false, allowedTIDs, allowMultipleSelection = false, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onAllItemsChanged, onDocumentDoubleClick, customItemRender, customDocumentStyle, customMainContainerContent, customDocumentContent, showMetadataNames = false, maxDepthLevel = 2, invertMasterNavigation = true, additionalStaticItems, showMainDocument = true, labelMainContainer, onNoRelationsFound, onItemContextMenu, focusedItemFormData = [], showExpandAllButton = false, defaultExpandAll = false }) => {
|
|
140
140
|
// State
|
|
141
141
|
const [dcmtTypes, setDcmtTypes] = useState([]);
|
|
142
142
|
const [treeData, setTreeData] = useState([]);
|
|
143
143
|
const [showZeroDcmts, setShowZeroDcmts] = useState(initialShowZeroDcmts);
|
|
144
144
|
const [staticItemsState, setStaticItemsState] = useState([]);
|
|
145
|
+
const [allExpanded, setAllExpanded] = useState(defaultExpandAll);
|
|
146
|
+
const initialExpandAllAppliedRef = React.useRef(false);
|
|
145
147
|
const [showWaitPanel, setShowWaitPanel] = useState(false);
|
|
146
148
|
const [waitPanelTextPrimary, setWaitPanelTextPrimary] = useState('');
|
|
147
149
|
const [waitPanelValuePrimary, setWaitPanelValuePrimary] = useState(0);
|
|
@@ -271,7 +273,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
271
273
|
console.error('❌ Error loading detail documents:', error);
|
|
272
274
|
}
|
|
273
275
|
return items;
|
|
274
|
-
}, [allowedTIDs
|
|
276
|
+
}, [allowedTIDs]);
|
|
275
277
|
/**
|
|
276
278
|
* Recursively retrieve master documents
|
|
277
279
|
*/
|
|
@@ -734,6 +736,24 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
734
736
|
// and may contain custom properties that would be lost by the spread operator
|
|
735
737
|
return [...treeData, ...itemsToMerge];
|
|
736
738
|
}, [treeData, additionalStaticItems, staticItemsState]);
|
|
739
|
+
/**
|
|
740
|
+
* Notify parent with a flattened list of all items whenever the merged tree data changes.
|
|
741
|
+
*/
|
|
742
|
+
useEffect(() => {
|
|
743
|
+
if (!onAllItemsChanged)
|
|
744
|
+
return;
|
|
745
|
+
const flatten = (items) => {
|
|
746
|
+
const out = [];
|
|
747
|
+
for (const it of items) {
|
|
748
|
+
out.push(it);
|
|
749
|
+
if (it.items && Array.isArray(it.items)) {
|
|
750
|
+
out.push(...flatten(it.items));
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return out;
|
|
754
|
+
};
|
|
755
|
+
onAllItemsChanged(flatten(mergedTreeData));
|
|
756
|
+
}, [mergedTreeData, onAllItemsChanged]);
|
|
737
757
|
/**
|
|
738
758
|
* Load data when inputs change
|
|
739
759
|
*/
|
|
@@ -1118,7 +1138,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1118
1138
|
}
|
|
1119
1139
|
}
|
|
1120
1140
|
return (_jsxs("div", { onDoubleClick: handleDoubleClick, style: documentStyle, children: [item.did && item.tid && showCurrentDcmtIndicator && inputDcmts?.some(d => d.DID === item.did && d.TID === item.tid) ? _jsx(IconBackhandIndexPointingRight, { fontSize: 22, overflow: 'visible' }) : _jsx(_Fragment, {}), item.values && (_jsx(TMDcmtIcon, { tid: item.values?.TID?.value, did: item.values?.DID?.value, fileExtension: item.values?.FILEEXT?.value, fileCount: item.values?.FILECOUNT?.value, isLexProt: item.values?.IsLexProt?.value, isMail: item.values?.ISMAIL?.value, isShared: item.values?.ISSHARED?.value, isSigned: item.values?.ISSIGNED?.value, downloadMode: 'openInNewWindow' })), checkoutStatusIcon, metadataContent] }));
|
|
1121
|
-
}, [onDocumentDoubleClick, showCurrentDcmtIndicator, inputDcmts, customMainContainerContent, customDocumentStyle, customDocumentContent, showMetadataNames, showMainDocument,
|
|
1141
|
+
}, [onDocumentDoubleClick, showCurrentDcmtIndicator, inputDcmts, customMainContainerContent, customDocumentStyle, customDocumentContent, showMetadataNames, showMainDocument, allUsers]);
|
|
1122
1142
|
/**
|
|
1123
1143
|
* Wrapper renderer that handles custom rendering if provided
|
|
1124
1144
|
*/
|
|
@@ -1148,6 +1168,42 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1148
1168
|
const handleSelectedItemsChanged = useCallback((items) => {
|
|
1149
1169
|
onSelectedItemsChanged?.(items);
|
|
1150
1170
|
}, [onSelectedItemsChanged]);
|
|
1171
|
+
/**
|
|
1172
|
+
* Recursively set the `expanded` property on every node that has children loaded.
|
|
1173
|
+
* Nodes without `items` are left untouched (will be loaded lazily on user click).
|
|
1174
|
+
*/
|
|
1175
|
+
const setExpandedRecursively = useCallback((nodes, expanded) => {
|
|
1176
|
+
if (!nodes || !Array.isArray(nodes))
|
|
1177
|
+
return [];
|
|
1178
|
+
return nodes.map(node => {
|
|
1179
|
+
const hasChildren = Array.isArray(node.items) && node.items.length > 0;
|
|
1180
|
+
const newItems = hasChildren ? setExpandedRecursively(node.items, expanded) : node.items;
|
|
1181
|
+
// Only toggle expansion if the node is expandable (container/doc with children or marked expandible)
|
|
1182
|
+
const canExpand = hasChildren || node.isExpandible;
|
|
1183
|
+
return { ...node, expanded: canExpand ? expanded : node.expanded, items: newItems };
|
|
1184
|
+
});
|
|
1185
|
+
}, []);
|
|
1186
|
+
const handleToggleExpandAll = useCallback(() => {
|
|
1187
|
+
const next = !allExpanded;
|
|
1188
|
+
setAllExpanded(next);
|
|
1189
|
+
setTreeData(prev => setExpandedRecursively(prev, next));
|
|
1190
|
+
setStaticItemsState(prev => setExpandedRecursively(prev, next));
|
|
1191
|
+
userInteractedWithStaticItemsRef.current = true;
|
|
1192
|
+
}, [allExpanded, setExpandedRecursively]);
|
|
1193
|
+
/**
|
|
1194
|
+
* Apply defaultExpandAll once on initial tree load.
|
|
1195
|
+
*/
|
|
1196
|
+
useEffect(() => {
|
|
1197
|
+
if (!defaultExpandAll)
|
|
1198
|
+
return;
|
|
1199
|
+
if (initialExpandAllAppliedRef.current)
|
|
1200
|
+
return;
|
|
1201
|
+
if (!treeData || treeData.length === 0)
|
|
1202
|
+
return;
|
|
1203
|
+
initialExpandAllAppliedRef.current = true;
|
|
1204
|
+
setTreeData(prev => setExpandedRecursively(prev, true));
|
|
1205
|
+
setStaticItemsState(prev => setExpandedRecursively(prev, true));
|
|
1206
|
+
}, [defaultExpandAll, treeData, setExpandedRecursively]);
|
|
1151
1207
|
/**
|
|
1152
1208
|
* Handle data changed - separate static items from dynamic tree data
|
|
1153
1209
|
*/
|
|
@@ -1169,7 +1225,20 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
1169
1225
|
return null;
|
|
1170
1226
|
return _jsx("div", { style: { padding: '20px', textAlign: 'center', color: '#666' }, children: "Nessuna relazione disponibile." });
|
|
1171
1227
|
}
|
|
1172
|
-
return (_jsxs(
|
|
1228
|
+
return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0, width: '100%' }, children: [showExpandAllButton && (_jsx(StyledToolbarForm, { style: { flexShrink: 0 }, children: _jsxs("button", { type: "button", onClick: handleToggleExpandAll, title: allExpanded ? SDKUI_Localizator.CollapseAll : SDKUI_Localizator.ExpandAll, style: {
|
|
1229
|
+
display: 'inline-flex',
|
|
1230
|
+
alignItems: 'center',
|
|
1231
|
+
gap: '4px',
|
|
1232
|
+
padding: '4px 8px',
|
|
1233
|
+
fontSize: '0.8rem',
|
|
1234
|
+
color: TMColors.primary,
|
|
1235
|
+
background: 'transparent',
|
|
1236
|
+
border: `1px solid ${TMColors.border_normal}`,
|
|
1237
|
+
borderRadius: '4px',
|
|
1238
|
+
cursor: 'pointer',
|
|
1239
|
+
lineHeight: 1,
|
|
1240
|
+
whiteSpace: 'nowrap'
|
|
1241
|
+
}, children: [allExpanded ? _jsx(IconChevronRight, { fontSize: 14 }) : _jsx(IconChevronDown, { fontSize: 14 }), _jsx("span", { children: allExpanded ? SDKUI_Localizator.CollapseAll : SDKUI_Localizator.ExpandAll })] }) })), _jsx("div", { style: { flex: 1, minHeight: 0, overflow: 'auto' }, children: _jsx(TMTreeView, { dataSource: mergedTreeData, itemRender: finalItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: handleDataChanged, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, itemsPerPage: 100, onSelectionChanged: handleSelectedItemsChanged, onItemContextMenu: onItemContextMenu }) }), showExpansionWaitPanel && (_jsx(TMWaitPanel, { title: isForMaster ? 'Caricamento documenti master' : 'Caricamento documenti dettaglio', showPrimary: true, textPrimary: expansionWaitPanelText, valuePrimary: expansionWaitPanelValue, maxValuePrimary: expansionWaitPanelMaxValue, isCancelable: true, abortController: expansionAbortController, onAbortClick: (abortController) => {
|
|
1173
1242
|
setTimeout(() => {
|
|
1174
1243
|
abortController?.abort();
|
|
1175
1244
|
}, 100);
|