@topconsultnpm/sdkui-react 6.21.0-dev3.2 → 6.21.0-dev3.20

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.
Files changed (51) hide show
  1. package/lib/components/NewComponents/ContextMenu/styles.d.ts +4 -4
  2. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +2 -2
  3. package/lib/components/base/TMDataGrid.js +12 -2
  4. package/lib/components/base/TMDataGridExportForm.js +19 -8
  5. package/lib/components/base/TMFileManagerDataGridView.js +4 -4
  6. package/lib/components/base/TMFileManagerThumbnailItems.js +3 -3
  7. package/lib/components/base/TMFileManagerUtils.d.ts +7 -0
  8. package/lib/components/base/TMFileManagerUtils.js +14 -1
  9. package/lib/components/base/TMModal.js +2 -2
  10. package/lib/components/base/TMTreeView.js +12 -15
  11. package/lib/components/choosers/TMDynDataListItemChooser.js +6 -1
  12. package/lib/components/editors/TMEditorStyled.d.ts +6 -6
  13. package/lib/components/editors/TMMetadataEditor.js +6 -2
  14. package/lib/components/editors/TMMetadataValues.js +10 -2
  15. package/lib/components/features/blog/TMBlogCommentForm.js +5 -2
  16. package/lib/components/features/documents/TMCopyToFolderForm.js +2 -2
  17. package/lib/components/features/documents/TMDcmtIcon.js +1 -1
  18. package/lib/components/features/documents/TMMergeToPdfForm.js +2 -2
  19. package/lib/components/features/documents/TMRelationViewer.js +6 -1
  20. package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +0 -13
  21. package/lib/components/features/documents/copyAndMergeDcmtsShared.js +1 -39
  22. package/lib/components/features/search/TMMetadataOutputForm.d.ts +17 -0
  23. package/lib/components/features/search/TMMetadataOutputForm.js +225 -0
  24. package/lib/components/features/search/TMMetadataSorterForm.d.ts +17 -0
  25. package/lib/components/features/search/TMMetadataSorterForm.js +243 -0
  26. package/lib/components/features/search/TMSearchQueryEditor.js +14 -8
  27. package/lib/components/features/search/TMSearchQueryPanel.js +208 -58
  28. package/lib/components/features/search/TMSearchResult.js +2 -3
  29. package/lib/components/features/search/TMViewHistoryDcmt.js +1 -1
  30. package/lib/components/features/search/metadataFormHelper.d.ts +16 -0
  31. package/lib/components/features/search/metadataFormHelper.js +77 -0
  32. package/lib/components/grids/TMBlogAttachments.js +2 -2
  33. package/lib/components/grids/TMBlogsPost.js +5 -3
  34. package/lib/components/grids/TMBlogsPostUtils.d.ts +1 -0
  35. package/lib/components/grids/TMBlogsPostUtils.js +3 -1
  36. package/lib/helper/MergePdfManager.js +7 -4
  37. package/lib/helper/SDKUI_Globals.js +2 -1
  38. package/lib/helper/SDKUI_Localizator.d.ts +4 -0
  39. package/lib/helper/SDKUI_Localizator.js +40 -0
  40. package/lib/helper/TMUtils.d.ts +23 -0
  41. package/lib/helper/TMUtils.js +55 -0
  42. package/lib/helper/checkinCheckoutManager.d.ts +4 -3
  43. package/lib/helper/checkinCheckoutManager.js +29 -11
  44. package/lib/hooks/useCheckInOutOperations.d.ts +4 -3
  45. package/lib/hooks/useDataUserIdItem.js +1 -1
  46. package/lib/hooks/useDcmtOperations.d.ts +18 -1
  47. package/lib/hooks/useDcmtOperations.js +67 -21
  48. package/lib/hooks/useDocumentOperations.js +3 -3
  49. package/lib/hooks/useRelatedDocuments.js +4 -4
  50. package/lib/services/platform_services.d.ts +4 -4
  51. package/package.json +10 -7
@@ -0,0 +1,243 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { OrderByItem, SDK_Localizator } from "@topconsultnpm/sdk-ts";
4
+ import { IconAddCircleOutline, IconApply, IconClear, IconDelete, IconDraggabledots, IconUndo, SDKUI_Localizator } from "../../../helper";
5
+ import TMToppyMessage from "../../../helper/TMToppyMessage";
6
+ import { ButtonNames, TMMessageBoxManager } from "../../base/TMPopUp";
7
+ import { TMColors } from "../../../utils/theme";
8
+ import { StyledToolbarForm } from "../../base/Styled";
9
+ import TMButton from "../../base/TMButton";
10
+ import TMModal from "../../base/TMModal";
11
+ import { TMMetadataChooserForm } from "../../choosers/TMMetadataChooser";
12
+ import TMDropDown from "../../editors/TMDropDown";
13
+ import { TMMetadataIcon } from "../../viewers/TMMidViewer";
14
+ import { loadMetadataFromQd, removeDuplicatesByTidMid, areArraysEqual } from "./metadataFormHelper";
15
+ const TMMetadataSorterForm = (props) => {
16
+ const { qd, selectedOrderByItems, allowSysMetadata = true, filterMetadata, onClose, onChoose } = props;
17
+ // =============================================================================
18
+ // STATE
19
+ // =============================================================================
20
+ // Stato iniziale degli OrderByItem (per confronto isModified)
21
+ const initialOrderByItemsRef = useRef((selectedOrderByItems ?? []).map(item => {
22
+ const newItem = new OrderByItem();
23
+ newItem.tid = item.tid;
24
+ newItem.mid = item.mid;
25
+ newItem.asc = item.asc ?? true;
26
+ return newItem;
27
+ }));
28
+ // Lista degli OrderByItem correnti (inizializzata da selectedOrderByItems)
29
+ const [orderByItems, setOrderByItems] = useState(() => {
30
+ // Clona gli OrderByItem iniziali per evitare mutazioni
31
+ return (selectedOrderByItems ?? []).map(item => {
32
+ const newItem = new OrderByItem();
33
+ newItem.tid = item.tid;
34
+ newItem.mid = item.mid;
35
+ newItem.asc = item.asc ?? true;
36
+ return newItem;
37
+ });
38
+ });
39
+ // Calcola se ci sono modifiche rispetto allo stato iniziale
40
+ const isModified = useMemo(() => {
41
+ return !areArraysEqual(orderByItems, initialOrderByItemsRef.current, (a, b) => a.asc === b.asc);
42
+ }, [orderByItems]);
43
+ // Lista "piatta" di tutti i metadati estratti dai DTD, con chiave univoca
44
+ const [metadataList, setMetadataList] = useState([]);
45
+ // Flag di caricamento
46
+ const [isLoading, setIsLoading] = useState(true);
47
+ // Flag per mostrare il TMMetadataChooserForm
48
+ const [showMetadataChooser, setShowMetadataChooser] = useState(false);
49
+ // Item in fase di drag
50
+ const [draggingItem, setDraggingItem] = useState(undefined);
51
+ // =============================================================================
52
+ // MEMOIZZAZIONI per evitare re-render del TMMetadataChooserForm
53
+ // =============================================================================
54
+ // Lista di TID_MID già selezionati (per escluderli dal chooser)
55
+ const selectedIDs = useMemo(() => orderByItems.map(oi => ({ tid: oi.tid, mid: oi.mid })), [orderByItems]);
56
+ // Callback per chiudere il chooser
57
+ const handleCloseChooser = useCallback(() => {
58
+ setShowMetadataChooser(false);
59
+ }, []);
60
+ // =============================================================================
61
+ // EFFECT: Carica i metadati al mount
62
+ // =============================================================================
63
+ useEffect(() => {
64
+ const load = async () => {
65
+ setIsLoading(true);
66
+ try {
67
+ const { metadata } = await loadMetadataFromQd(qd, filterMetadata);
68
+ setMetadataList(metadata);
69
+ }
70
+ catch (error) {
71
+ console.error("Errore nel caricamento dei metadati:", error);
72
+ setMetadataList([]);
73
+ }
74
+ finally {
75
+ setIsLoading(false);
76
+ }
77
+ };
78
+ load();
79
+ }, [qd, filterMetadata]);
80
+ // =============================================================================
81
+ // HELPER: Trova il MetadataDescriptor per un OrderByItem
82
+ // =============================================================================
83
+ const getMetadataForOrderByItem = useCallback((item) => {
84
+ return metadataList.find(md => md.customData1 === item.tid && md.id === item.mid);
85
+ }, [metadataList]);
86
+ // =============================================================================
87
+ // HANDLER: Conferma la scelta dal chooser (sincronizza la lista completa)
88
+ // =============================================================================
89
+ const handleChooseFromChooser = useCallback((tid_mids) => {
90
+ // Se la lista è vuota o undefined, rimuovi tutti
91
+ if (!tid_mids || tid_mids.length === 0) {
92
+ setOrderByItems([]);
93
+ setShowMetadataChooser(false);
94
+ return;
95
+ }
96
+ setOrderByItems(prev => {
97
+ // Filtra quelli esistenti che sono ancora selezionati (mantenendo ordine e impostazioni asc/desc)
98
+ const kept = prev.filter(oi => tid_mids.some(tm => tm.tid === oi.tid && tm.mid === oi.mid));
99
+ // Trova i nuovi da aggiungere
100
+ const newItems = [];
101
+ for (const tm of tid_mids) {
102
+ const exists = prev.some(oi => oi.tid === tm.tid && oi.mid === tm.mid);
103
+ if (!exists) {
104
+ const newItem = new OrderByItem();
105
+ newItem.tid = tm.tid;
106
+ newItem.mid = tm.mid;
107
+ newItem.asc = true;
108
+ newItems.push(newItem);
109
+ }
110
+ }
111
+ return removeDuplicatesByTidMid([...kept, ...newItems]);
112
+ });
113
+ setShowMetadataChooser(false);
114
+ }, []);
115
+ // =============================================================================
116
+ // HANDLER: Rimuove un ordinamento
117
+ // =============================================================================
118
+ const handleRemoveOrderBy = useCallback((index) => {
119
+ setOrderByItems(prev => prev.filter((_, i) => i !== index));
120
+ }, []);
121
+ // =============================================================================
122
+ // HANDLER: Toggle ascendente/discendente
123
+ // =============================================================================
124
+ const handleChangeAsc = useCallback((index, asc) => {
125
+ setOrderByItems(prev => prev.map((item, i) => {
126
+ if (i !== index)
127
+ return item;
128
+ const newItem = new OrderByItem();
129
+ newItem.tid = item.tid;
130
+ newItem.mid = item.mid;
131
+ newItem.asc = asc;
132
+ return newItem;
133
+ }));
134
+ }, []);
135
+ // =============================================================================
136
+ // DRAG & DROP HANDLERS
137
+ // =============================================================================
138
+ const handleDragStart = useCallback((e, item) => {
139
+ // Previeni il drag se il target è l'icona elimina o il dropdown
140
+ const target = e.target;
141
+ if (target.closest('[data-no-drag="true"]')) {
142
+ e.preventDefault();
143
+ return;
144
+ }
145
+ setDraggingItem(item);
146
+ e.dataTransfer.setData('text/plain', '');
147
+ e.dataTransfer.effectAllowed = 'move';
148
+ }, []);
149
+ const handleDragEnd = useCallback(() => {
150
+ setDraggingItem(undefined);
151
+ }, []);
152
+ const handleDragOver = useCallback((e) => {
153
+ e.preventDefault();
154
+ e.dataTransfer.dropEffect = 'move';
155
+ }, []);
156
+ const handleDrop = useCallback((e, targetItem) => {
157
+ e.preventDefault();
158
+ if (!draggingItem)
159
+ return;
160
+ const currentIndex = orderByItems.indexOf(draggingItem);
161
+ const targetIndex = orderByItems.indexOf(targetItem);
162
+ if (currentIndex === -1 || targetIndex === -1 || currentIndex === targetIndex) {
163
+ setDraggingItem(undefined);
164
+ return;
165
+ }
166
+ const listCopy = [...orderByItems];
167
+ listCopy.splice(currentIndex, 1);
168
+ listCopy.splice(targetIndex, 0, draggingItem);
169
+ setOrderByItems(listCopy);
170
+ setDraggingItem(undefined);
171
+ }, [draggingItem, orderByItems]);
172
+ // =============================================================================
173
+ // HANDLER: Rollback allo stato iniziale
174
+ // =============================================================================
175
+ const handleRollback = useCallback(() => {
176
+ setOrderByItems(initialOrderByItemsRef.current.map(item => {
177
+ const newItem = new OrderByItem();
178
+ newItem.tid = item.tid;
179
+ newItem.mid = item.mid;
180
+ newItem.asc = item.asc;
181
+ return newItem;
182
+ }));
183
+ }, []);
184
+ // =============================================================================
185
+ // HANDLER: Chiusura con conferma se modificato
186
+ // =============================================================================
187
+ const confirmCloseContainerId = "TMMetadataSorterFormConfirmClose";
188
+ const handleClose = useCallback(() => {
189
+ if (!isModified) {
190
+ onClose();
191
+ return;
192
+ }
193
+ TMMessageBoxManager.show({
194
+ parentId: confirmCloseContainerId,
195
+ message: SDKUI_Localizator.ConfirmOnCancel,
196
+ buttons: [ButtonNames.YES, ButtonNames.NO],
197
+ onButtonClick: (buttonClicked) => {
198
+ if (buttonClicked === ButtonNames.YES) {
199
+ onClose();
200
+ }
201
+ }
202
+ });
203
+ }, [isModified, onClose]);
204
+ // =============================================================================
205
+ // HANDLER: Conferma la selezione
206
+ // =============================================================================
207
+ const handleConfirm = useCallback(() => {
208
+ onChoose?.(orderByItems.length > 0 ? orderByItems : undefined);
209
+ onClose();
210
+ }, [orderByItems, onChoose, onClose]);
211
+ // =============================================================================
212
+ // RENDER
213
+ // =============================================================================
214
+ return (_jsxs(_Fragment, { children: [_jsxs(TMModal, { title: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QueryOrderBy}${orderByItems.length > 0 ? ` (${orderByItems.length})` : ''}`, width: "600px", height: "500px", onClose: handleClose, hidePopup: false, askClosingConfirm: isModified, children: [_jsx("div", { id: confirmCloseContainerId }), _jsxs("div", { style: { display: 'flex', flexDirection: 'column', height: '100%', gap: '10px' }, children: [_jsxs(StyledToolbarForm, { children: [_jsx(TMButton, { caption: SDKUI_Localizator.Confirm, icon: _jsx(IconApply, {}), btnStyle: "toolbar", color: "success", disabled: !isModified, onClick: handleConfirm }), _jsx(TMButton, { caption: SDKUI_Localizator.Undo, icon: _jsx(IconUndo, {}), btnStyle: "toolbar", color: "tertiary", disabled: !isModified, onClick: handleRollback }), _jsx(TMButton, { caption: SDKUI_Localizator.Add, icon: _jsx(IconAddCircleOutline, {}), btnStyle: "toolbar", onClick: () => setShowMetadataChooser(true) }), _jsx(TMButton, { caption: SDKUI_Localizator.Clear, icon: _jsx(IconClear, {}), btnStyle: "toolbar", disabled: orderByItems.length === 0, onClick: () => setOrderByItems([]) })] }), _jsxs("div", { style: {
215
+ flex: 1,
216
+ overflow: 'auto',
217
+ border: `1px solid ${TMColors.border_normal}`,
218
+ borderRadius: '4px',
219
+ padding: '5px'
220
+ }, children: [isLoading && _jsxs("p", { style: { textAlign: 'center', padding: '20px' }, children: [SDKUI_Localizator.Loading, "..."] }), !isLoading && orderByItems.length === 0 && (_jsx(TMToppyMessage, { message: SDKUI_Localizator.NoSortingApplied, titleTooltip: SDKUI_Localizator.NoSortingApplied })), !isLoading && orderByItems.length > 0 && (_jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '2px' }, children: orderByItems.map((item, index) => {
221
+ const md = getMetadataForOrderByItem(item);
222
+ const isDragging = draggingItem === item;
223
+ return (_jsxs("div", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragEnd: handleDragEnd, onDragOver: handleDragOver, onDrop: (e) => handleDrop(e, item), style: {
224
+ display: 'flex',
225
+ alignItems: 'center',
226
+ gap: '6px',
227
+ padding: '4px 8px',
228
+ backgroundColor: isDragging ? TMColors.primary_container : TMColors.default_background,
229
+ borderRadius: '3px',
230
+ border: `1px solid ${isDragging ? TMColors.primaryColor : TMColors.border_normal}`,
231
+ minHeight: '32px',
232
+ cursor: 'grab',
233
+ transition: 'all 0.2s ease',
234
+ transform: isDragging ? 'scale(1.02)' : 'scale(1)',
235
+ boxShadow: isDragging ? '0 4px 12px rgba(0,0,0,0.15)' : 'none',
236
+ opacity: isDragging ? 0.9 : 1,
237
+ }, children: [_jsx("div", { style: { display: 'flex', cursor: 'grab' }, children: _jsx(IconDraggabledots, { fontSize: 15, color: TMColors.button_icon }) }), _jsx(TMMetadataIcon, { tid: item.tid ?? 0, md: md }), _jsx("span", { style: { flex: 1, fontSize: '13px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: md?.name ?? `MID: ${item.mid}` }), _jsx("div", { "data-no-drag": "true", onMouseDown: (e) => e.stopPropagation(), children: _jsx(TMDropDown, { width: "175px", height: "28px", value: item.asc ? 'asc' : 'desc', dataSource: [
238
+ { value: 'asc', display: SDKUI_Localizator.ValueAscending },
239
+ { value: 'desc', display: SDKUI_Localizator.ValueDescending }
240
+ ], onValueChanged: (e) => handleChangeAsc(index, e.target.value === 'asc') }) }), _jsx("div", { "data-no-drag": "true", onMouseDown: (e) => e.stopPropagation(), children: _jsx(TMButton, { caption: SDKUI_Localizator.Remove, icon: _jsx(IconDelete, { color: TMColors.error }), btnStyle: "icon", onClick: () => handleRemoveOrderBy(index) }) })] }, `${item.tid}_${item.mid}_${index}`));
241
+ }) }))] })] })] }), showMetadataChooser && (_jsx(TMMetadataChooserForm, { allowMultipleSelection: true, height: "600px", width: "700px", allowSysMetadata: allowSysMetadata, filterMetadata: filterMetadata, qd: qd, selectedIDs: selectedIDs, onClose: handleCloseChooser, onChoose: handleChooseFromChooser }))] }));
242
+ };
243
+ export default TMMetadataSorterForm;
@@ -148,17 +148,23 @@ const TMSearchWhereItemEditor = React.memo(({ whereItem, queryParamsDynDataList,
148
148
  let dtd = await DcmtTypeListCacheService.GetAsync(whereItem.tid, true);
149
149
  return dtd?.metadata?.find(o => o.id === whereItem.mid);
150
150
  };
151
- // Rimuove gli apici singoli da valori separati da virgola: 'msegato','plevolella' -> msegato,plevolella
151
+ // Rimuove gli apici singoli da valori separati da virgola: 'val1','val2' -> val1,val2
152
+ // Applica trim solo ai valori quotati, preservando gli spazi nei valori non quotati
152
153
  const stripQuotes = (value) => {
153
154
  if (!value || typeof value !== 'string')
154
155
  return value;
155
- return value.split(',').map(item => {
156
- const trimmed = item.trim();
157
- if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
158
- return trimmed.slice(1, -1);
159
- }
160
- return trimmed;
161
- }).join(',');
156
+ try {
157
+ return value.split(',').map(item => {
158
+ const trimmed = item.trim();
159
+ if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
160
+ return trimmed.slice(1, -1); // trim + rimuovi apici
161
+ }
162
+ return item; // mantieni originale (con spazi)
163
+ }).join(',');
164
+ }
165
+ catch {
166
+ return value; // in caso di errore, ritorna il valore iniziale
167
+ }
162
168
  };
163
169
  const normalizeValue = (value, isForValue1 = true) => {
164
170
  let newValues = [];
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
- import { PlatformObjectValidator, QueryDescriptor, WhereItem, SDK_Localizator, OrderByItem, SelectItem, SelectItemVisibilities, SDK_Globals, SavedQueryCacheService, SearchEngine, QueryOperators, AccessLevelsEx, AccessLevels } from '@topconsultnpm/sdk-ts';
3
+ import { PlatformObjectValidator, QueryDescriptor, WhereItem, SDK_Localizator, SelectItemVisibilities, SDK_Globals, SavedQueryCacheService, SearchEngine, QueryOperators, AccessLevelsEx, AccessLevels } from '@topconsultnpm/sdk-ts';
4
4
  import styled from 'styled-components';
5
5
  import TMSearchQueryEditor from './TMSearchQueryEditor';
6
- import { getDcmtTypesByQdAsync, SDKUI_Localizator, getQD, IconMenuVertical, IconAddCircleOutline, IconEdit, IconEasy, IconAdvanced, deepCompare, IconSearch, IconClear, getDefaultOperator, prepareQdForSearchAsync, IsParametricQuery, SDKUI_Globals, IconArrowRight, IconMenuCAArchive, getListMaxItems, DEFAULT_MAX_DCMTS_TO_BE_RETURNED } from '../../../helper';
6
+ import { getDcmtTypesByQdAsync, SDKUI_Localizator, getQD, IconMenuVertical, IconAddCircleOutline, IconEdit, IconEasy, IconAdvanced, deepCompare, IconSearch, IconClear, getDefaultOperator, prepareQdForSearchAsync, IsParametricQuery, SDKUI_Globals, IconArrowRight, IconMenuCAArchive, getListMaxItems, DEFAULT_MAX_DCMTS_TO_BE_RETURNED, IconSortAsc, IconSortDesc, IconFilter, IconColumns, IconSort } from '../../../helper';
7
7
  import { useQueryParametersDialog } from '../../../hooks/useQueryParametersDialog';
8
8
  import { FormModes } from '../../../ts';
9
9
  import { TMColors } from '../../../utils/theme';
@@ -21,6 +21,9 @@ import TMSavedQueryForm from './TMSavedQueryForm';
21
21
  import { ContextMenu } from '../../NewComponents/ContextMenu';
22
22
  import { AdvancedMenuButtons } from '../../editors/TMMetadataValues';
23
23
  import TMToppyMessage from '../../../helper/TMToppyMessage';
24
+ import TMMetadataSorterForm from './TMMetadataSorterForm';
25
+ import TMMetadataOutputForm from './TMMetadataOutputForm';
26
+ import TMTooltip from '../../base/TMTooltip';
24
27
  const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, SQD, inputMids, onSearchCompleted, onSqdSaved, onBack, onClosePanel, allowMaximize = true, onMaximizePanel, onBackToResult, passToArchiveCallback, maxDcmtsToBeReturned }) => {
25
28
  const [confirmQueryParams, ConfirmQueryParamsDialog] = useQueryParametersDialog();
26
29
  const [qd, setQd] = useState();
@@ -34,7 +37,7 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
34
37
  const [showAdvancedSearch, setShowAdvancedSearch] = useState(false);
35
38
  const [showFiltersConfig, setShowFiltersConfig] = useState(false);
36
39
  const [showOutputConfig, setShowOutputConfig] = useState(false);
37
- const [showOrderByConfig, setShowOrderByConfig] = useState(false);
40
+ const [showMetadataSorterForm, setShowMetadataSorterForm] = useState(false);
38
41
  const [showDistinctValuesPanel, setShowDistinctValuesPanel] = useState(false);
39
42
  const [focusedTidMid, setFocusedTidMid] = useState();
40
43
  const [modalIsOpen, setModalIsOpen] = useState(false);
@@ -162,7 +165,7 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
162
165
  newWi.init({ ...curItem, value1: undefined, value2: undefined });
163
166
  return newWi;
164
167
  });
165
- setQd({ ...qd, where: newWhere });
168
+ setQd({ ...qd, where: newWhere, orderBy: [] });
166
169
  };
167
170
  const searchAsync = async (qdInput, isAdvancedSearch) => {
168
171
  onSearchCompleted?.([], undefined); // reset results
@@ -266,61 +269,16 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
266
269
  setQd({ ...qd, where: newWhere });
267
270
  }, [qd, fromDTD?.metadata, SQD?.masterTID]);
268
271
  const handleCloseOutputConfig = useCallback(() => setShowOutputConfig(false), []);
269
- const handleChooseOutput = useCallback((tid_mids) => {
270
- if (!fromDTD?.metadata)
271
- return;
272
- if (!tid_mids)
273
- return;
274
- // copia dei SelectItems senza i rimossi
275
- let newSelect = qd?.select?.filter(item => tid_mids?.some(tm => tm.mid == item.mid)) ?? [];
276
- // aggiungiamo i nuovi
277
- for (const tm of tid_mids.filter(tm => !qd?.select?.some(item => item.mid == tm.mid))) {
278
- let md = fromDTD?.metadata.find(o => o.id == tm.mid);
279
- let si = new SelectItem();
280
- si.visibility = SelectItemVisibilities.Visible;
281
- si.tid = SQD?.masterTID;
282
- si.mid = md?.id;
283
- let indexMD = 0;
284
- for (const m of fromDTD?.metadata ?? []) {
285
- if (m.id == si.mid)
286
- break;
287
- if (newSelect.findIndex(o => o.mid == m.id && o.tid == SQD?.masterTID) < 0)
288
- continue;
289
- indexMD++;
290
- }
291
- newSelect.splice(indexMD, 0, si);
292
- }
293
- setQd({ ...qd, select: newSelect });
294
- }, [qd, fromDTD?.metadata, SQD?.masterTID]);
295
- const handleCloseOrderByConfig = useCallback(() => setShowOrderByConfig(false), []);
296
- const handleChooseOrderBy = useCallback((tid_mids) => {
297
- if (!fromDTD?.metadata)
298
- return;
299
- if (!tid_mids)
300
- return;
301
- // copia dei OrderByItems senza i rimossi
302
- let newOrderBy = qd?.orderBy?.filter(item => tid_mids?.some(tm => tm.mid == item.mid)) ?? [];
303
- // aggiungiamo i nuovi
304
- for (const tm of tid_mids.filter(tm => !qd?.orderBy?.some(item => item.mid == tm.mid))) {
305
- let md = fromDTD?.metadata.find(o => o.id == tm.mid);
306
- let oi = new OrderByItem();
307
- oi.tid = SQD?.masterTID;
308
- oi.mid = md?.id;
309
- oi.asc = true;
310
- newOrderBy.push(oi);
311
- }
312
- setQd({ ...qd, orderBy: newOrderBy });
313
- }, [qd, fromDTD?.metadata, SQD?.masterTID]);
314
272
  const contextMenuItems = useMemo(() => [
315
273
  ...(showBackToResultButton ? [{ icon: _jsx(IconArrowRight, {}), name: "Vai a risultato", onClick: () => { onBackToResult?.(); } }] : []),
316
274
  { icon: _jsx(IconAddCircleOutline, {}), name: SDKUI_Localizator.SavedQueryNew, beginGroup: showBackToResultButton, onClick: () => { openSqdForm(FormModes.Create); } },
317
275
  { icon: _jsx(IconEdit, {}), name: SDKUI_Localizator.SavedQueryUpdate, disabled: (SQD && SQD.id == 1), onClick: () => { openSqdForm(FormModes.Update); } },
318
276
  { icon: showAdvancedSearch ? _jsx(IconEasy, {}) : _jsx(IconAdvanced, {}), beginGroup: true, name: showAdvancedSearch ? SDKUI_Localizator.Search_Easy : SDKUI_Localizator.Search_Advanced, onClick: () => { changeAdvancedSearchAsync(!showAdvancedSearch); } },
319
- { icon: _jsx(IconEdit, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QueryWhere}`, beginGroup: true, onClick: () => { setShowFiltersConfig(true); } },
320
- { icon: _jsx(IconEdit, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QuerySelect}`, onClick: () => { setShowOutputConfig(true); } },
321
- { icon: _jsx(IconEdit, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QueryOrderBy}`, onClick: () => { setShowOrderByConfig(true); } },
277
+ { icon: _jsx(IconFilter, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QueryWhere}`, beginGroup: true, onClick: () => { setShowFiltersConfig(true); } },
278
+ { icon: _jsx(IconColumns, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QuerySelect}`, onClick: () => { setShowOutputConfig(true); } },
279
+ { icon: _jsx(IconSort, {}), name: `${SDKUI_Localizator.Configure} - ${SDK_Localizator.QueryOrderBy}`, onClick: () => { setShowMetadataSorterForm(true); } },
322
280
  { icon: _jsx(IconMenuCAArchive, { viewBox: '11 11.5 26 27', fontSize: 16, strokeWidth: 2, color: 'black' }), beginGroup: true, name: SDKUI_Localizator.PassToArchive, disabled: fromDTD?.perm?.canArchive !== AccessLevelsEx.Yes && fromDTD?.perm?.canArchive !== AccessLevelsEx.Mixed, onClick: handlePassToArchive }
323
- ], [showBackToResultButton, showAdvancedSearch, SQD, onBackToResult, openSqdForm, changeAdvancedSearchAsync, setShowFiltersConfig, setShowOutputConfig, setShowOrderByConfig, handlePassToArchive, fromDTD?.perm?.canArchive]);
281
+ ], [showBackToResultButton, showAdvancedSearch, SQD, onBackToResult, openSqdForm, changeAdvancedSearchAsync, setShowFiltersConfig, setShowOutputConfig, handlePassToArchive, fromDTD?.perm?.canArchive]);
324
282
  const captionText = showAllMdWhere ? SDKUI_Localizator.ShowLess : SDKUI_Localizator.ShowAll;
325
283
  let maxItems = getListMaxItems(deviceType ?? DeviceType.DESKTOP);
326
284
  const diff = (qd?.where?.length ?? 0) - maxItems;
@@ -329,7 +287,25 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
329
287
  : _jsx(_Fragment, {}) }), children: [_jsx(ConfirmQueryParamsDialog, {}), SQD
330
288
  ? _jsxs("div", { onContextMenu: (e) => e.preventDefault(), style: { height: '100%', width: '100%', position: 'relative', display: showSqdForm ? 'none' : 'flex', flexDirection: 'column', gap: 5 }, children: [showAdvancedSearch
331
289
  ? _jsx(TMQueryEditor, { formMode: FormModes.Update, showToolbar: false, inputData: qd, validateSelect: true, showApply: false, onQDChanged: handleQdChanged, updateIsModalOpen: updateIsModalOpen })
332
- : _jsx(TMSearchQueryEditor, { qd: qd, dcmtTypesList: dcmtTypesList, isExpertMode: isExpertMode, showAllMdWhere: showAllMdWhere, onQdChanged: handleQdChanged, onFocusedMetadataChanged: setFocusedTidMid, onAdvancedMenuClick: handleAdvancedMenuClick, updateIsModalOpen: updateIsModalOpen }), _jsxs("div", { style: {
290
+ : _jsx(TMSearchQueryEditor, { qd: qd, dcmtTypesList: dcmtTypesList, isExpertMode: isExpertMode, showAllMdWhere: showAllMdWhere, onQdChanged: handleQdChanged, onFocusedMetadataChanged: setFocusedTidMid, onAdvancedMenuClick: handleAdvancedMenuClick, updateIsModalOpen: updateIsModalOpen }), qd?.select && qd.select.length > 0 && (_jsxs(StyledSelectBadgesContainer, { children: [_jsxs(StyledSelectLabel, { children: [SDK_Localizator.QuerySelect, ":"] }), _jsx(StyledSelectBadgesWrapper, { children: (() => {
291
+ const maxVisible = isMobile ? 1 : 2;
292
+ const visibleItems = qd.select.slice(0, maxVisible);
293
+ const hiddenCount = qd.select.length - maxVisible;
294
+ return (_jsxs(_Fragment, { children: [visibleItems.map((si, index) => {
295
+ const md = fromDTD?.metadata?.find(m => m.id === si.mid);
296
+ const mdName = md?.nameLoc ?? md?.name ?? `MID ${si.mid}`;
297
+ return (_jsxs(StyledSelectBadge, { children: [_jsx(IconColumns, { fontSize: 12 }), _jsx("span", { className: "badge-name", children: mdName })] }, `${si.tid}-${si.mid}-${index}`));
298
+ }), hiddenCount > 0 && (_jsxs(StyledSelectBadgeMore, { onClick: () => setShowOutputConfig(true), children: ["+", hiddenCount] }))] }));
299
+ })() }), _jsx(StyledSelectEditButton, { title: SDKUI_Localizator.Configure, onClick: () => setShowOutputConfig(true), children: _jsx(IconEdit, { fontSize: 16 }) })] })), qd?.orderBy && qd.orderBy.length > 0 && (_jsxs(StyledOrderByBadgesContainer, { children: [_jsxs(StyledOrderByLabel, { children: [qd.orderBy.length === 1 ? SDKUI_Localizator.SortBy : SDKUI_Localizator.SortByPlural, ":"] }), _jsx(StyledOrderByBadgesWrapper, { children: (() => {
300
+ const maxVisible = isMobile ? 1 : 2;
301
+ const visibleItems = qd.orderBy.slice(0, maxVisible);
302
+ const hiddenCount = qd.orderBy.length - maxVisible;
303
+ return (_jsxs(_Fragment, { children: [visibleItems.map((obi, index) => {
304
+ const md = fromDTD?.metadata?.find(m => m.id === obi.mid);
305
+ const mdName = md?.nameLoc ?? md?.name ?? `MID ${obi.mid}`;
306
+ return (_jsxs(StyledOrderByBadge, { children: [_jsx(TMTooltip, { content: obi.asc !== false ? SDKUI_Localizator.ValueAscending : SDKUI_Localizator.ValueDescending, children: obi.asc !== false ? (_jsx(IconSortAsc, { fontSize: 12 })) : (_jsx(IconSortDesc, { fontSize: 12 })) }), _jsx("span", { className: "badge-name", children: mdName })] }, `${obi.tid}-${obi.mid}-${index}`));
307
+ }), hiddenCount > 0 && (_jsxs(StyledOrderByBadgeMore, { onClick: () => setShowMetadataSorterForm(true), children: ["+", hiddenCount] }))] }));
308
+ })() }), _jsx(StyledOrderByEditButton, { title: SDKUI_Localizator.Configure, onClick: () => setShowMetadataSorterForm(true), children: _jsx(IconEdit, { fontSize: 16 }) })] })), _jsxs("div", { style: {
333
309
  display: 'flex',
334
310
  flexWrap: 'wrap',
335
311
  justifyContent: 'center',
@@ -338,8 +314,12 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
338
314
  width: '100%'
339
315
  }, children: [_jsx(TMButton, { btnStyle: 'advanced', icon: _jsx(IconSearch, {}), showTooltip: false, width: '90px', caption: SDKUI_Localizator.Search, advancedColor: '#4A96D2', onClick: handleSearchButtonClick }), _jsx(TMButton, { width: '90px', btnStyle: 'advanced', advancedType: 'primary', showTooltip: false, caption: SDKUI_Localizator.Clear, icon: _jsx(IconClear, {}), advancedColor: 'white', color: 'primaryOutline', onClick: clearFilters }), (!showAdvancedSearch && qd?.where && qd.where.length > initialMaxItems) && (_jsx(TMButton, { width: '120px', btnStyle: isMobile ? 'icon' : 'advanced', advancedColor: TMColors.button_primary, caption: captionText, showTooltip: false, icon: isMobile ? (_jsx("div", { children: _jsx("p", { children: showAllMdWhere ? `-${diff}` : `+${diff}` }) })) : (_jsx("p", { children: showAllMdWhere ? `-${diff}` : `+${diff}` })), onClick: () => setShowAllMdWhere(!showAllMdWhere) }))] }), showFiltersConfig &&
340
316
  _jsx(TMMetadataChooserForm, { allowMultipleSelection: true, height: '500px', width: '600px', allowSysMetadata: true, filterMetadata: (o => o.perm?.canSearch === AccessLevels.Yes), qd: qd, selectedIDs: qd?.where?.map((w) => ({ tid: w.tid, mid: w.mid })), onClose: handleCloseFiltersConfig, onChoose: handleChooseFilters }), showOutputConfig &&
341
- _jsx(TMMetadataChooserForm, { allowMultipleSelection: true, height: '500px', width: '600px', allowSysMetadata: true, filterMetadata: (o => o.perm?.canView === AccessLevels.Yes || o.perm?.canUpdate === AccessLevels.Yes), qd: qd, selectedIDs: qd?.select?.map((item) => ({ tid: item.tid, mid: item.mid })), onClose: handleCloseOutputConfig, onChoose: handleChooseOutput }), showOrderByConfig &&
342
- _jsx(TMMetadataChooserForm, { allowMultipleSelection: true, height: '500px', width: '600px', allowSysMetadata: true, filterMetadata: (o => o.perm?.canView === AccessLevels.Yes || o.perm?.canUpdate === AccessLevels.Yes), qd: qd, selectedIDs: qd?.orderBy?.map((item) => ({ tid: item.tid, mid: item.mid })), onClose: handleCloseOrderByConfig, onChoose: handleChooseOrderBy })] })
317
+ _jsx(TMMetadataOutputForm, { qd: qd, selectedSelectItems: qd?.select, allowSysMetadata: true, filterMetadata: (o => o.perm?.canView === AccessLevels.Yes || o.perm?.canUpdate === AccessLevels.Yes), onClose: handleCloseOutputConfig, onChoose: (selectItems) => {
318
+ setQd({ ...qd, select: selectItems });
319
+ } }), showMetadataSorterForm &&
320
+ _jsx(TMMetadataSorterForm, { qd: qd, selectedOrderByItems: qd?.orderBy, allowSysMetadata: true, filterMetadata: (o => o.perm?.canView === AccessLevels.Yes || o.perm?.canUpdate === AccessLevels.Yes), onClose: () => setShowMetadataSorterForm(false), onChoose: (orderByItems) => {
321
+ setQd({ ...qd, orderBy: orderByItems });
322
+ } })] })
343
323
  :
344
324
  _jsx(TMToppyMessage, { message: SDKUI_Localizator.DcmtTypeSelectOrQuickSearch, titleTooltip: SDKUI_Localizator.DcmtTypeSelectOrQuickSearch }), showSqdForm &&
345
325
  _jsx(StyledModalContainer, { style: { backgroundColor: `${TMColors.backgroundColorHeader}12` }, children: _jsx(TMSavedQueryForm, { height: '50%', width: '50%', id: formModeSqdForm === FormModes.Create ? -1 : SQD?.id, title: 'Ricerca rapida', formMode: formModeSqdForm, showBackButton: true, qd: qd, isAdvancedSearch: showAdvancedSearch, isModal: false, onClose: () => { setShowSqdForm(false); }, onSaved: onSqdSaved }) })] }), showDistinctValuesPanel &&
@@ -415,6 +395,174 @@ export const refreshLastSearch = async (qd) => {
415
395
  }
416
396
  return searchResults;
417
397
  };
398
+ // =============================================================================
399
+ // STYLED COMPONENTS per i badge degli ordinamenti
400
+ // =============================================================================
401
+ const StyledOrderByBadgesContainer = styled.div `
402
+ display: flex;
403
+ flex-wrap: wrap;
404
+ align-items: center;
405
+ gap: 8px;
406
+ padding: 6px 10px;
407
+ margin: 1px 0;
408
+ background: linear-gradient(135deg, rgba(74, 150, 210, 0.08) 0%, rgba(37, 89, 165, 0.08) 100%);
409
+ border-radius: 8px;
410
+ border: 1px solid rgba(74, 150, 210, 0.2);
411
+ `;
412
+ const StyledOrderByLabel = styled.span `
413
+ font-size: 0.82rem;
414
+ font-weight: 600;
415
+ color: #4A96D2;
416
+ white-space: nowrap;
417
+ `;
418
+ const StyledOrderByBadgesWrapper = styled.div `
419
+ display: flex;
420
+ flex-wrap: wrap;
421
+ gap: 6px;
422
+ align-items: center;
423
+ flex: 1;
424
+ `;
425
+ const StyledOrderByBadge = styled.div `
426
+ display: inline-flex;
427
+ align-items: center;
428
+ gap: 4px;
429
+ padding: 3px 8px;
430
+ background: white;
431
+ border: 1px solid #d1d9e6;
432
+ border-radius: 16px;
433
+ font-size: 0.82rem;
434
+ color: #333;
435
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
436
+
437
+ .badge-name {
438
+ max-width: 120px;
439
+ overflow: hidden;
440
+ text-overflow: ellipsis;
441
+ white-space: nowrap;
442
+
443
+ @media (max-width: 600px) {
444
+ max-width: 80px;
445
+ }
446
+ }
447
+ `;
448
+ const StyledOrderByBadgeMore = styled.div `
449
+ display: inline-flex;
450
+ align-items: center;
451
+ justify-content: center;
452
+ padding: 3px 10px;
453
+ background: linear-gradient(135deg, #4A96D2 0%, #2559A5 100%);
454
+ border: none;
455
+ border-radius: 16px;
456
+ font-size: 0.82rem;
457
+ font-weight: 600;
458
+ color: white;
459
+ cursor: pointer;
460
+ transition: all 0.2s ease;
461
+
462
+ &:hover {
463
+ transform: scale(1.05);
464
+ box-shadow: 0 2px 6px rgba(74, 150, 210, 0.4);
465
+ }
466
+ `;
467
+ const StyledOrderByEditButton = styled.div `
468
+ display: flex;
469
+ align-items: center;
470
+ justify-content: center;
471
+ width: 28px;
472
+ height: 28px;
473
+ border-radius: 4px;
474
+ color: #4A96D2;
475
+ cursor: pointer;
476
+ transition: all 0.2s ease;
477
+
478
+ &:hover {
479
+ background-color: rgba(74, 150, 210, 0.15);
480
+ }
481
+ `;
482
+ // =============================================================================
483
+ // STYLED COMPONENTS per i badge degli output (select) - colore verde/teal
484
+ // =============================================================================
485
+ const StyledSelectBadgesContainer = styled.div `
486
+ display: flex;
487
+ flex-wrap: wrap;
488
+ align-items: center;
489
+ gap: 8px;
490
+ padding: 6px 10px;
491
+ margin: 1px 0;
492
+ background: linear-gradient(135deg, rgba(46, 125, 50, 0.08) 0%, rgba(27, 94, 32, 0.08) 100%);
493
+ border-radius: 8px;
494
+ border: 1px solid rgba(46, 125, 50, 0.2);
495
+ `;
496
+ const StyledSelectLabel = styled.span `
497
+ font-size: 0.82rem;
498
+ font-weight: 600;
499
+ color: #2E7D32;
500
+ white-space: nowrap;
501
+ `;
502
+ const StyledSelectBadgesWrapper = styled.div `
503
+ display: flex;
504
+ flex-wrap: wrap;
505
+ gap: 6px;
506
+ align-items: center;
507
+ flex: 1;
508
+ `;
509
+ const StyledSelectBadge = styled.div `
510
+ display: inline-flex;
511
+ align-items: center;
512
+ gap: 4px;
513
+ padding: 3px 8px;
514
+ background: white;
515
+ border: 1px solid #c8e6c9;
516
+ border-radius: 16px;
517
+ font-size: 0.82rem;
518
+ color: #333;
519
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
520
+
521
+ .badge-name {
522
+ max-width: 120px;
523
+ overflow: hidden;
524
+ text-overflow: ellipsis;
525
+ white-space: nowrap;
526
+
527
+ @media (max-width: 600px) {
528
+ max-width: 80px;
529
+ }
530
+ }
531
+ `;
532
+ const StyledSelectBadgeMore = styled.div `
533
+ display: inline-flex;
534
+ align-items: center;
535
+ justify-content: center;
536
+ padding: 3px 10px;
537
+ background: linear-gradient(135deg, #43A047 0%, #2E7D32 100%);
538
+ border: none;
539
+ border-radius: 16px;
540
+ font-size: 0.82rem;
541
+ font-weight: 600;
542
+ color: white;
543
+ cursor: pointer;
544
+ transition: all 0.2s ease;
545
+
546
+ &:hover {
547
+ transform: scale(1.05);
548
+ box-shadow: 0 2px 6px rgba(46, 125, 50, 0.4);
549
+ }
550
+ `;
551
+ const StyledSelectEditButton = styled.div `
552
+ display: flex;
553
+ align-items: center;
554
+ justify-content: center;
555
+ width: 28px;
556
+ height: 28px;
557
+ border-radius: 4px;
558
+ color: #2E7D32;
559
+ cursor: pointer;
560
+ transition: all 0.2s ease;
561
+
562
+ &:hover {
563
+ background-color: rgba(46, 125, 50, 0.15);
564
+ }
565
+ `;
418
566
  export const StyledToppyTextContainer = styled.div `
419
567
  padding: 22px 8px;
420
568
  width: 100%;
@@ -433,11 +581,13 @@ export const StyledToppyText = styled.p `
433
581
  font-size: 1rem;
434
582
  user-select: none;
435
583
  -webkit-touch-callout: none;
436
- -webkit-user-select: none;
584
+ -webkit-user-select: none;
585
+ -moz-user-select: none;
586
+ -ms-user-select: none;
437
587
  margin: 0;
438
588
  display: -webkit-box;
439
589
  -webkit-box-orient: vertical;
440
- -webkit-line-clamp: 3; /* non è una proprietà standard ma è così diffusa e ben supportata che è considerata una "best practice pragmatica" */
590
+ -webkit-line-clamp: 3;
441
591
  overflow: hidden;
442
592
  text-overflow: ellipsis;
443
593
  white-space: normal;
@@ -635,7 +635,7 @@ handleNavigateToWGs, handleNavigateToDossiers, }) => {
635
635
  _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 && deviceType !== DeviceType.MOBILE, start: showSelector ? deviceType !== DeviceType.MOBILE ? ['30%', '70%'] : splitterSize : ['0%', '100%'], children: [showSelector ?
636
636
  _jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, disableAccordionIfSingleCategory: disableAccordionIfSingleCategory, selectedTID: selectedSearchResultTID, selectedSearchResult: selectedSearchResult, autoSelectFirst: !isMobile || currentSearchResults.length === 1, onSelectionChanged: onSearchResultSelectionChanged }) })
637
637
  :
638
- _jsx(_Fragment, {}), _jsx(TMLayoutItem, { children: _jsx(TMSearchResultGrid, { openInOffice: openInOffice, fromDTD: fromDTD, operationItems: operationItems, allUsers: allUsers, inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, showExportForm: showExportForm, onFocusedItemChanged: setFocusedItem, onDownloadDcmtsAsync: async (inputDcmts, downloadType, downloadMode, _y, confirmAttachments) => await downloadDcmtsAsync(inputDcmts, downloadType, downloadMode, 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 }) })] }), 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: () => {
638
+ _jsx(_Fragment, {}), _jsx(TMLayoutItem, { children: _jsx(TMSearchResultGrid, { openInOffice: openInOffice, fromDTD: fromDTD, operationItems: operationItems, allUsers: allUsers, inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, showExportForm: showExportForm, onFocusedItemChanged: setFocusedItem, 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 }) })] }), 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: () => {
639
639
  updateShowApprovePopup(true);
640
640
  }, onSignApprove: () => {
641
641
  handleSignApprove();
@@ -1124,8 +1124,7 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, i
1124
1124
  // Previene l'errore E1047 quando il filtro riferisce campi non più presenti nelle nuove colonne.
1125
1125
  const oldFields = columns.map(c => c.dataField);
1126
1126
  const newFields = cols.map(c => c.dataField);
1127
- const columnsChanged = oldFields.length !== newFields.length ||
1128
- oldFields.some((f, i) => f !== newFields[i]);
1127
+ const columnsChanged = oldFields.length !== newFields.length || oldFields.some((f, i) => f !== newFields[i]);
1129
1128
  if (columnsChanged) {
1130
1129
  const gridInstance = dataGridRef.current?.instance();
1131
1130
  if (gridInstance) {