@topconsultnpm/sdkui-react-beta 6.12.63 → 6.12.65

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.
@@ -2,15 +2,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { useEffect, useMemo, useState } from 'react';
3
3
  import styled from 'styled-components';
4
4
  import TMDcmtPreview from './TMDcmtPreview';
5
- import { ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutModes, LocalStorageService, MetadataDataTypes, ResultTypes, SDK_Globals, SystemMIDsAsNumber, TemplateTIDs, UpdateEngineByID, ValidationItem } from '@topconsultnpm/sdk-ts-beta';
5
+ import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutModes, LocalStorageService, MetadataDataTypes, ResultTypes, SDK_Globals, SystemMIDsAsNumber, TemplateTIDs, UpdateEngineByID, ValidationItem } from '@topconsultnpm/sdk-ts-beta';
6
6
  import { ContextMenu } from 'devextreme-react';
7
7
  import { WorkFlowApproveRejectPopUp, WorkFlowOperationButtons, WorkFlowReAssignPopUp } from '../workflow/TMWorkflowPopup';
8
- import { FormModes } from '../../../ts';
8
+ import { DownloadTypes, FormModes } from '../../../ts';
9
9
  import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
10
10
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
11
11
  import { handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
12
12
  import { genUniqueId, IconCloseCircle, IconShow, SDKUI_Localizator, IconBoard, IconDcmtTypeSys, IconDataList, IconDetailDcmts, svgToString, IconDownload, IconHide, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo } from '../../../helper';
13
- import { hasDetailRelations, hasMasterRelations } from '../../../helper/dcmtsHelper';
13
+ import { hasDetailRelations, hasMasterRelations, isXMLFileExt } from '../../../helper/dcmtsHelper';
14
14
  import { TMColors } from '../../../utils/theme';
15
15
  import { StyledFormButtonsContainer, StyledModalContainer, StyledToolbarCardContainer } from '../../base/Styled';
16
16
  import ShowAlert from '../../base/TMAlert';
@@ -28,6 +28,7 @@ import TMShowAllOrMaxItemsButton from '../../base/TMShowAllOrMaxItemsButton';
28
28
  import TMFileUploader from '../../features/documents/TMFileUploader';
29
29
  import TMMasterDetailDcmts from './TMMasterDetailDcmts';
30
30
  import TMDcmtBlog from './TMDcmtBlog';
31
+ import { useInputAttachmentsDialog } from '../../../hooks/useInputDialog';
31
32
  let abortControllerLocal = new AbortController();
32
33
  //#endregion
33
34
  const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes.Update, onClose, onSavedAsyncCallback, TID, DID, formMode = FormModes.Update, canNext, canPrev, count, itemIndex, onNext, onPrev, customRightSidebarItems = [], allowNavigation = true, allowRelations = true, isClosable = false, showDcmtForm = true, showDcmtFormSidebar = true, showPreview = false, showBoard = false, showSysMetadata = false, onClosePreview }) => {
@@ -69,6 +70,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
69
70
  const [dcmtFile, setDcmtFile] = useState(null);
70
71
  const [focusedMetadataValue, setFocusedMetadataValue] = useState();
71
72
  const [showAll, setShowAll] = useState(false);
73
+ const { openConfirmAttachmentsDialog, ConfirmAttachmentsDialog } = useInputAttachmentsDialog();
72
74
  const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync } = useDcmtOperations();
73
75
  const deviceType = useDeviceType();
74
76
  const isOpenMiddlePanel = () => isOpenSysMetadata || isOpenBoard || isOpenTags || isOpenDistinctValues || isOpenFormulaEditor;
@@ -208,9 +210,10 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
208
210
  const handleRemoveItem = (tid, did) => {
209
211
  setSecondaryMasterDcmts((prevItems) => prevItems.filter(item => item.TID !== tid && item.DID !== did));
210
212
  };
211
- const getDcmts = () => { return [{ TID: TID, DID: DID }]; };
213
+ const getDcmts = () => { return [{ TID: currentDcmt?.tid, DID: currentDcmt?.did, FILEEXT: currentDcmt?.fileExt }]; };
212
214
  const commandsMenuItems = [
213
- { icon: svgToString(_jsx(IconDownload, {})), operationType: 'singleRow', text: "Download file", onClick: async () => await downloadDcmtsAsync(getDcmts()) },
215
+ { icon: svgToString(_jsx(IconDownload, {})), operationType: 'singleRow', disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes, text: "Download file", onClick: async () => await downloadDcmtsAsync(getDcmts(), DownloadTypes.Dcmt) },
216
+ { icon: svgToString(_jsx(IconDownload, {})), operationType: 'singleRow', disabled: !isXMLFileExt(currentDcmt?.fileExt), text: "Download allegati XML", onClick: async () => await downloadDcmtsAsync(getDcmts(), DownloadTypes.Attachment, openConfirmAttachmentsDialog) },
214
217
  { icon: svgToString(showAdvancedMenu ? _jsx(IconHide, {}) : _jsx(IconShow, {})), operationType: 'singleRow', text: showAdvancedMenu ? SDKUI_Localizator.StandardMode : SDKUI_Localizator.ExpertMode, onClick: () => setShowAdvancedMenu(!showAdvancedMenu) },
215
218
  ];
216
219
  const formToolbar = _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [canPrev != undefined && _jsx("p", { style: { backgroundColor: `white`, color: TMColors.primaryColor, textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${itemIndex}/${count}` }), canPrev != undefined && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', iconColor: 'white', isModified: calcIsModified(formData, formDataOrig), formMode: formMode, canPrev: canPrev, onPrev: onPrev }), canNext != undefined && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', iconColor: 'white', isModified: calcIsModified(formData, formDataOrig), formMode: formMode, canNext: canNext, onNext: onNext }), layoutMode === LayoutModes.Update && _jsx(IconMenuVertical, { id: `commands-detail-${id}`, color: 'white', cursor: 'pointer' }), layoutMode === LayoutModes.Update && _jsx(ContextMenu, { showEvent: 'click', dataSource: commandsMenuItems, target: `#commands-detail-${id}` })] });
@@ -478,7 +481,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
478
481
  break;
479
482
  }
480
483
  } }), _jsxs(StyledFormButtonsContainer, { children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 10 }, children: [fromDTD?.templateTID === TemplateTIDs.WF_WIApprView && _jsx(WorkFlowOperationButtons, { onApprove: () => setShowApprovePopup(true), onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), isInDcmtForm: true }), _jsx("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '8px' }, children: layoutMode === LayoutModes.Update ? _jsxs(_Fragment, { children: [_jsx(TMSaveFormButtonSave, { showTooltip: false, btnStyle: 'advanced', advancedColor: '#f09c0a', isModified: isModified, formMode: formMode, errorsCount: validationItems.filter(o => o.ResultType == ResultTypes.ERROR).length, onSaveAsync: confirmActionPopup }), _jsx(TMSaveFormButtonUndo, { btnStyle: 'toolbar', showTooltip: true, color: 'primary', isModified: isModified, formMode: formMode, onUndo: onUndoHandler })] }) :
481
- _jsxs(_Fragment, { children: [_jsx(TMButton, { disabled: archiveBtnDisabled, btnStyle: 'advanced', icon: _jsx(IconBoxArchiveIn, {}), showTooltip: false, caption: 'Archivia', advancedColor: TMColors.success, onClick: confirmActionPopup }), _jsx(TMButton, { disabled: !clearFormBtnDisabled, btnStyle: 'advanced', icon: _jsx(IconClear, {}), showTooltip: false, caption: 'Pulisci', advancedColor: TMColors.tertiary, onClick: clearFormHandler }), DID && _jsx(TMButton, { disabled: undoBtnDisabled, btnStyle: 'advanced', icon: _jsx(IconUndo, {}), width: '150px', showTooltip: false, caption: 'Annulla modifiche', advancedColor: TMColors.tertiary, onClick: onUndoHandler })] }) })] }), totalItems > listMaxItems && _jsx(TMShowAllOrMaxItemsButton, { showAll: showAll, dataSourceLength: totalItems, onClick: () => { setShowAll(!showAll); } })] }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, TID: TID, DID: DID, op: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, TID: TID, DID: DID, op: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, TID: TID, DID: DID, onClose: () => setShowReAssignPopup(false) })] }) }) }), isOpenPreview || isOpenMiddlePanel() ?
484
+ _jsxs(_Fragment, { children: [_jsx(TMButton, { disabled: archiveBtnDisabled, btnStyle: 'advanced', icon: _jsx(IconBoxArchiveIn, {}), showTooltip: false, caption: 'Archivia', advancedColor: TMColors.success, onClick: confirmActionPopup }), _jsx(TMButton, { disabled: !clearFormBtnDisabled, btnStyle: 'advanced', icon: _jsx(IconClear, {}), showTooltip: false, caption: 'Pulisci', advancedColor: TMColors.tertiary, onClick: clearFormHandler }), DID && _jsx(TMButton, { disabled: undoBtnDisabled, btnStyle: 'advanced', icon: _jsx(IconUndo, {}), width: '150px', showTooltip: false, caption: 'Annulla modifiche', advancedColor: TMColors.tertiary, onClick: onUndoHandler })] }) })] }), totalItems > listMaxItems && _jsx(TMShowAllOrMaxItemsButton, { showAll: showAll, dataSourceLength: totalItems, onClick: () => { setShowAll(!showAll); } })] }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, TID: TID, DID: DID, op: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, TID: TID, DID: DID, op: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, TID: TID, DID: DID, onClose: () => setShowReAssignPopup(false) }), _jsx(ConfirmAttachmentsDialog, {})] }) }) }), isOpenPreview || isOpenMiddlePanel() ?
482
485
  _jsx(TMLayoutItem, { children: _jsxs(TMSplitterLayout, { separatorSize: 5, direction: 'horizontal', showSeparator: deviceType !== DeviceType.MOBILE && (isOpenPreview && isOpenMiddlePanel()), start: getSecondarySplitterStartLayout(), min: ['0', '0'], separatorColor: 'transparent', children: [isOpenMiddlePanel()
483
486
  ? _jsx(TMLayoutItem, { children: _jsx(TMToolbarCard, { padding: '0', showHeader: !(isOpenDetails && layoutMode === LayoutModes.Update), color: TMColors.primaryColor, backgroundColor: `${TMColors.primaryColor}25`, title: titleText(), toolbar: middlePanelToolbar, onClose: () => { closeMiddlePanel(); }, children: _jsx(StyledToolbarCardContainer, { children: _jsx(StyledSectionContainer, { children: _jsxs(StyledSidebarItemsContentContainer, { children: [isOpenBoard && layoutMode === LayoutModes.Update &&
484
487
  _jsx(TMDcmtBlog, { tid: TID, did: DID }), isOpenSysMetadata && layoutMode === LayoutModes.Update &&
@@ -160,6 +160,8 @@ const TMSearch = ({ inputTID, inputSqdID, onRefreshAfterAddDcmtToFavs, onTaskCre
160
160
  setMruTIDs(newMruTIDS);
161
161
  } }) }), _jsx(TMSearchQueryPanel, { fromDTD: fromDTD, SQD: currentSQD, isOpenDistinctValuesPanel: showDistinctValuesPanel, rightSidebarItems: rightSidebarItems, onFocusedMetadataChanged: setFocusedTidMid, onRightSidebarItemClick: rightSidebarItemClickHandler, onCloseDistinctValuesPanel: () => setShowDistinctValuesPanel(false), onSearchCompleted: (searchResult, qd) => {
162
162
  setSearchResult(searchResult);
163
+ if (searchResult.length <= 0)
164
+ return;
163
165
  setLastQdSearched(qd);
164
166
  setCurrentSearchView(TMSearchViews.Result);
165
167
  // Salvataggio ultimi 10 TIDs
@@ -63,6 +63,7 @@ const TMSearchQueryPanel = ({ fromDTD, rightSidebarItems, isOpenDistinctValuesPa
63
63
  setQd({ ...qd, where: newWhere });
64
64
  };
65
65
  const searchAsync = async (qdInput, isAdvancedSearch) => {
66
+ onSearchCompleted?.([], undefined); // reset results
66
67
  let searchParams = { isAdvancedSearch: isAdvancedSearch, lastQdParams: lastQdParams, confirmQueryParams: confirmQueryParams, setLastQdParamsCallback: setLastQdParams };
67
68
  let searchResult = await searchByQdAsync(qdInput, searchParams);
68
69
  let dcmtsFound = searchResult?.result?.dcmtsFound ?? 0;
@@ -6,7 +6,7 @@ import { getCommandsMenuItems, getSelectedDcmtsOrFocused } from './TMSearchResul
6
6
  import { ContextMenu } from 'devextreme-react';
7
7
  import { genUniqueId, IconShow, IconBoard, IconDcmtTypeSys, IconDetailDcmts, SDKUI_Localizator, IconTag, IconDetails, IconCommand, IconDelete, IconRefresh, IconMenuVertical, IconDownload, IconSignature, deepCompare, getDataColumnName, searchResultDescriptorToSimpleArray, SDKUI_Globals, IconArchive, IconActivityLog, IconStar, IconFreeSearch, IconChevronDown, searchResultToMetadataValues } from '../../../helper';
8
8
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
9
- import { useInputCvtFormatDialog } from '../../../hooks/useInputDialog';
9
+ import { useInputAttachmentsDialog, useInputCvtFormatDialog } from '../../../hooks/useInputDialog';
10
10
  import { DcmtOperationTypes, FormModes, SearchResultContext } from '../../../ts';
11
11
  import { TMColors } from '../../../utils/theme';
12
12
  import { StyledModalContainer, StyledBadge, StyledMultiViewPanel } from '../../base/Styled';
@@ -84,6 +84,7 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
84
84
  // const [allowMultipleSelection, setAllowMultipleSelection] = useState<boolean>(false);
85
85
  const [isModifiedBatchUpdate, setIsModifiedBatchUpdate] = useState(false);
86
86
  const [confirmFormat, ConfirmFormatDialog] = useInputCvtFormatDialog();
87
+ const { openConfirmAttachmentsDialog, ConfirmAttachmentsDialog } = useInputAttachmentsDialog();
87
88
  const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync } = useDcmtOperations();
88
89
  const deviceType = useDeviceType();
89
90
  let disable = getSelectedDcmtsOrFocused(selectedItems, focusedItem).length === 0;
@@ -224,7 +225,7 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
224
225
  return;
225
226
  if (e.target === 'content') {
226
227
  e.items = e.items || [];
227
- const menuItems = getCommandsMenuItems(fromDTD, selectedItems, focusedItem, context, showFloatingBar, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler);
228
+ const menuItems = getCommandsMenuItems(fromDTD, selectedItems, focusedItem, context, showFloatingBar, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler);
228
229
  e.items.push(...menuItems);
229
230
  }
230
231
  };
@@ -427,7 +428,7 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
427
428
  if (!searchResults || searchResults.length <= 0)
428
429
  return _jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%' }, children: [_jsx(IconBoard, { fontSize: 96 }), _jsx("div", { style: { fontSize: "15px", marginTop: "10px" }, children: SDKUI_Localizator.NoDcmtFound })] });
429
430
  return (_jsx(StyledMultiViewPanel, { "$isVisible": isVisible, children: _jsxs(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: [_jsxs(TMSplitterLayout, { separatorSize: 5, separatorColor: 'transparent', showSeparator: (isOpenPreview || isOpenMiddlePanel() || isOpenBatchUpdate) && deviceType !== DeviceType.MOBILE, start: getPrimarySplitterStartLayout(), min: deviceType !== DeviceType.MOBILE && isOpenDcmtForm ? ['150px', '0'] : ['0', '0'], direction: 'horizontal', children: [_jsx(TMLayoutItem, { children: _jsxs(TMToolbarCard, { toolbar: _jsxs(_Fragment, { children: [context !== SearchResultContext.METADATA_SEARCH && fromDTD?.templateTID === TemplateTIDs.WF_WIApprView && _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), approveDisable: disable, rejectDisable: disable, reassignDisable: disable, infoDisable: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length !== 1 }), (dcmtsReturned != dcmtsFound) && _jsx("p", { style: { backgroundColor: `white`, color: TMColors.primaryColor, textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${dcmtsReturned}/${dcmtsFound} restituiti` }), (context === SearchResultContext.RECENT || context === SearchResultContext.FAVORITES) &&
430
- _jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconDelete, { color: 'white' }), caption: "Rimuovi da " + (context === SearchResultContext.RECENT ? '"Recenti"' : '"Preferiti"'), disabled: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length <= 0, onClick: removeDcmtFromFavsOrRecents }) }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: onRefreshSearchAsync }), _jsx(IconMenuVertical, { id: `commands-header-${id}`, color: 'white', cursor: 'pointer' }), _jsx(CommandsContextMenu, { target: `#commands-header-${id}`, menuItems: getCommandsMenuItems(fromDTD, selectedItems, focusedItem, context, showFloatingBar, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler) })] }), onBack: !isClosable && allowBackButton() ? onBack : undefined, onClose: isClosable && allowBackButton() ? onBack : undefined, items: showSearchResultSidebar ? sideBarItems : undefined, title: getTitleHeader(), showHeader: showToolbarHeader, children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', min: ['0', '0'], showSeparator: showSelector && deviceType !== DeviceType.MOBILE, start: showSelector ? deviceType !== DeviceType.MOBILE ? ['25%', '75%'] : splitterSize : ['0%', '100%'], children: [showSelector ?
431
+ _jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconDelete, { color: 'white' }), caption: "Rimuovi da " + (context === SearchResultContext.RECENT ? '"Recenti"' : '"Preferiti"'), disabled: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length <= 0, onClick: removeDcmtFromFavsOrRecents }) }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: onRefreshSearchAsync }), _jsx(IconMenuVertical, { id: `commands-header-${id}`, color: 'white', cursor: 'pointer' }), _jsx(CommandsContextMenu, { target: `#commands-header-${id}`, menuItems: getCommandsMenuItems(fromDTD, selectedItems, focusedItem, context, showFloatingBar, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler) })] }), onBack: !isClosable && allowBackButton() ? onBack : undefined, onClose: isClosable && allowBackButton() ? onBack : undefined, items: showSearchResultSidebar ? sideBarItems : undefined, title: getTitleHeader(), showHeader: showToolbarHeader, children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', min: ['0', '0'], showSeparator: showSelector && deviceType !== DeviceType.MOBILE, start: showSelector ? deviceType !== DeviceType.MOBILE ? ['25%', '75%'] : splitterSize : ['0%', '100%'], children: [showSelector ?
431
432
  _jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: searchResults, onSelectionChanged: onSearchResultSelectionChanged }) })
432
433
  :
433
434
  _jsx(_Fragment, {}), _jsxs(TMLayoutItem, { children: [_jsx(TMSearchResultGrid
@@ -435,7 +436,7 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
435
436
  , {
436
437
  // allowMultipleSelection={allowMultipleSelection}
437
438
  inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, searchResult: searchResults.length > 1 ? selectedSearchResult : searchResults[0], lastUpdateSearchTime: lastUpdateSearchTime, onDblClick: () => openFormHandler(LayoutModes.Update), onContextMenuPreparing: onContextMenuPreparing, onSelectionChanged: (items) => { setSelectedItems(items); }, onVisibleItemChanged: setVisibleItems, onFocusedItemChanged: setFocusedItem }), allowFloatingBar && showFloatingBar && deviceType !== DeviceType.MOBILE &&
438
- _jsxs(TMFloatingToolbar, { backgroundColor: TMColors.primaryColor, initialLeft: '10px', initialTop: 'calc(100% - 75px)', children: [fromDTD?.perm?.canRetrieveFile === AccessLevels.Yes && _jsx(TMButton, { btnStyle: 'icon', caption: "Download file", disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes, icon: _jsx(IconDownload, { color: 'white' }), onClick: () => { downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem)); } }), _jsx(TMButton, { btnStyle: 'icon', caption: 'Firma e marca', icon: _jsx(IconSignature, { color: 'white' }), onClick: () => { ShowAlert({ message: "TODO Firma e marca ", mode: 'info', title: `${"TODO"}`, duration: 3000 }); } }), _jsx(IconMenuVertical, { id: `commands-floating-${id}`, color: 'white', cursor: 'pointer' }), _jsx(CommandsContextMenu, { target: `#commands-floating-${id}`, menuItems: getCommandsMenuItems(fromDTD, selectedItems, focusedItem, context, showFloatingBar, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler) })] })] })] }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onUpdate: onUpdate, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), op: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onUpdate: onUpdate, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), op: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onUpdate: onUpdate, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), onClose: () => setShowReAssignPopup(false) })] }), _jsx(ConfirmFormatDialog, {})] }) }), isOpenBatchUpdate ?
439
+ _jsxs(TMFloatingToolbar, { backgroundColor: TMColors.primaryColor, initialLeft: '10px', initialTop: 'calc(100% - 75px)', children: [fromDTD?.perm?.canRetrieveFile === AccessLevels.Yes && _jsx(TMButton, { btnStyle: 'icon', caption: "Download file", disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes, icon: _jsx(IconDownload, { color: 'white' }), onClick: () => { downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem)); } }), _jsx(TMButton, { btnStyle: 'icon', caption: 'Firma e marca', icon: _jsx(IconSignature, { color: 'white' }), onClick: () => { ShowAlert({ message: "TODO Firma e marca ", mode: 'info', title: `${"TODO"}`, duration: 3000 }); } }), _jsx(IconMenuVertical, { id: `commands-floating-${id}`, color: 'white', cursor: 'pointer' }), _jsx(CommandsContextMenu, { target: `#commands-floating-${id}`, menuItems: getCommandsMenuItems(fromDTD, selectedItems, focusedItem, context, showFloatingBar, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler) })] })] })] }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onUpdate: onUpdate, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), op: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onUpdate: onUpdate, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), op: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onUpdate: onUpdate, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), onClose: () => setShowReAssignPopup(false) })] }), _jsx(ConfirmFormatDialog, {}), _jsx(ConfirmAttachmentsDialog, {})] }) }), isOpenBatchUpdate ?
439
440
  _jsx(StyledModalContainer, { style: { backgroundColor: 'white' }, children: _jsx(TMBatchUpdateForm, { inputDcmts: getSelectionDcmtInfo(), TID: focusedItem ? focusedItem?.TID : selectedItems[0]?.TID, DID: focusedItem ? focusedItem?.DID : selectedItems[0]?.DID, onBack: () => setIsOpenBatchUpdate(false), onSavedCallbackAsync: async () => {
440
441
  setIsOpenBatchUpdate(false);
441
442
  setIsModifiedBatchUpdate(false);
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { DcmtTypeDescriptor, FileFormats, LayoutModes, RecentCategories } from '@topconsultnpm/sdk-ts-beta';
2
+ import { DcmtTypeDescriptor, FileDescriptor, FileFormats, LayoutModes, RecentCategories } from '@topconsultnpm/sdk-ts-beta';
3
3
  import { TMDataGridContextMenuItem } from '../../base/TMDataGrid';
4
- import { DcmtInfo, DcmtOperationTypes, SearchResultContext } from '../../../ts';
4
+ import { DcmtInfo, DcmtOperationTypes, DownloadTypes, SearchResultContext } from '../../../ts';
5
5
  export declare const getSelectedDcmtsOrFocused: (selectedItems: Array<any>, focusedItem: any, category?: RecentCategories, fileFormat?: FileFormats) => DcmtInfo[];
6
- export declare const getCommandsMenuItems: (dtd: DcmtTypeDescriptor | undefined, selectedItems: Array<any>, focusedItem: any, context: SearchResultContext, showFloatingBar: boolean, setShowFloatingBar: React.Dispatch<React.SetStateAction<boolean>>, openFormHandler: (layoutMode: LayoutModes) => void, downloadDcmtsAsync: (inputDcmts: DcmtInfo[] | undefined) => Promise<void>, runOperationAsync: (inputDcmts: DcmtInfo[] | undefined, dcmtOperationType: DcmtOperationTypes, actionAfterOperationAsync?: () => Promise<void>) => Promise<void>, onRefreshSearchAsync: (() => Promise<void>) | undefined, onRefreshDataRowsAsync: (() => Promise<void>) | undefined, onRefreshAfterAddDcmtToFavs: (() => void) | undefined, confirmFormat: () => Promise<FileFormats>, openTaskFormHandler: (value: boolean) => void, openDetailDcmtsFormHandler: (value: boolean) => void, openMasterDcmtsFormHandler: (value: boolean) => void, openBatchUpdateFormHandler: (value: boolean) => void) => Array<TMDataGridContextMenuItem>;
6
+ export declare const getCommandsMenuItems: (dtd: DcmtTypeDescriptor | undefined, selectedItems: Array<any>, focusedItem: any, context: SearchResultContext, showFloatingBar: boolean, setShowFloatingBar: React.Dispatch<React.SetStateAction<boolean>>, openFormHandler: (layoutMode: LayoutModes) => void, downloadDcmtsAsync: (inputDcmts: DcmtInfo[] | undefined, downloadType: DownloadTypes, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>) => Promise<void>, runOperationAsync: (inputDcmts: DcmtInfo[] | undefined, dcmtOperationType: DcmtOperationTypes, actionAfterOperationAsync?: () => Promise<void>) => Promise<void>, onRefreshSearchAsync: (() => Promise<void>) | undefined, onRefreshDataRowsAsync: (() => Promise<void>) | undefined, onRefreshAfterAddDcmtToFavs: (() => void) | undefined, confirmFormat: () => Promise<FileFormats>, confirmAttachments: (list: FileDescriptor[]) => Promise<string[] | undefined>, openTaskFormHandler: (value: boolean) => void, openDetailDcmtsFormHandler: (value: boolean) => void, openMasterDcmtsFormHandler: (value: boolean) => void, openBatchUpdateFormHandler: (value: boolean) => void) => Array<TMDataGridContextMenuItem>;
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { AccessLevels, AccessLevelsEx, AppModules, FileFormats, LayoutModes, SDK_Globals } from '@topconsultnpm/sdk-ts-beta';
3
- import { IconActivity, IconArchiveDoc, IconBatchUpdate, IconCheckFile, IconCloseCircle, IconConvertFilePdf, IconDelete, IconDotsVerticalCircleOutline, IconDownload, IconFileDots, IconHide, IconInfo, IconPreview, IconRelation, IconSearch, IconShow, IconSignature, IconStar, IconSubstFile, IconUndo, SDKUI_Localizator, svgToString } from '../../../helper';
3
+ import { IconActivity, IconArchiveDoc, IconBatchUpdate, IconCheckFile, IconCloseCircle, IconConvertFilePdf, IconDelete, IconDotsVerticalCircleOutline, IconDownload, IconExportTo, IconFileDots, IconHide, IconInfo, IconPreview, IconRelation, IconSearch, IconShow, IconSignature, IconStar, IconSubstFile, IconUndo, SDKUI_Localizator, svgToString } from '../../../helper';
4
4
  import ShowAlert from '../../base/TMAlert';
5
5
  import { TMMessageBoxManager, ButtonNames, TMExceptionBoxManager } from '../../base/TMPopUp';
6
6
  import TMSpinner from '../../base/TMSpinner';
7
- import { DcmtOperationTypes, SearchResultContext } from '../../../ts';
7
+ import { DcmtOperationTypes, DownloadTypes, SearchResultContext } from '../../../ts';
8
+ import { isXMLFileExt } from '../../../helper/dcmtsHelper';
8
9
  const disabledForSingleRow = (selectedItems, focusedItem) => {
9
10
  return selectedItems.length > 1 || focusedItem === undefined;
10
11
  };
@@ -23,7 +24,7 @@ export const getSelectedDcmtsOrFocused = (selectedItems, focusedItem, category,
23
24
  }
24
25
  return [];
25
26
  };
26
- export const getCommandsMenuItems = (dtd, selectedItems, focusedItem, context, showFloatingBar, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, onRefreshDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler) => {
27
+ export const getCommandsMenuItems = (dtd, selectedItems, focusedItem, context, showFloatingBar, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, onRefreshDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, confirmAttachments, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler) => {
27
28
  return [
28
29
  {
29
30
  icon: svgToString(_jsx(IconFileDots, {})),
@@ -120,13 +121,13 @@ export const getCommandsMenuItems = (dtd, selectedItems, focusedItem, context, s
120
121
  icon: svgToString(_jsx(IconDownload, {})),
121
122
  operationType: 'multiRow',
122
123
  disabled: dtd?.perm?.canRetrieveFile !== AccessLevels.Yes ? true : disabledForMultiRow(selectedItems, focusedItem),
123
- text: "Download file", onClick: () => downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem))
124
+ text: "Download file", onClick: () => downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem), DownloadTypes.Dcmt)
124
125
  },
125
126
  {
126
127
  icon: svgToString(_jsx(IconDownload, {})),
127
128
  operationType: 'singleRow',
128
- disabled: dtd?.perm?.canRetrieveFile !== AccessLevels.Yes ? true : disabledForSingleRow(selectedItems, focusedItem),
129
- text: "Download allegati XML", onClick: () => downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem))
129
+ disabled: !isXMLFileExt(getSelectedDcmtsOrFocused(selectedItems, focusedItem)?.[0]?.FILEEXT) ? true : disabledForSingleRow(selectedItems, focusedItem),
130
+ text: "Download allegati XML", onClick: () => downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem), DownloadTypes.Attachment, confirmAttachments)
130
131
  },
131
132
  {
132
133
  icon: svgToString(_jsx(IconArchiveDoc, {})),
@@ -334,13 +335,13 @@ export const getCommandsMenuItems = (dtd, selectedItems, focusedItem, context, s
334
335
  icon: svgToString(_jsx(IconDotsVerticalCircleOutline, {})),
335
336
  text: "Altro",
336
337
  items: [
337
- // {
338
- // icon: svgToString(<IconExportTo />),
339
- // text: "Esporta in...",
340
- // operationType: 'multiRow',
341
- // disabled: fromDatagrid ? false : disabledForMultiRow(selectedItems, focusedItem),
342
- // onClick: () => ShowAlert({ message: "TODO Esporta in", mode: 'info', title: `${"TODO"}`, duration: 3000 })
343
- // },
338
+ {
339
+ icon: svgToString(_jsx(IconExportTo, {})),
340
+ text: "Esporta in...",
341
+ operationType: 'multiRow',
342
+ disabled: false,
343
+ onClick: () => ShowAlert({ message: "TODO Esporta in", mode: 'info', title: `${"TODO"}`, duration: 3000 })
344
+ },
344
345
  // {
345
346
  // icon: svgToString(<IconShow />),
346
347
  // text: "Mostra footer",
@@ -231,6 +231,7 @@ export declare class SDKUI_Localizator {
231
231
  static get NoDcmtFound(): "Kein Dokument gefunden" | "No documents found" | "Ningún documento encontrado" | "Pas de documents trouvés" | "Nenhum documento encontrado" | "Nessun documento trovato";
232
232
  static get NoMessages(): string;
233
233
  static get NoMessagesFound(): string;
234
+ static get NoResultsFound(): string;
234
235
  static get NoneSelection(): "Keine Auswahl" | "No selection" | "Ninguna selección" | "Pas de sélections" | "Nenhuma seleção" | "Nessuna selezione";
235
236
  static get OfSystem(): "Des Systems" | "Of system" | "Del sistema" | "Du système" | "Do sistema" | "Di sistema";
236
237
  static get OldPassword(): "Altes Kennwort" | "Old password" | "Contraseña anterior" | "Ancien mot de passe" | "Senha Antiga" | "Password vecchia";
@@ -2261,6 +2261,16 @@ export class SDKUI_Localizator {
2261
2261
  default: return "Nessun messaggio trovato";
2262
2262
  }
2263
2263
  }
2264
+ static get NoResultsFound() {
2265
+ switch (this._cultureID) {
2266
+ case CultureIDs.De_DE: return "Kein Ergebnis gefunden";
2267
+ case CultureIDs.En_US: return "No results found";
2268
+ case CultureIDs.Es_ES: return "No se encontraron resultados";
2269
+ case CultureIDs.Fr_FR: return "Aucun résultat trouvé";
2270
+ case CultureIDs.Pt_PT: return "Nenhum resultado encontrado";
2271
+ default: return "Nessun risultato trovato";
2272
+ }
2273
+ }
2264
2274
  static get NoneSelection() {
2265
2275
  switch (this._cultureID) {
2266
2276
  case CultureIDs.De_DE: return "Keine Auswahl";
@@ -2,3 +2,4 @@
2
2
  export declare const hasDetailRelations: (mTID: number | undefined) => Promise<boolean>;
3
3
  /** Check if dcmtType (mTID) has configured Master or Many-to-Many relations */
4
4
  export declare const hasMasterRelations: (mTID: number | undefined) => Promise<boolean>;
5
+ export declare const isXMLFileExt: (fileExt: string | undefined) => boolean;
@@ -13,3 +13,13 @@ export const hasMasterRelations = async (mTID) => {
13
13
  let rdlManyToMany = allRelations?.filter(o => o.relationType == RelationTypes.ManyToMany && (o.masterTID == mTID || o.detailTID == mTID)) ?? [];
14
14
  return rdlManyToMany.length > 0 || rdlOneToMany.length > 0;
15
15
  };
16
+ export const isXMLFileExt = (fileExt) => {
17
+ const fileExtension = fileExt?.toLowerCase() ?? '';
18
+ switch (fileExtension) {
19
+ case 'xml':
20
+ case 'xml.p7m':
21
+ case 'xml.p7m.ts':
22
+ case 'xml.p7m.tsd': return true;
23
+ default: return false;
24
+ }
25
+ };
@@ -21,6 +21,7 @@ export declare function getTIDByMID(mid: number | undefined, defaultTid?: number
21
21
  export declare const getSystemMetadata: (withPerm?: boolean) => MetadataDescriptor[];
22
22
  export declare function deepCompare(obj1: any, obj2: any): boolean;
23
23
  export declare const extensionHandler: (fileExt: string | undefined) => FileExtensionHandler;
24
+ export declare const downloadBase64File: (base64Data: string, fileName: string) => void;
24
25
  export declare const canNext: (visibleItems: any[], selectedItems: any[]) => boolean;
25
26
  export declare const getNext: (visibleItems: any[], selectedItems: any[]) => any;
26
27
  export declare const canPrev: (visibleItems: any[], selectedItems: any[]) => boolean;
@@ -473,6 +473,26 @@ export const extensionHandler = (fileExt) => {
473
473
  default: return FileExtensionHandler.NONE;
474
474
  }
475
475
  };
476
+ export const downloadBase64File = (base64Data, fileName) => {
477
+ // Decodifica la stringa base64 in un Blob
478
+ const byteCharacters = atob(base64Data);
479
+ const byteNumbers = new Array(byteCharacters.length).fill(0).map((_, i) => byteCharacters.charCodeAt(i));
480
+ const byteArray = new Uint8Array(byteNumbers);
481
+ const blob = new Blob([byteArray], { type: 'application/octet-stream' });
482
+ // Crea un URL per il Blob
483
+ const blobUrl = URL.createObjectURL(blob);
484
+ // Crea un link di download
485
+ const link = document.createElement('a');
486
+ link.href = blobUrl;
487
+ link.download = fileName;
488
+ // Simula un click sul link
489
+ document.body.appendChild(link);
490
+ link.click();
491
+ // Rimuovi il link dal DOM
492
+ document.body.removeChild(link);
493
+ // Libera l'URL del Blob
494
+ URL.revokeObjectURL(blobUrl);
495
+ };
476
496
  //#region Form, Page Helpers
477
497
  export const canNext = (visibleItems, selectedItems) => {
478
498
  if (!visibleItems)
@@ -1,5 +1,5 @@
1
- import { RetrieveFileOptions } from '@topconsultnpm/sdk-ts-beta';
2
- import { DcmtInfo, DcmtOperationTypes } from '../ts';
1
+ import { RetrieveFileOptions, FileDescriptor } from '@topconsultnpm/sdk-ts-beta';
2
+ import { DcmtInfo, DcmtOperationTypes, DownloadTypes } from '../ts';
3
3
  export declare function useDcmtOperations(): {
4
4
  abortController: AbortController;
5
5
  showWaitPanel: boolean;
@@ -12,7 +12,7 @@ export declare function useDcmtOperations(): {
12
12
  waitPanelTextSecondary: string;
13
13
  waitPanelValueSecondary: number;
14
14
  waitPanelMaxValueSecondary: number;
15
- downloadDcmtsAsync: (inputDcmts: DcmtInfo[] | undefined) => Promise<void>;
15
+ downloadDcmtsAsync: (inputDcmts: DcmtInfo[] | undefined, downloadType?: DownloadTypes, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>) => Promise<void>;
16
16
  getDcmtFileAsync: (inputDcmt: DcmtInfo | undefined, rfo: RetrieveFileOptions, operationTitle: string, keepWaitPanelPrimary: boolean) => Promise<{
17
17
  file: File | undefined;
18
18
  isFromCache: boolean;
@@ -1,10 +1,11 @@
1
1
  import { useState } from 'react';
2
2
  import { LocalizeDcmtOperationTypes } from '../helper/Enum_Localizator';
3
3
  import { SDK_Globals, RetrieveFileOptions, DcmtOpers, ResultTypes, RecentCategories, MetadataDataTypes, MetadataDataDomains, DataListCacheService } from '@topconsultnpm/sdk-ts-beta';
4
- import { ShowAlert, TMResultManager, FormulaHelper } from '../components';
5
- import { Globalization, getExceptionMessage, dialogConfirmOperation, extensionHandler } from '../helper';
6
- import { DcmtOperationTypes, FileExtensionHandler } from '../ts';
4
+ import { ShowAlert, TMResultManager, FormulaHelper, TMExceptionBoxManager, TMSpinner } from '../components';
5
+ import { Globalization, getExceptionMessage, dialogConfirmOperation, extensionHandler, downloadBase64File } from '../helper';
6
+ import { DcmtOperationTypes, DownloadTypes, FileExtensionHandler } from '../ts';
7
7
  import { useFileDialog } from './useInputDialog';
8
+ import { isXMLFileExt } from '../helper/dcmtsHelper';
8
9
  let abortController = new AbortController();
9
10
  const dcmtsFileCacheDownload = new Map();
10
11
  const dcmtsFileCachePreview = new Map();
@@ -21,7 +22,7 @@ export function useDcmtOperations() {
21
22
  const [waitPanelValueSecondary, setWaitPanelValueSecondary] = useState(0);
22
23
  const [waitPanelMaxValueSecondary, setWaitPanelMaxValueSecondary] = useState(0);
23
24
  const { OpenFileDialog } = useFileDialog();
24
- const downloadDcmtsAsync = async (inputDcmts) => {
25
+ const _downloadDcmtsAsync = async (inputDcmts) => {
25
26
  if (inputDcmts === undefined)
26
27
  return;
27
28
  if (inputDcmts.length <= 0)
@@ -99,6 +100,73 @@ export function useDcmtOperations() {
99
100
  setShowWaitPanel(false);
100
101
  TMResultManager.show(result, operationTitle, "TID", "DID");
101
102
  };
103
+ const _downloadAttachmentsAsync = async (inputDcmts, confirmAttachments) => {
104
+ if (inputDcmts === undefined)
105
+ return;
106
+ if (inputDcmts.length !== 1)
107
+ return;
108
+ if (!isXMLFileExt(inputDcmts[0].FILEEXT)) {
109
+ ShowAlert({ message: 'Il file non è in formato XML', mode: 'warning', duration: 5000, title: 'Download Allegati' });
110
+ return;
111
+ }
112
+ let operationTitle = 'Download Allegati XML';
113
+ const rfo = new RetrieveFileOptions();
114
+ rfo.retrieveReason = DcmtOpers.ShowFile;
115
+ let result = [];
116
+ try {
117
+ TMSpinner.show({ description: 'Recupero allegati...' });
118
+ let files = await SDK_Globals.tmSession?.NewSearchEngine().RetrieveAttachmentsAsync(inputDcmts[0].TID, inputDcmts[0].DID, -1, 1);
119
+ TMSpinner.hide();
120
+ result.push({ rowIndex: 0, id1: inputDcmts[0].TID, id2: inputDcmts[0].DID, resultType: ResultTypes.SUCCESS });
121
+ if (!files || files.length === 0) {
122
+ ShowAlert({ message: 'Nessun allegato trovato', mode: 'warning', duration: 5000, title: 'Download Allegati' });
123
+ return;
124
+ }
125
+ if (files.length === 1) {
126
+ const file = files[0];
127
+ if (file?.base64Content)
128
+ downloadBase64File(file.base64Content, file.name ?? '');
129
+ }
130
+ else {
131
+ // Open a dialog for the user to select files
132
+ const selectedFiles = await confirmAttachments?.(files);
133
+ if (!selectedFiles)
134
+ return;
135
+ if (selectedFiles.length === 0) {
136
+ ShowAlert({ message: 'Nessun file selezionato', mode: 'info', duration: 3000, title: 'Download Allegati' });
137
+ return;
138
+ }
139
+ // Download the selected files
140
+ for (let i = 0; i < selectedFiles.length; i++) {
141
+ if (abortController.signal.aborted) {
142
+ result.push({ rowIndex: i, id1: inputDcmts[i].TID, id2: inputDcmts[i].DID, resultType: ResultTypes.WARNING, description: `Operazione interrotta. Elaborati ${i + 1} documenti` });
143
+ break;
144
+ }
145
+ let fd = files.find(f => f.name === selectedFiles[i]);
146
+ if (fd?.base64Content) {
147
+ downloadBase64File(fd.base64Content, fd.name ?? '');
148
+ }
149
+ }
150
+ }
151
+ TMResultManager.show(result, operationTitle, "TID", "DID");
152
+ }
153
+ catch (ex) {
154
+ TMSpinner.hide();
155
+ const err = ex;
156
+ if (err.name === 'CanceledError') {
157
+ ShowAlert({ message: err.message, mode: 'warning', duration: 3000, title: 'Abort' });
158
+ }
159
+ else
160
+ TMExceptionBoxManager.show({ exception: err });
161
+ }
162
+ };
163
+ const downloadDcmtsAsync = async (inputDcmts, downloadType = DownloadTypes.Attachment, confirmAttachments) => {
164
+ switch (downloadType) {
165
+ case DownloadTypes.Dcmt: return await _downloadDcmtsAsync(inputDcmts);
166
+ case DownloadTypes.Attachment: return await _downloadAttachmentsAsync(inputDcmts, confirmAttachments);
167
+ default: return await _downloadDcmtsAsync(inputDcmts);
168
+ }
169
+ };
102
170
  const uploadDcmtsAsync = async (inputDcmts, operationTitle, operType, actionAfterOperationAsync) => {
103
171
  if (inputDcmts === undefined)
104
172
  return;
@@ -1,5 +1,9 @@
1
- import { FileFormats } from '@topconsultnpm/sdk-ts-beta';
1
+ import { FileDescriptor, FileFormats } from '@topconsultnpm/sdk-ts-beta';
2
2
  export declare const useInputCvtFormatDialog: () => [() => Promise<FileFormats>, () => JSX.Element];
3
3
  export declare const useFileDialog: () => {
4
4
  OpenFileDialog: () => Promise<File | undefined>;
5
5
  };
6
+ export declare const useInputAttachmentsDialog: () => {
7
+ openConfirmAttachmentsDialog: (list: FileDescriptor[]) => Promise<string[] | undefined>;
8
+ ConfirmAttachmentsDialog: () => import("react/jsx-runtime").JSX.Element | null;
9
+ };
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
3
  import { FileFormats } from '@topconsultnpm/sdk-ts-beta';
4
- import { TMModal, TMRadioButton, TMButton } from "../components";
4
+ import { TMModal, TMRadioButton, TMButton, TMChooserForm } from "../components";
5
5
  import { SDKUI_Localizator, IconApply, IconCloseOutline } from "../helper";
6
6
  import { TMColors } from "../utils/theme";
7
7
  const formats = [
@@ -71,3 +71,35 @@ export const useFileDialog = () => {
71
71
  });
72
72
  return { OpenFileDialog };
73
73
  };
74
+ export const useInputAttachmentsDialog = () => {
75
+ const [promise, setPromise] = useState(null);
76
+ const [open, setOpen] = useState(false);
77
+ const [inputList, setInputList] = useState([]);
78
+ const handleClose = () => {
79
+ setOpen(false);
80
+ setPromise(null);
81
+ };
82
+ const handleConfirm = (selectedValues) => {
83
+ promise?.resolve(selectedValues);
84
+ handleClose();
85
+ };
86
+ const handleCancel = () => {
87
+ promise?.resolve(undefined);
88
+ handleClose();
89
+ };
90
+ const ConfirmAttachmentsDialog = () => {
91
+ return (open ? (_jsx(TMChooserForm, { title: "Seleziona allegati", dataSource: inputList, allowMultipleSelection: true, hasShowId: false, hideRefresh: true, showDefaultColumns: false, keyName: "name", width: "650px", height: "400px", columns: [
92
+ { dataField: "name", caption: SDKUI_Localizator.Name },
93
+ { dataField: "ext", caption: SDKUI_Localizator.Extension },
94
+ { dataField: "size", caption: SDKUI_Localizator.Size },
95
+ ], onClose: handleCancel, onChoose: handleConfirm })) : null);
96
+ };
97
+ const openConfirmAttachmentsDialog = (list) => {
98
+ setInputList(list);
99
+ setOpen(true);
100
+ return new Promise((resolve) => {
101
+ setPromise({ resolve });
102
+ });
103
+ };
104
+ return { openConfirmAttachmentsDialog, ConfirmAttachmentsDialog };
105
+ };
package/lib/index.js CHANGED
@@ -7,3 +7,6 @@ export * from './hooks/useOutsideClick';
7
7
  export * from './hooks/useQueryParametersDialog';
8
8
  export * from './hooks/useDcmtOperations';
9
9
  export * from './services';
10
+ import config from 'devextreme/core/config';
11
+ // DevExtreme License Key (valid for v24.2 and earlier versions)
12
+ config({ licenseKey: 'ewogICJmb3JtYXQiOiAxLAogICJjdXN0b21lcklkIjogIjE1ODg1NDc4LTNjNTItNGUzYy1hNDI1LTU5NjAzMzQ0ZDVjMyIsCiAgIm1heFZlcnNpb25BbGxvd2VkIjogMjQyCn0=.TgAR2q7mkzFeXFXJEZ/gbaQ6BKwr+bQp6soLuoI7qfdAoMmM2LON4ApYs5sW7m67kMzun8PSOdTkOlvvOr/PgXivZsGP5jix6zSv57UWR3JHoFYA2LLFluu2x4LFtTxoJdDaaA==' });
package/lib/ts/types.d.ts CHANGED
@@ -36,6 +36,10 @@ export declare enum DcmtOperationTypes {
36
36
  FreeSearchPurge = 12,
37
37
  BatchUpdate = 13
38
38
  }
39
+ export declare enum DownloadTypes {
40
+ Dcmt = "Dcmt",
41
+ Attachment = "Attachment"
42
+ }
39
43
  export declare enum SearchResultContext {
40
44
  METADATA_SEARCH = "metadataSearch",
41
45
  WORKFLOW_APPROVE = "workflowApprove",
package/lib/ts/types.js CHANGED
@@ -38,6 +38,11 @@ export var DcmtOperationTypes;
38
38
  DcmtOperationTypes[DcmtOperationTypes["FreeSearchPurge"] = 12] = "FreeSearchPurge";
39
39
  DcmtOperationTypes[DcmtOperationTypes["BatchUpdate"] = 13] = "BatchUpdate";
40
40
  })(DcmtOperationTypes || (DcmtOperationTypes = {}));
41
+ export var DownloadTypes;
42
+ (function (DownloadTypes) {
43
+ DownloadTypes["Dcmt"] = "Dcmt";
44
+ DownloadTypes["Attachment"] = "Attachment";
45
+ })(DownloadTypes || (DownloadTypes = {}));
41
46
  export var SearchResultContext;
42
47
  (function (SearchResultContext) {
43
48
  SearchResultContext["METADATA_SEARCH"] = "metadataSearch";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react-beta",
3
- "version": "6.12.63",
3
+ "version": "6.12.65",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -41,7 +41,7 @@
41
41
  "lib"
42
42
  ],
43
43
  "dependencies": {
44
- "@topconsultnpm/sdk-ts-beta": "^6.12.8",
44
+ "@topconsultnpm/sdk-ts-beta": "6.12.8",
45
45
  "buffer": "^6.0.3",
46
46
  "devextreme": "24.2.6",
47
47
  "devextreme-react": "24.2.6",