@topconsultnpm/sdkui-react 6.22.0-dev2.11 → 6.22.0-dev2.12
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/TMPanel.d.ts +1 -0
- package/lib/components/base/TMPanel.js +79 -20
- package/lib/components/base/TMTreeView.js +6 -1
- package/lib/components/features/documents/TMBatchUpdateForm.js +19 -5
- package/lib/components/features/search/TMSearchResult.d.ts +1 -0
- package/lib/components/features/search/TMSearchResult.js +136 -66
- package/lib/helper/SDKUI_Localizator.d.ts +2 -0
- package/lib/helper/SDKUI_Localizator.js +20 -0
- package/lib/hooks/useDocumentOperations.d.ts +1 -0
- package/lib/hooks/useDocumentOperations.js +12 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useRef, useState, forwardRef, useImperativeHandle } from 'react';
|
|
3
|
-
import styled from 'styled-components';
|
|
3
|
+
import styled, { css, keyframes } from 'styled-components';
|
|
4
4
|
import { getAppModuleGradient, IconArrowLeft, IconClearButton, IconWindowMaximize, IconWindowMinimize, isPositiveNumber, SDKUI_Localizator } from '../../helper';
|
|
5
5
|
import TMButton from './TMButton';
|
|
6
6
|
import { Gutters } from '../../utils/theme';
|
|
@@ -96,6 +96,77 @@ const StyledPanelContent = styled.div `
|
|
|
96
96
|
outline: none;
|
|
97
97
|
}
|
|
98
98
|
`;
|
|
99
|
+
// Allineata al TABLET_BREAKPOINT (768) di TMDeviceProvider
|
|
100
|
+
const MOBILE_MEDIA_QUERY = '(max-width: 767.98px)';
|
|
101
|
+
// L'eccedenza da scorrere è "larghezza viewport - larghezza testo", ma nessuna delle due
|
|
102
|
+
// è nota al CSS. La si ottiene componendo due percentuali che si risolvono su box diversi:
|
|
103
|
+
// la track (larga quanto il viewport) va a +100% della PROPRIA larghezza, il testo a -100%
|
|
104
|
+
// della SUA. Le due animazioni hanno stessa durata ed easing, quindi lo scostamento netto
|
|
105
|
+
// in ogni istante è esattamente e(t) * (viewport - testo).
|
|
106
|
+
const panelTitleTrackMarquee = keyframes `
|
|
107
|
+
0%, 15% { transform: translateX(0); }
|
|
108
|
+
45%, 55% { transform: translateX(100%); }
|
|
109
|
+
85%, 100% { transform: translateX(0); }
|
|
110
|
+
`;
|
|
111
|
+
const panelTitleTextMarquee = keyframes `
|
|
112
|
+
0%, 15% { transform: translateX(0); }
|
|
113
|
+
45%, 55% { transform: translateX(-100%); }
|
|
114
|
+
85%, 100% { transform: translateX(0); }
|
|
115
|
+
`;
|
|
116
|
+
// Ritaglia il testo in eccesso: è l'unico box con overflow hidden, la track ci scorre dentro
|
|
117
|
+
const StyledPanelTitleViewport = styled.div `
|
|
118
|
+
flex: 1;
|
|
119
|
+
display: flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
justify-content: flex-start;
|
|
122
|
+
min-width: 0;
|
|
123
|
+
overflow: hidden;
|
|
124
|
+
padding: 0 8px;
|
|
125
|
+
`;
|
|
126
|
+
// Larga quanto il viewport: è il metro con cui il -100% del testo viene compensato.
|
|
127
|
+
const StyledPanelTitleTrack = styled.div `
|
|
128
|
+
flex: 1;
|
|
129
|
+
min-width: 0;
|
|
130
|
+
display: flex;
|
|
131
|
+
align-items: center;
|
|
132
|
+
|
|
133
|
+
${({ $marquee }) => $marquee && css `
|
|
134
|
+
@media ${MOBILE_MEDIA_QUERY} {
|
|
135
|
+
animation: ${panelTitleTrackMarquee} 10s ease-in-out infinite;
|
|
136
|
+
|
|
137
|
+
@media (prefers-reduced-motion: reduce) {
|
|
138
|
+
animation: none;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
`}
|
|
142
|
+
`;
|
|
143
|
+
// Senza $marquee resta il troncamento con i puntini di sempre
|
|
144
|
+
const StyledPanelTitle = styled.div `
|
|
145
|
+
margin: 0;
|
|
146
|
+
white-space: nowrap;
|
|
147
|
+
overflow: hidden;
|
|
148
|
+
text-overflow: ellipsis;
|
|
149
|
+
|
|
150
|
+
${({ $marquee }) => $marquee && css `
|
|
151
|
+
@media ${MOBILE_MEDIA_QUERY} {
|
|
152
|
+
flex: 0 0 auto;
|
|
153
|
+
width: max-content;
|
|
154
|
+
min-width: 100%;
|
|
155
|
+
max-width: none;
|
|
156
|
+
overflow: visible;
|
|
157
|
+
text-overflow: clip;
|
|
158
|
+
animation: ${panelTitleTextMarquee} 10s ease-in-out infinite;
|
|
159
|
+
|
|
160
|
+
@media (prefers-reduced-motion: reduce) {
|
|
161
|
+
animation: none;
|
|
162
|
+
width: auto;
|
|
163
|
+
min-width: 0;
|
|
164
|
+
overflow: hidden;
|
|
165
|
+
text-overflow: ellipsis;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
`}
|
|
169
|
+
`;
|
|
99
170
|
/**
|
|
100
171
|
* TMPanel - Pannello con supporto Controlled/Uncontrolled
|
|
101
172
|
*
|
|
@@ -103,7 +174,7 @@ const StyledPanelContent = styled.div `
|
|
|
103
174
|
* - Se NON passata → Uncontrolled: gestione interna dello stato attivo (plug-and-play)
|
|
104
175
|
* - Se passata → Controlled: il parent gestisce lo stato tramite onActivate
|
|
105
176
|
*/
|
|
106
|
-
const TMPanel = forwardRef(({ allowMaximize = true, color, backgroundColor, backgroundColorContainer, children, showHeader = true, title, totalItems, displayedItemsCount, toolbar, padding = '5px', isVisible = true, panelID = 'tmpanel', isActive, // Questa prop determinerà la modalità
|
|
177
|
+
const TMPanel = forwardRef(({ allowMaximize = true, color, backgroundColor, backgroundColorContainer, children, showHeader = true, title, enableTitleMarquee = false, totalItems, displayedItemsCount, toolbar, padding = '5px', isVisible = true, panelID = 'tmpanel', isActive, // Questa prop determinerà la modalità
|
|
107
178
|
onActivate, onBack, onClose, onHeaderDoubleClick, onMaximize, onActiveChanged }, ref) => {
|
|
108
179
|
const [isMaximized, setIsMaximized] = useState(false);
|
|
109
180
|
// Detect device type (e.g., mobile or desktop)
|
|
@@ -157,6 +228,7 @@ onActivate, onBack, onClose, onHeaderDoubleClick, onMaximize, onActiveChanged },
|
|
|
157
228
|
handleFocusUncontrolled();
|
|
158
229
|
}
|
|
159
230
|
};
|
|
231
|
+
const titleMarqueeKey = enableTitleMarquee && (typeof title === 'string' || typeof title === 'number') ? String(title) : undefined;
|
|
160
232
|
// handler for external maximize management
|
|
161
233
|
const handleMaximize = () => {
|
|
162
234
|
setIsMaximized(prevState => {
|
|
@@ -188,24 +260,11 @@ onActivate, onBack, onClose, onHeaderDoubleClick, onMaximize, onActiveChanged },
|
|
|
188
260
|
flexDirection: 'row',
|
|
189
261
|
alignItems: 'center',
|
|
190
262
|
flexShrink: 0
|
|
191
|
-
}, children: _jsxs(StyledBackButton, { "$isActive": currentIsActive, onClick: () => onBack ? onBack() : null, title: SDKUI_Localizator.Back, children: [_jsx(IconArrowLeft, {}), !isMobile && _jsx("span", { children: SDKUI_Localizator.Back })] }) }), _jsx("
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
minWidth: 0,
|
|
197
|
-
overflow: 'hidden',
|
|
198
|
-
padding: '0 8px'
|
|
199
|
-
}, children: _jsxs("div", { style: {
|
|
200
|
-
whiteSpace: 'nowrap',
|
|
201
|
-
overflow: 'hidden',
|
|
202
|
-
textOverflow: 'ellipsis',
|
|
203
|
-
margin: 0
|
|
204
|
-
}, children: [title, isPositiveNumber(displayedItemsCount) && isPositiveNumber(totalItems)
|
|
205
|
-
? ` (${displayedItemsCount} / ${totalItems})`
|
|
206
|
-
: isPositiveNumber(totalItems)
|
|
207
|
-
? ` (${totalItems})`
|
|
208
|
-
: ''] }) }), _jsxs("div", { style: {
|
|
263
|
+
}, children: _jsxs(StyledBackButton, { "$isActive": currentIsActive, onClick: () => onBack ? onBack() : null, title: SDKUI_Localizator.Back, children: [_jsx(IconArrowLeft, {}), !isMobile && _jsx("span", { children: SDKUI_Localizator.Back })] }) }), _jsx(StyledPanelTitleViewport, { children: _jsx(StyledPanelTitleTrack, { "$marquee": enableTitleMarquee, children: _jsxs(StyledPanelTitle, { "$marquee": enableTitleMarquee, children: [title, isPositiveNumber(displayedItemsCount) && isPositiveNumber(totalItems)
|
|
264
|
+
? ` (${displayedItemsCount} / ${totalItems})`
|
|
265
|
+
: isPositiveNumber(totalItems)
|
|
266
|
+
? ` (${totalItems})`
|
|
267
|
+
: ''] }) }, titleMarqueeKey) }), _jsxs("div", { style: {
|
|
209
268
|
display: 'flex',
|
|
210
269
|
flexDirection: 'row',
|
|
211
270
|
alignItems: 'center',
|
|
@@ -77,6 +77,11 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
77
77
|
const getVisibleItems = useCallback((node) => {
|
|
78
78
|
if (!node.items)
|
|
79
79
|
return [];
|
|
80
|
+
// Con la virtualizzazione react-window renderizza già solo le righe visibili:
|
|
81
|
+
// la paginazione nasconderebbe gli items oltre itemsPerPage senza renderizzare
|
|
82
|
+
// il paginatore, presente solo nel render standard (renderTree).
|
|
83
|
+
if (enableVirtualization)
|
|
84
|
+
return node.items;
|
|
80
85
|
const totalItems = node.items.length;
|
|
81
86
|
// Se non c'è paginazione attiva o gli items sono pochi, mostra tutti
|
|
82
87
|
if (totalItems <= itemsPerPage || !showLoadMoreButton) {
|
|
@@ -87,7 +92,7 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
87
92
|
const startIndex = currentPage * itemsPerPage;
|
|
88
93
|
const endIndex = startIndex + itemsPerPage;
|
|
89
94
|
return node.items.slice(startIndex, endIndex);
|
|
90
|
-
}, [itemsPerPage, showLoadMoreButton]);
|
|
95
|
+
}, [itemsPerPage, showLoadMoreButton, enableVirtualization]);
|
|
91
96
|
// Misura le dimensioni del container per react-window
|
|
92
97
|
useEffect(() => {
|
|
93
98
|
if (!enableVirtualization || !containerRef.current)
|
|
@@ -7,7 +7,7 @@ import { DcmtOperationTypes, FormModes } from '../../../ts';
|
|
|
7
7
|
import { StyledToolbarCardContainer, StyledFormButtonsContainer } from '../../base/Styled';
|
|
8
8
|
import { useDeviceType, DeviceType } from '../../base/TMDeviceProvider';
|
|
9
9
|
import { TMSplitterLayout } from '../../base/TMLayout';
|
|
10
|
-
import { TMExceptionBoxManager } from '../../base/TMPopUp';
|
|
10
|
+
import { TMExceptionBoxManager, TMMessageBoxManager, ButtonNames } from '../../base/TMPopUp';
|
|
11
11
|
import TMShowAllOrMaxItemsButton from '../../base/TMShowAllOrMaxItemsButton';
|
|
12
12
|
import TMSpinner from '../../base/TMSpinner';
|
|
13
13
|
import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
|
|
@@ -114,10 +114,24 @@ const TMBatchUpdateForm = ({ inputDcmts, TID, DID, isExpertMode = SDKUI_Globals.
|
|
|
114
114
|
const totalItems = metadataValues.filter(o => o.mid && o.mid > 100).length;
|
|
115
115
|
const metadataValuesSource = metadataValues.filter(o => o.mid && o.mid > 100).slice(0, showAll ? metadataValues.filter(o => o.mid && o.mid > 100).length : listMaxItems);
|
|
116
116
|
const metadataValuesSourceOrig = metadataValuesOrig.filter(o => o.mid && o.mid > 100).slice(0, showAll ? metadataValuesOrig.filter(o => o.mid && o.mid > 100).length : listMaxItems);
|
|
117
|
+
/**
|
|
118
|
+
* Chiusura del form: con modifiche pendenti chiede conferma prima di scartarle.
|
|
119
|
+
* Il TMModal è montato con askClosingConfirm, quindi non si auto-nasconde: la chiusura
|
|
120
|
+
* effettiva avviene solo quando onBack smonta il componente.
|
|
121
|
+
*/
|
|
122
|
+
const handleClose = () => {
|
|
123
|
+
if (!isModified) {
|
|
124
|
+
onBack?.();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
TMMessageBoxManager.show({
|
|
128
|
+
title: SDKUI_Localizator.Cancel, message: SDKUI_Localizator.ConfirmOnCancel, buttons: [ButtonNames.YES, ButtonNames.NO],
|
|
129
|
+
onButtonClick: (e) => { if (e === ButtonNames.YES)
|
|
130
|
+
onBack?.(); }
|
|
131
|
+
});
|
|
132
|
+
};
|
|
117
133
|
const renderContent = () => {
|
|
118
|
-
return (_jsx(TMLayoutWaitingContainer, { showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, children: _jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: 'visible', separatorSize: Gutters.getGutters(), separatorColor: 'transparent', separatorActiveColor: 'transparent', showSeparator: showFormulaEditor, start: showFormulaEditor ? ['50%', '50%'] : ['100%', '0%'], min: ['0', '0'], children: [_jsx(TMPanel, { title: isModal ? 'Modifica i metadati' : `${SDKUI_Localizator.BatchUpdate} (${inputDcmts.length} documenti selezionati)`, onBack: deviceType === DeviceType.MOBILE ?
|
|
119
|
-
// onClose={deviceType !== DeviceType.MOBILE ? onBack : undefined}
|
|
120
|
-
allowMaximize: !isModal, showHeader: !isModal, children: _jsxs(StyledToolbarCardContainer, { children: [_jsx(TMMetadataValues, { TID: TID, isExpertMode: isExpertMode, showCheckBoxes: ShowCheckBoxesMode.Always, showNullValueCheckBoxes: true, metadataValues: metadataValuesSource, metadataValuesOrig: metadataValuesSourceOrig, validationItems: validationItems, isOpenDistinctValues: showDistinctValuesPanel, selectedMID: focusedMetadataValue?.mid, onFocusedItemChanged: (item) => { setFocusedMetadataValue(item); }, onValueChanged: (newItems) => {
|
|
134
|
+
return (_jsx(TMLayoutWaitingContainer, { showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, children: _jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: 'visible', separatorSize: Gutters.getGutters(), separatorColor: 'transparent', separatorActiveColor: 'transparent', showSeparator: showFormulaEditor, start: showFormulaEditor ? ['50%', '50%'] : ['100%', '0%'], min: ['0', '0'], children: [_jsx(TMPanel, { title: isModal ? 'Modifica i metadati' : `${SDKUI_Localizator.BatchUpdate} (${inputDcmts.length} documenti selezionati)`, onBack: deviceType === DeviceType.MOBILE ? handleClose : undefined, allowMaximize: !isModal, showHeader: !isModal, children: _jsxs(StyledToolbarCardContainer, { children: [_jsx(TMMetadataValues, { TID: TID, isExpertMode: isExpertMode, showCheckBoxes: ShowCheckBoxesMode.Always, showNullValueCheckBoxes: true, metadataValues: metadataValuesSource, metadataValuesOrig: metadataValuesSourceOrig, validationItems: validationItems, isOpenDistinctValues: showDistinctValuesPanel, selectedMID: focusedMetadataValue?.mid, onFocusedItemChanged: (item) => { setFocusedMetadataValue(item); }, onValueChanged: (newItems) => {
|
|
121
135
|
setMetadataValues((prevItems) => prevItems.map((item) => {
|
|
122
136
|
const newItem = newItems.find((newItem) => newItem.tid === item.tid && newItem.mid === item.mid);
|
|
123
137
|
return newItem ? { ...item, ...newItem } : item;
|
|
@@ -153,7 +167,7 @@ const TMBatchUpdateForm = ({ inputDcmts, TID, DID, isExpertMode = SDKUI_Globals.
|
|
|
153
167
|
} })] }) })] }) }));
|
|
154
168
|
};
|
|
155
169
|
return (_jsx(_Fragment, { children: (isModal && onBack)
|
|
156
|
-
? _jsx(TMModal, { title: titleModal, onClose:
|
|
170
|
+
? _jsx(TMModal, { title: titleModal, onClose: handleClose, width: widthModal ?? '100%', height: heightModal ?? '100%', hidePopup: false, askClosingConfirm: true, children: _jsx("div", { style: { width: "100%", height: "100%", display: 'block', padding: "4px" }, children: renderContent() }) })
|
|
157
171
|
: renderContent() }));
|
|
158
172
|
};
|
|
159
173
|
export default TMBatchUpdateForm;
|
|
@@ -37,6 +37,7 @@ interface ITMSearchResultProps {
|
|
|
37
37
|
openInOffice?: (selectedDcmtsOrFocused: Array<DcmtInfo>) => Promise<void>;
|
|
38
38
|
onWFOperationCompleted?: () => Promise<void>;
|
|
39
39
|
onSelectedTIDChanged?: (TID: number) => void;
|
|
40
|
+
onSelectedTIDCleared?: () => void;
|
|
40
41
|
onRefreshSearchAsyncDatagrid?: () => Promise<void>;
|
|
41
42
|
onRefreshAfterAddDcmtToFavs?: () => void;
|
|
42
43
|
onFileOpened?: (blob: File | undefined) => void;
|
|
@@ -57,7 +57,7 @@ groupId, searchResults = [], context = SearchResultContext.METADATA_SEARCH, titl
|
|
|
57
57
|
// Boolean flags to enable/disable features
|
|
58
58
|
autoFocusFirstRow = true, formAutoOpen, isVisible = true, allowRelations = true, openDcmtFormAsModal = false, showSearchResultSidebar = true, showDcmtFormSidebar = true, showSelector = false, isClosable = false, allowFloatingBar = true, showToolbarHeader = true, showBackButton = true, disableAccordionIfSingleCategory = false, editPdfForm = false, openS4TViewer = false, showTodoDcmtForm = false, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, showNoDcmtFoundMessage = true, enablePinIcons = true,
|
|
59
59
|
// Callbacks (optional)
|
|
60
|
-
openInOffice, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsyncDatagrid, onSelectedTIDChanged, onWFOperationCompleted, onClose, onFileOpened, onTaskCreateRequest, openWGsCopyMoveForm, openCommentFormCallback, openAddDocumentForm, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, passToArchiveCallback, onReferenceClick,
|
|
60
|
+
openInOffice, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsyncDatagrid, onSelectedTIDChanged, onSelectedTIDCleared, onWFOperationCompleted, onClose, onFileOpened, onTaskCreateRequest, openWGsCopyMoveForm, openCommentFormCallback, openAddDocumentForm, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, passToArchiveCallback, onReferenceClick,
|
|
61
61
|
// Tasks
|
|
62
62
|
allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback,
|
|
63
63
|
// Navigation
|
|
@@ -69,13 +69,19 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
69
69
|
// Quando l'utente seleziona manualmente, il ref viene settato a false e il focus automatico
|
|
70
70
|
// torna al comportamento normale.
|
|
71
71
|
const isFirstAutoFocusRef = useRef(true);
|
|
72
|
+
// Mostra il pannello lista. È una ref perché il TMPanelManagerProvider sta dentro al JSX di
|
|
73
|
+
// questo componente, quindi qui il context non si può usare: la riempie ShowMainPanelBridge.
|
|
74
|
+
const showMainPanelRef = useRef(null);
|
|
72
75
|
// ID state to force remount of components
|
|
73
76
|
const [id, setID] = useState('');
|
|
74
77
|
// Document type descriptor of the currently document
|
|
75
78
|
const [fromDTD, setFromDTD] = useState();
|
|
76
79
|
const [currentDcmt, setCurrentDcmt] = useState();
|
|
77
|
-
//
|
|
78
|
-
|
|
80
|
+
// Passo corrente. Su mobile decide anche quale pannello è a schermo (vedi isSteppedLayout).
|
|
81
|
+
// 'auto' -> l'utente non ha ancora scelto: si può selezionare il primo tipo documento
|
|
82
|
+
// 'selector' -> è tornato indietro col back: non selezionare niente al posto suo
|
|
83
|
+
// 'results' -> è sulla griglia del tipo scelto
|
|
84
|
+
const [navStep, setNavStep] = useState('auto');
|
|
79
85
|
// State to control the selected search result
|
|
80
86
|
const [selectedSearchResult, setSelectedSearchResult] = useState();
|
|
81
87
|
// State to control the search results to show in the datagrid
|
|
@@ -377,9 +383,20 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
377
383
|
openTaskFormHandler,
|
|
378
384
|
},
|
|
379
385
|
});
|
|
380
|
-
const { isOpenDcmtForm, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid,
|
|
386
|
+
const { isOpenDcmtForm, openFormHandler, dcmtFormLayoutMode, onDcmtFormOpenChange, showSearchTMDatagrid, showDcmtTypesSelection, showExportForm, updateBatchUpdateForm, closeDcmtFormHandler, handleSignApprove, checkoutInfo: { showCicoWaitPanel, cicoWaitPanelTitle, showCicoPrimaryProgress, cicoPrimaryProgressText, cicoPrimaryProgressValue, cicoPrimaryProgressMax, }, dcmtOperations: { abortController, showWaitPanel, showPrimary, waitPanelTitle, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, }, relatedDocumentsInfo: { isOpenDetails, isOpenMaster, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, }, toppyOperations: { showApprovePopup, showRejectPopup, showReAssignPopup, showMoreInfoPopup, updateShowApprovePopup, updateShowRejectPopup, updateShowReAssignPopup, updateShowMoreInfoPopup } } = features;
|
|
381
387
|
const deviceType = useDeviceType();
|
|
382
388
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
389
|
+
const hasSingleDcmtType = currentSearchResults.length === 1;
|
|
390
|
+
// Su mobile si vede un pannello per volta; su desktop selettore e griglia sono affiancati
|
|
391
|
+
const isSteppedLayout = showSelector && isMobile;
|
|
392
|
+
// Un solo tipo documento su desktop: non c'è niente da scegliere, quindi il selettore sparisce
|
|
393
|
+
// (larghezza 0, nessun separatore) e lo spazio va tutto alla griglia. Il menu "Altro" permette
|
|
394
|
+
// di riaprirlo (vedi canToggleDcmtTypesSelection nell'hook).
|
|
395
|
+
const isSelectorCollapsed = showSelector && !isSteppedLayout && hasSingleDcmtType && !showDcmtTypesSelection;
|
|
396
|
+
// Senza selettore lo spazio va tutto alla griglia; altrimenti a step su mobile, affiancati su desktop
|
|
397
|
+
const splitterSizes = (!showSelector || isSelectorCollapsed) ? ['0%', '100%']
|
|
398
|
+
: isSteppedLayout ? (navStep === 'results' ? ['0', '100%'] : ['100%', '0'])
|
|
399
|
+
: ['30%', '70%'];
|
|
383
400
|
const selectedDocs = getSelectedDcmtsOrFocused(selectedItems, focusedItem);
|
|
384
401
|
// Disable the "Sign/Approve" button if:
|
|
385
402
|
// 1. No document or multiple documents are selected, OR
|
|
@@ -400,8 +417,14 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
400
417
|
setSelectedSearchResult(undefined);
|
|
401
418
|
return;
|
|
402
419
|
}
|
|
420
|
+
// Un solo tipo documento: selezionalo e vai ai risultati, a meno che l'utente sia tornato indietro
|
|
403
421
|
if (searchResults.length === 1) {
|
|
422
|
+
if (navStep === 'selector') {
|
|
423
|
+
setSelectedSearchResult(undefined);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
404
426
|
setSelectedSearchResult(searchResults[0]);
|
|
427
|
+
setNavStep('results');
|
|
405
428
|
return;
|
|
406
429
|
}
|
|
407
430
|
// Se il TID precedentemente selezionato esiste ancora nei nuovi risultati, mantienilo.
|
|
@@ -415,6 +438,11 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
415
438
|
return;
|
|
416
439
|
}
|
|
417
440
|
}
|
|
441
|
+
// L'utente è sul selettore
|
|
442
|
+
if (isMobile && navStep !== 'results') {
|
|
443
|
+
setSelectedSearchResult(undefined);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
418
446
|
// Altrimenti seleziona il primo risultato ordinato
|
|
419
447
|
setSelectedSearchResult(orderByName(searchResults)[0]);
|
|
420
448
|
}, [searchResults]);
|
|
@@ -533,47 +561,75 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
533
561
|
let counters = (showSelector && disableAccordionIfSingleCategory && searchResults.length > 1) ? getSearchResultCountersSingleCategory(searchResults) : "";
|
|
534
562
|
if (title)
|
|
535
563
|
return title + counters;
|
|
536
|
-
|
|
564
|
+
// Nome del tipo documento selezionato, accodato al titolo
|
|
565
|
+
const selectedDcmtTypeName = selectedSearchResult?.fromName ?? (searchResults?.length === 1 ? searchResults[0]?.fromName : undefined);
|
|
566
|
+
const withSelectedDcmtTypeName = (baseTitle) => selectedDcmtTypeName ? `${baseTitle} - ${selectedDcmtTypeName}` : baseTitle;
|
|
567
|
+
let titleHeader = withSelectedDcmtTypeName('Ricerca per metadati');
|
|
537
568
|
switch (context) {
|
|
538
569
|
case SearchResultContext.MASTER_DETAIL:
|
|
539
570
|
case SearchResultContext.METADATA_SEARCH:
|
|
540
571
|
titleHeader = `${searchResults?.length > 1 ? selectedSearchResult?.fromName ?? 'Ricerca per metadati' : searchResults[0]?.fromName ?? 'Ricerca per metadati'}`;
|
|
541
572
|
break;
|
|
542
573
|
case SearchResultContext.FAVORITES_AND_RECENTS:
|
|
543
|
-
titleHeader = SDKUI_Localizator.FavoritesAndRecentDcmts;
|
|
574
|
+
titleHeader = withSelectedDcmtTypeName(SDKUI_Localizator.FavoritesAndRecentDcmts);
|
|
544
575
|
break;
|
|
545
576
|
case SearchResultContext.WORKFLOW_APPROVE:
|
|
546
|
-
titleHeader = SDKUI_Localizator.WorkflowApproval;
|
|
577
|
+
titleHeader = withSelectedDcmtTypeName(SDKUI_Localizator.WorkflowApproval);
|
|
547
578
|
break;
|
|
548
579
|
case SearchResultContext.FREE_SEARCH:
|
|
549
|
-
titleHeader =
|
|
580
|
+
titleHeader = withSelectedDcmtTypeName('Risultato della ricerca full text');
|
|
550
581
|
break;
|
|
551
582
|
}
|
|
552
583
|
return titleHeader + counters;
|
|
553
584
|
};
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
setSelectedSearchResult(undefined);
|
|
572
|
-
}
|
|
573
|
-
setSplitterSize(['100%', '0']);
|
|
574
|
-
onClose?.();
|
|
585
|
+
// Dai risultati si risale al selettore dei tipi documento
|
|
586
|
+
const canGoBackToSelector = isSteppedLayout && navStep === 'results' && selectedSearchResult !== undefined;
|
|
587
|
+
/**
|
|
588
|
+
* Back di tutti i pannelli (e X di chiusura se isClosable). Su mobile risale un livello alla volta:
|
|
589
|
+
* pannello secondario -> lista dei risultati -> selettore dei tipi documento -> uscita.
|
|
590
|
+
* Su desktop i pannelli sono affiancati, quindi resta solo l'uscita.
|
|
591
|
+
*
|
|
592
|
+
* @param fromSecondaryPanel - true se il back arriva da un pannello secondario
|
|
593
|
+
*/
|
|
594
|
+
const onBack = useCallback((fromSecondaryPanel = false) => {
|
|
595
|
+
// Non è previsto nessun modo di uscire: non fare niente
|
|
596
|
+
if (!showBackButton && !isClosable)
|
|
597
|
+
return;
|
|
598
|
+
// Torna alla lista senza toccare gli stati: l'utente deve ritrovare la sua selezione
|
|
599
|
+
if (fromSecondaryPanel) {
|
|
600
|
+
showMainPanelRef.current?.();
|
|
601
|
+
return;
|
|
575
602
|
}
|
|
576
|
-
|
|
603
|
+
// Sia il ritorno al selettore sia l'uscita ripartono da una lista pulita
|
|
604
|
+
setSelectedSearchResult(undefined);
|
|
605
|
+
setFocusedItem(undefined);
|
|
606
|
+
setSelectedItems([]);
|
|
607
|
+
setSelectedRowKeysFromDataGrid([]);
|
|
608
|
+
setCurrentDcmt(undefined);
|
|
609
|
+
setCurrentMetadataValues([]);
|
|
610
|
+
setShowIndexingInfo(false);
|
|
611
|
+
isFirstAutoFocusRef.current = true;
|
|
612
|
+
// Il chiamante può tenere allineato il suo TID selezionato (es. selectedSearchResultTID)
|
|
613
|
+
onSelectedTIDCleared?.();
|
|
614
|
+
// [2] l'utente ha chiesto la lista: resta lì finché non sceglie lui, niente auto-selezione.
|
|
615
|
+
// [1] si esce: si riparte da capo, quindi l'auto-selezione torna permessa.
|
|
616
|
+
setNavStep(canGoBackToSelector ? 'selector' : 'auto');
|
|
617
|
+
// [2] C'è ancora un livello sopra: restiamo dentro, sul selettore
|
|
618
|
+
if (canGoBackToSelector)
|
|
619
|
+
return;
|
|
620
|
+
// [1] Si esce e si avvisa il chiamante
|
|
621
|
+
onClose?.();
|
|
622
|
+
}, [canGoBackToSelector, showBackButton, isClosable, onClose, onSelectedTIDCleared]);
|
|
623
|
+
/**
|
|
624
|
+
* Back del pannello lista. `undefined` = freccia non renderizzata, quindi la mostriamo solo se
|
|
625
|
+
* ha dove tornare: uno step intermedio, o un onClose per uscire. Con `isClosable` basta la X.
|
|
626
|
+
*/
|
|
627
|
+
const backHandler = (showBackButton && !isClosable && (canGoBackToSelector || onClose !== undefined)) ? onBack : undefined;
|
|
628
|
+
/**
|
|
629
|
+
* Back dei pannelli secondari: la stessa onBack marcata come livello [3]. Solo su mobile:
|
|
630
|
+
* su desktop stanno affiancati alla lista e non c'è niente da cui tornare.
|
|
631
|
+
*/
|
|
632
|
+
const backHandlerSecondary = useMemo(() => (isMobile && backHandler) ? () => backHandler(true) : undefined, [isMobile, backHandler]);
|
|
577
633
|
const refreshDataGridAfterRemoveAsync = async () => {
|
|
578
634
|
let index = selectedSearchResult?.dtdResult?.columns?.findIndex(col => col.caption === 'DID');
|
|
579
635
|
let selectedRows = [];
|
|
@@ -605,21 +661,6 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
605
661
|
return newResults;
|
|
606
662
|
});
|
|
607
663
|
};
|
|
608
|
-
/**
|
|
609
|
-
* Restituisce l'handler onBack per i pannelli, evitando duplicazione di codice.
|
|
610
|
-
* @param isMainPanel - Se true, è il pannello principale dei risultati di ricerca
|
|
611
|
-
*/
|
|
612
|
-
const getOnBackHandler = (isMainPanel = false) => {
|
|
613
|
-
// Se showBackButton è false, non mostrare mai il back
|
|
614
|
-
if (showBackButton === false)
|
|
615
|
-
return undefined;
|
|
616
|
-
// Mobile: mostra back su tutti i pannelli (se showBackButton è definito e non è closable)
|
|
617
|
-
if (isMobile) {
|
|
618
|
-
return (showBackButton !== undefined && !isClosable) ? onBack : undefined;
|
|
619
|
-
}
|
|
620
|
-
// Desktop: mostra back solo sul pannello principale dei risultati (se showBackButton è definito e non è closable)
|
|
621
|
-
return (showBackButton !== undefined && isMainPanel && !isClosable) ? onBack : undefined;
|
|
622
|
-
};
|
|
623
664
|
const removeDcmtFromFavsOrRecents = async () => {
|
|
624
665
|
switch (selectedSearchResult?.category) {
|
|
625
666
|
case "Favorites":
|
|
@@ -636,9 +677,9 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
636
677
|
};
|
|
637
678
|
const onSearchResultSelectionChanged = (e) => {
|
|
638
679
|
setSelectedSearchResult(e);
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
680
|
+
// Scelto il tipo documento si passa ai risultati (a livello di layout è ignorato se i due
|
|
681
|
+
// step sono affiancati, ma vale comunque come "l'utente non è più fermo sul selettore")
|
|
682
|
+
setNavStep('results');
|
|
642
683
|
onSelectedTIDChanged?.(e.fromTID);
|
|
643
684
|
};
|
|
644
685
|
const showToppyForApprove = useMemo(() => {
|
|
@@ -666,8 +707,8 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
666
707
|
const tmSearchResult = useMemo(() => (!searchResults || searchResults.length <= 0)
|
|
667
708
|
? _jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%' }, children: [_jsx(IconBoard, { fontSize: 96 }), showNoDcmtFoundMessage && _jsx("div", { style: { fontSize: "15px", marginTop: "10px" }, children: SDKUI_Localizator.NoDcmtFound }), openAddDocumentForm && _jsx("div", { style: { marginTop: "10px" }, children: _jsx(TMButton, { fontSize: "15px", icon: _jsx("i", { className: 'dx-icon-share' }), caption: SDKUI_Localizator.Share, onClick: openAddDocumentForm }) })] })
|
|
668
709
|
:
|
|
669
|
-
_jsxs(_Fragment, { children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs("div", { ref: floatingBarContainerRef, style: { position: 'relative', height: '100%', width: '100%' }, children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: 'visible', separatorSize: Gutters.getGutters(), separatorActiveColor: 'transparent', separatorColor: 'transparent', min: ['0', '0'], showSeparator: showSelector &&
|
|
670
|
-
_jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, disableAccordionIfSingleCategory: disableAccordionIfSingleCategory, selectedTID: selectedSearchResultTID, selectedSearchResult: selectedSearchResult, autoSelectFirst: !isMobile ||
|
|
710
|
+
_jsxs(_Fragment, { children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs("div", { ref: floatingBarContainerRef, style: { position: 'relative', height: '100%', width: '100%' }, children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: 'visible', separatorSize: Gutters.getGutters(), separatorActiveColor: 'transparent', separatorColor: 'transparent', min: ['0', '0'], showSeparator: showSelector && !isSteppedLayout && !isSelectorCollapsed, start: splitterSizes, children: [showSelector ?
|
|
711
|
+
_jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, disableAccordionIfSingleCategory: disableAccordionIfSingleCategory, selectedTID: selectedSearchResultTID, selectedSearchResult: selectedSearchResult, autoSelectFirst: !isMobile || hasSingleDcmtType, onSelectionChanged: onSearchResultSelectionChanged }) })
|
|
671
712
|
:
|
|
672
713
|
_jsx(_Fragment, {}), _jsx(TMLayoutItem, { children: _jsx(TMSearchResultGrid, { openInOffice: openInOffice, fromDTD: fromDTD, operationItems: operationItems, allUsers: allUsers, inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, showExportForm: showExportForm, onFocusedItemChanged: handleFocusedItemChangedFromGrid, onDownloadDcmtsAsync: async (inputDcmts, downloadType, downloadMode, _y, confirmAttachments) => await downloadDcmtsAsync({ inputDcmts, downloadType, downloadMode, onFileDownloaded: onFileOpened, confirmAttachments }), lastUpdateSearchTime: lastUpdateSearchTime, searchResult: searchResults.length > 1 ? selectedSearchResult : searchResults[0], onSelectionChanged: (items) => { setSelectedItems(items); }, onDblClick: () => openFormHandler(LayoutModes.Update), showSearchTMDatagrid: showSearchTMDatagrid, onVisibleItemChanged: setVisibleItems, updateDataColumnsFromDataGrid: updateDataColumnsFromDataGrid, updateDataSourceFromDataGrid: updateDataSourceFromDataGrid, updateSelectedRowKeysFromDataGrid: updateSelectedRowKeysFromDataGrid, disableAutoFocus: autoFocusFirstRow === false && isFirstAutoFocusRef.current, dcmtsReturned: dcmtsReturned, dcmtsFound: dcmtsFound }) })] }), renderFloatingBar] }), _jsx(TMToppyDraggableHelpCenter, { usePortal: toppyHelpCenterUsePortal, isVisible: isToppyHelpCenterVisible, content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { dtd: fromDTD, deviceType: deviceType, onApprove: () => {
|
|
673
714
|
updateShowApprovePopup(true);
|
|
@@ -689,7 +730,6 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
689
730
|
showApprovePopup,
|
|
690
731
|
showRejectPopup,
|
|
691
732
|
showReAssignPopup,
|
|
692
|
-
isOpenBatchUpdate,
|
|
693
733
|
isOpenDetails,
|
|
694
734
|
isOpenMaster,
|
|
695
735
|
isOpenDcmtForm,
|
|
@@ -700,6 +740,10 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
700
740
|
openS4TViewer,
|
|
701
741
|
showBackButton,
|
|
702
742
|
isMobile,
|
|
743
|
+
navStep,
|
|
744
|
+
isSteppedLayout,
|
|
745
|
+
isSelectorCollapsed,
|
|
746
|
+
currentSearchResults,
|
|
703
747
|
currentMetadataValues,
|
|
704
748
|
onRefreshSearchAsyncDatagrid,
|
|
705
749
|
handleNavigateToWGs,
|
|
@@ -709,7 +753,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
709
753
|
]);
|
|
710
754
|
const tmBlog = useMemo(() => _jsx(TMDcmtBlog, { tid: focusedItem?.TID, did: focusedItem?.DID, fetchBlogDataTrigger: refreshBlogTrigger, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), [focusedItem, allTasks, refreshBlogTrigger, handleNavigateToWGs, handleNavigateToDossiers, onRefreshBlogDatagrid]);
|
|
711
755
|
const tmSysMetadata = useMemo(() => _jsx(TMMetadataValues, { layoutMode: LayoutModes.Update, openChooserBySingleClick: true, TID: focusedItem?.TID, isReadOnly: true, deviceType: deviceType, metadataValues: currentMetadataValues.filter(o => (o.mid != undefined && o.mid <= 100)), metadataValuesOrig: currentMetadataValues.filter(o => (o.mid != undefined && o.mid <= 100)), validationItems: [] }), [focusedItem, currentMetadataValues, deviceType]);
|
|
712
|
-
const tmDcmtPreview = useMemo(() => _jsx(TMDcmtPreviewWrapper, { refreshPreviewTrigger: refreshPreviewTrigger, currentDcmt: currentDcmt, onBack:
|
|
756
|
+
const tmDcmtPreview = useMemo(() => _jsx(TMDcmtPreviewWrapper, { refreshPreviewTrigger: refreshPreviewTrigger, currentDcmt: currentDcmt, onBack: backHandlerSecondary }), [currentDcmt, refreshPreviewTrigger, backHandlerSecondary]);
|
|
713
757
|
// Auto-fetch indexing info when drawer is open and focusedItem changes
|
|
714
758
|
useEffect(() => {
|
|
715
759
|
if (!focusedItem || !showIndexingInfo)
|
|
@@ -788,9 +832,10 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
788
832
|
component: tmSearchResult,
|
|
789
833
|
panelContainer: {
|
|
790
834
|
title: getTitleHeader(),
|
|
835
|
+
enableTitleMarquee: true,
|
|
791
836
|
showHeader: showToolbarHeader,
|
|
792
837
|
allowMaximize: !isMobile,
|
|
793
|
-
onBack:
|
|
838
|
+
onBack: backHandler,
|
|
794
839
|
onClose: isClosable ? onBack : undefined,
|
|
795
840
|
toolbar: searchResutlToolbar
|
|
796
841
|
},
|
|
@@ -805,7 +850,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
805
850
|
panelContainer: {
|
|
806
851
|
title: SDKUI_Localizator.BlogCase,
|
|
807
852
|
allowMaximize: !isMobile,
|
|
808
|
-
onBack:
|
|
853
|
+
onBack: backHandlerSecondary,
|
|
809
854
|
}
|
|
810
855
|
},
|
|
811
856
|
toolbarOptions: { icon: _jsx(IconBoard, { fontSize: 24 }), visible: getSearchToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmBlog, orderNumber: 2, isActive: allInitialPanelVisibility['tmBlog'] }
|
|
@@ -818,7 +863,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
818
863
|
panelContainer: {
|
|
819
864
|
title: SDKUI_Localizator.MetadataSystem,
|
|
820
865
|
allowMaximize: !isMobile,
|
|
821
|
-
onBack:
|
|
866
|
+
onBack: backHandlerSecondary,
|
|
822
867
|
}
|
|
823
868
|
},
|
|
824
869
|
toolbarOptions: { icon: _jsx(IconDcmtTypeSys, { fontSize: 24 }), visible: getSearchToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmSysMetadata, orderNumber: 3, isActive: allInitialPanelVisibility['tmSysMetadata'] }
|
|
@@ -832,7 +877,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
832
877
|
panelContainer: {
|
|
833
878
|
title: SDKUI_Localizator.ResultDetails,
|
|
834
879
|
allowMaximize: !isMobile,
|
|
835
|
-
onBack:
|
|
880
|
+
onBack: backHandlerSecondary,
|
|
836
881
|
}
|
|
837
882
|
},
|
|
838
883
|
toolbarOptions: { icon: _jsx(IconPlatform, { fontSize: 20 }), visible: getSearchToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmFullTextSearch, orderNumber: 4, isActive: allInitialPanelVisibility['tmFullTextSearch'] }
|
|
@@ -846,7 +891,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
846
891
|
},
|
|
847
892
|
toolbarOptions: { icon: _jsx(IconShow, { fontSize: 24 }), visible: getSearchToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmDcmtPreview, orderNumber: context === SearchResultContext.FREE_SEARCH ? 5 : 4, isActive: allInitialPanelVisibility['tmDcmtPreview'] }
|
|
848
893
|
}
|
|
849
|
-
], [tmSearchResult, tmBlog, tmSysMetadata, tmDcmtPreview, tmFullTextSearch, showToolbarHeader, context, isMobile]);
|
|
894
|
+
], [tmSearchResult, tmBlog, tmSysMetadata, tmDcmtPreview, tmFullTextSearch, showToolbarHeader, context, isMobile, backHandler, backHandlerSecondary, isClosable, onBack]);
|
|
850
895
|
return (_jsxs(StyledMultiViewPanel, { "$isVisible": isVisible, children: [_jsx(StyledMultiViewPanel, { "$isVisible": !isOpenDcmtForm && !isOpenDetails && !isOpenMaster, style: {
|
|
851
896
|
display: 'flex',
|
|
852
897
|
flexDirection: isMobile ? 'column' : 'row',
|
|
@@ -855,9 +900,9 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
855
900
|
width: '100%',
|
|
856
901
|
height: '100%',
|
|
857
902
|
}, children: _jsx(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: _jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showCicoWaitPanel, showWaitPanelPrimary: showCicoPrimaryProgress, waitPanelTitle: cicoWaitPanelTitle, waitPanelTextPrimary: cicoPrimaryProgressText, waitPanelValuePrimary: cicoPrimaryProgressValue, waitPanelMaxValuePrimary: cicoPrimaryProgressMax, isCancelable: true, abortController: abortControllerLocal, children: (groupId && groupId.length > 0) ?
|
|
858
|
-
_jsxs(_Fragment, { children: [_jsx(PanelDisabledStateHandler, { isBoardDisabled: isBoardDisabled }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar })] })
|
|
903
|
+
_jsxs(_Fragment, { children: [_jsx(PanelDisabledStateHandler, { isBoardDisabled: isBoardDisabled }), _jsx(ShowMainPanelBridge, { showMainPanelRef: showMainPanelRef }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar })] })
|
|
859
904
|
:
|
|
860
|
-
_jsxs(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmSearchResult', children: [_jsx(PanelDisabledStateHandler, { isBoardDisabled: isBoardDisabled }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar })] }) }) }) }), renderDcmtOperations] }));
|
|
905
|
+
_jsxs(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmSearchResult', children: [_jsx(PanelDisabledStateHandler, { isBoardDisabled: isBoardDisabled }), _jsx(ShowMainPanelBridge, { showMainPanelRef: showMainPanelRef }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar })] }) }) }) }), renderDcmtOperations] }));
|
|
861
906
|
};
|
|
862
907
|
export default TMSearchResult;
|
|
863
908
|
const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, inputFocusedItem, allowMultipleSelection = true, showExportForm = false, onFocusedItemChanged, onDownloadDcmtsAsync, onVisibleItemChanged, inputSelectedItems = [], lastUpdateSearchTime, searchResult, onSelectionChanged, onDblClick, showSearchTMDatagrid, updateDataColumnsFromDataGrid, updateDataSourceFromDataGrid, updateSelectedRowKeysFromDataGrid, disableAutoFocus = false, dcmtsReturned, dcmtsFound }) => {
|
|
@@ -1319,14 +1364,29 @@ const TMSearchResultSelector = ({ searchResults = [], disableAccordionIfSingleCa
|
|
|
1319
1364
|
}
|
|
1320
1365
|
}
|
|
1321
1366
|
}, [sortedCategories.length, autoSelectFirst]);
|
|
1367
|
+
// La preselezione esterna va applicata una volta per valore: riapplicarla a ogni cambio di
|
|
1368
|
+
// searchResults faceva sì che un refresh annullasse la navigazione dell'utente.
|
|
1369
|
+
const appliedSelectedTIDRef = useRef(undefined);
|
|
1322
1370
|
useEffect(() => {
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1371
|
+
// Richiesta ritirata: dimentichiamo il valore applicato, così se il chiamante richiede di
|
|
1372
|
+
// nuovo lo stesso TID la preselezione riparte
|
|
1373
|
+
if (selectedTID === undefined) {
|
|
1374
|
+
appliedSelectedTIDRef.current = undefined;
|
|
1375
|
+
return;
|
|
1326
1376
|
}
|
|
1377
|
+
if (appliedSelectedTIDRef.current === selectedTID)
|
|
1378
|
+
return;
|
|
1379
|
+
const found = searchResults.find(r => Number(r.fromTID) === selectedTID);
|
|
1380
|
+
if (!found)
|
|
1381
|
+
return; // risultati non ancora arrivati: riproviamo al prossimo giro
|
|
1382
|
+
appliedSelectedTIDRef.current = selectedTID;
|
|
1383
|
+
handleSelect(found);
|
|
1327
1384
|
}, [selectedTID, searchResults]);
|
|
1328
|
-
|
|
1329
|
-
|
|
1385
|
+
// force = true per i click dell'utente: la selezione va notificata anche se il tipo documento è già quello selezionato
|
|
1386
|
+
const handleSelect = useCallback((result, force = false) => {
|
|
1387
|
+
if (result === undefined)
|
|
1388
|
+
return;
|
|
1389
|
+
if (selectedResult !== result || force) {
|
|
1330
1390
|
setSelectedResult(result);
|
|
1331
1391
|
onSelectionChanged?.(result);
|
|
1332
1392
|
}
|
|
@@ -1371,14 +1431,24 @@ const TMSearchResultSelector = ({ searchResults = [], disableAccordionIfSingleCa
|
|
|
1371
1431
|
renderItem: (result, isSelected) => (_jsxs("div", { style: { width: '100%', padding: '5px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsx(TMTidViewer, { tid: result.fromTID, did: Number(result.dtdResult?.rows?.[0]?.[1]), showIcon: true }), _jsx("div", { style: { padding: 3, display: 'flex', alignItems: 'center', justifyContent: 'center', backgroundColor: 'white', color: 'gray', borderRadius: 3 }, children: result.dcmtsReturned })] })),
|
|
1372
1432
|
itemHeight: 40
|
|
1373
1433
|
})), [sortedCategories, groupedResults, searchResults]);
|
|
1374
|
-
const renderCategoryItems = (category) => (_jsx("div", { style: { padding: '5px', height: '100%', overflow: 'auto' }, children: groupedResults[category].map((result, index) => (_jsx(MemoizedStyledItemTemplate, { "$isSelected": selectedResult === result, onClick: () => handleSelect(result), children: renderItemTemplate(result) }, index))) }));
|
|
1434
|
+
const renderCategoryItems = (category) => (_jsx("div", { style: { padding: '5px', height: '100%', overflow: 'auto' }, children: groupedResults[category].map((result, index) => (_jsx(MemoizedStyledItemTemplate, { "$isSelected": selectedResult === result, onClick: () => handleSelect(result, true), children: renderItemTemplate(result) }, index))) }));
|
|
1375
1435
|
if (disableAccordionIfSingleCategory && sortedCategories.length === 1) {
|
|
1376
1436
|
const category = sortedCategories[0];
|
|
1377
1437
|
return renderCategoryItems(category);
|
|
1378
1438
|
}
|
|
1379
|
-
return (_jsx(TMAccordionNew, { groups: accordionGroups, selectedItem: selectedResult, onSelectedItemChange: (result) => handleSelect(result) }));
|
|
1439
|
+
return (_jsx(TMAccordionNew, { groups: accordionGroups, selectedItem: selectedResult, onSelectedItemChange: (result) => handleSelect(result, true) }));
|
|
1380
1440
|
};
|
|
1381
1441
|
//#endregion TMSearchResultSelector
|
|
1442
|
+
/** Senza UI: vive dentro il provider e passa a onBack, via ref, l'azione "mostra il pannello lista". */
|
|
1443
|
+
const ShowMainPanelBridge = ({ showMainPanelRef }) => {
|
|
1444
|
+
const { setPanelVisibilityById } = useTMPanelManagerContext();
|
|
1445
|
+
useEffect(() => {
|
|
1446
|
+
// Su mobile mostrare un pannello nasconde gli altri; su desktop la lista è già visibile
|
|
1447
|
+
showMainPanelRef.current = () => setPanelVisibilityById('tmSearchResult', true);
|
|
1448
|
+
return () => { showMainPanelRef.current = null; };
|
|
1449
|
+
}, [setPanelVisibilityById, showMainPanelRef]);
|
|
1450
|
+
return null;
|
|
1451
|
+
};
|
|
1382
1452
|
const PanelDisabledStateHandler = ({ isBoardDisabled }) => {
|
|
1383
1453
|
const { setPanelVisibilityById, setToolbarButtonDisabled } = useTMPanelManagerContext();
|
|
1384
1454
|
useEffect(() => {
|
|
@@ -405,6 +405,7 @@ export declare class SDKUI_Localizator {
|
|
|
405
405
|
static get Grids(): string;
|
|
406
406
|
static get Hide_CompleteName(): "Vollständigen Namen ausblenden" | "Hide full name" | "Ocultar nombre completo" | "Masquer le nom complet" | "Ocultar nome completo" | "Nascondi nome completo";
|
|
407
407
|
static get HideAll(): "Alle ausblenden" | "Hide all" | "Ocultar todo" | "Masquer tout" | "Ocultar tudo" | "Nascondi tutti";
|
|
408
|
+
static get HideDcmtTypes(): string;
|
|
408
409
|
static get HideDetailsWithZeroDocs(): string;
|
|
409
410
|
static get HideFloatingBar(): string;
|
|
410
411
|
static get HideFilters(): string;
|
|
@@ -764,6 +765,7 @@ export declare class SDKUI_Localizator {
|
|
|
764
765
|
static get Shortcuts(): "Tastenkombinationen" | "Shortcuts" | "Atajos" | "Raccourcis" | "Atalhos" | "Scorciatoie";
|
|
765
766
|
static get ShowAll(): "Alle anzeigen" | "Show all" | "Mostrar todo" | "Tout afficher" | "Mostrar tudo" | "Mostra tutti";
|
|
766
767
|
static get ShowColumnSelection(): string;
|
|
768
|
+
static get ShowDcmtTypes(): string;
|
|
767
769
|
static get ShowFloatingBar(): string;
|
|
768
770
|
static get ShowLess(): "Weniger anzeigen" | "Show less" | "Mostrar menos" | "Afficher moins" | "Mostra meno";
|
|
769
771
|
static get Show_CompleteName(): "Vollständigen Namen anzeigen" | "View full name" | "Mostrar nombre completo" | "Afficher le nom complet" | "Mostrar nome completo" | "Visualizza nome completo";
|
|
@@ -4018,6 +4018,16 @@ export class SDKUI_Localizator {
|
|
|
4018
4018
|
default: return "Nascondi tutti";
|
|
4019
4019
|
}
|
|
4020
4020
|
}
|
|
4021
|
+
static get HideDcmtTypes() {
|
|
4022
|
+
switch (this._cultureID) {
|
|
4023
|
+
case CultureIDs.De_DE: return "Dokumenttypen ausblenden";
|
|
4024
|
+
case CultureIDs.En_US: return "Hide document types";
|
|
4025
|
+
case CultureIDs.Es_ES: return "Ocultar tipos de documento";
|
|
4026
|
+
case CultureIDs.Fr_FR: return "Masquer les types de document";
|
|
4027
|
+
case CultureIDs.Pt_PT: return "Ocultar tipos de documento";
|
|
4028
|
+
default: return "Nascondi tipi documento";
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4021
4031
|
static get HideDetailsWithZeroDocs() {
|
|
4022
4032
|
switch (this._cultureID) {
|
|
4023
4033
|
case CultureIDs.De_DE: return "Details mit 0 Dokumenten ausblenden";
|
|
@@ -7620,6 +7630,16 @@ export class SDKUI_Localizator {
|
|
|
7620
7630
|
default: return "Mostra selezione colonne";
|
|
7621
7631
|
}
|
|
7622
7632
|
}
|
|
7633
|
+
static get ShowDcmtTypes() {
|
|
7634
|
+
switch (this._cultureID) {
|
|
7635
|
+
case CultureIDs.De_DE: return "Dokumenttypen anzeigen";
|
|
7636
|
+
case CultureIDs.En_US: return "Show document types";
|
|
7637
|
+
case CultureIDs.Es_ES: return "Mostrar tipos de documento";
|
|
7638
|
+
case CultureIDs.Fr_FR: return "Afficher les types de document";
|
|
7639
|
+
case CultureIDs.Pt_PT: return "Mostrar tipos de documento";
|
|
7640
|
+
default: return "Mostra tipi documento";
|
|
7641
|
+
}
|
|
7642
|
+
}
|
|
7623
7643
|
static get ShowFloatingBar() {
|
|
7624
7644
|
switch (this._cultureID) {
|
|
7625
7645
|
case CultureIDs.De_DE: return "Floating-Leiste anzeigen";
|
|
@@ -118,6 +118,7 @@ export interface UseDocumentOperationsResult {
|
|
|
118
118
|
closeDcmtFormHandler: () => void;
|
|
119
119
|
handleSignApprove: () => void;
|
|
120
120
|
showSearchTMDatagrid: boolean;
|
|
121
|
+
showDcmtTypesSelection: boolean;
|
|
121
122
|
showExportForm: boolean;
|
|
122
123
|
checkoutInfo: UseCheckInOutOperationsReturn;
|
|
123
124
|
relatedDocumentsInfo: UseRelatedDocumentsReturn;
|
|
@@ -152,6 +152,7 @@ export const useDocumentOperations = (props) => {
|
|
|
152
152
|
const [currentCustomButton, setCurrentCustomButton] = useState();
|
|
153
153
|
// State to control the visibility of the details form
|
|
154
154
|
const [showSearchTMDatagrid, setShowSearchTMDatagrid] = useState(false);
|
|
155
|
+
const [showDcmtTypesSelection, setShowDcmtTypesSelection] = useState(false);
|
|
155
156
|
const [secondaryMasterDcmts, setSecondaryMasterDcmts] = useState([]);
|
|
156
157
|
const [isOpenSharedArchive, setIsOpenSharedArchive] = useState(false);
|
|
157
158
|
const [sharedDcmtFile, setSharedDcmtFile] = useState(undefined);
|
|
@@ -1054,6 +1055,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1054
1055
|
]
|
|
1055
1056
|
};
|
|
1056
1057
|
};
|
|
1058
|
+
const canToggleDcmtTypesSelection = !isMobile && context === SearchResultContext.WORKFLOW_APPROVE;
|
|
1057
1059
|
const otherOperationsMenuItem = () => {
|
|
1058
1060
|
return {
|
|
1059
1061
|
id: 'oth',
|
|
@@ -1085,7 +1087,15 @@ export const useDocumentOperations = (props) => {
|
|
|
1085
1087
|
disabled: false,
|
|
1086
1088
|
onClick: () => setShowFloatingBar(prev => !prev)
|
|
1087
1089
|
}]
|
|
1088
|
-
: [])
|
|
1090
|
+
: []),
|
|
1091
|
+
{
|
|
1092
|
+
id: 'oth-dcmt-types',
|
|
1093
|
+
icon: showDcmtTypesSelection ? _jsx(IconHide, {}) : _jsx(IconShow, {}),
|
|
1094
|
+
name: showDcmtTypesSelection ? SDKUI_Localizator.HideDcmtTypes : SDKUI_Localizator.ShowDcmtTypes,
|
|
1095
|
+
visible: canToggleDcmtTypesSelection,
|
|
1096
|
+
disabled: false,
|
|
1097
|
+
onClick: () => setShowDcmtTypesSelection(prev => !prev)
|
|
1098
|
+
}
|
|
1089
1099
|
]
|
|
1090
1100
|
};
|
|
1091
1101
|
};
|
|
@@ -1454,6 +1464,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1454
1464
|
dcmtFormLayoutMode,
|
|
1455
1465
|
onDcmtFormOpenChange,
|
|
1456
1466
|
showSearchTMDatagrid,
|
|
1467
|
+
showDcmtTypesSelection,
|
|
1457
1468
|
showExportForm,
|
|
1458
1469
|
isOpenBatchUpdate,
|
|
1459
1470
|
isModifiedBatchUpdate,
|