@topconsultnpm/sdkui-react 6.21.0-dev4.9 → 6.21.0-dev5.10
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/TMTreeView.d.ts +16 -13
- package/lib/components/base/TMTreeView.js +230 -64
- package/lib/components/features/documents/TMDcmtIcon.d.ts +3 -1
- package/lib/components/features/documents/TMDcmtIcon.js +5 -32
- package/lib/components/features/documents/TMFileUploader.js +1 -1
- package/lib/components/features/documents/TMMasterDetailDcmts.js +165 -11
- package/lib/components/features/documents/TMMergeToPdfForm.js +6 -3
- package/lib/components/features/documents/TMRelationViewer.d.ts +15 -10
- package/lib/components/features/documents/TMRelationViewer.js +532 -179
- package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +4 -3
- package/lib/components/features/documents/copyAndMergeDcmtsShared.js +46 -23
- package/lib/components/features/documents/mergePdfUtils.js +21 -11
- package/lib/components/features/search/TMSearchResult.js +20 -5
- package/lib/components/viewers/TMTidViewer.js +14 -2
- package/lib/helper/SDKUI_Globals.d.ts +1 -0
- package/lib/helper/SDKUI_Globals.js +1 -0
- package/lib/helper/SDKUI_Localizator.d.ts +28 -0
- package/lib/helper/SDKUI_Localizator.js +280 -0
- package/lib/helper/TMIcons.d.ts +1 -0
- package/lib/helper/TMIcons.js +3 -0
- package/lib/helper/TMUtils.d.ts +33 -1
- package/lib/helper/TMUtils.js +104 -1
- package/lib/helper/helpers.d.ts +3 -0
- package/lib/helper/helpers.js +29 -1
- package/lib/hooks/useDocumentOperations.js +2 -2
- package/package.json +3 -4
|
@@ -11,25 +11,28 @@ export interface ITMTreeItem {
|
|
|
11
11
|
currentPage?: number;
|
|
12
12
|
totalItemsCount?: number;
|
|
13
13
|
}
|
|
14
|
-
interface ITMTreeViewProps
|
|
15
|
-
dataSource?:
|
|
16
|
-
focusedItem?:
|
|
17
|
-
selectedItems?:
|
|
14
|
+
interface ITMTreeViewProps {
|
|
15
|
+
dataSource?: ITMTreeItem[];
|
|
16
|
+
focusedItem?: ITMTreeItem | null;
|
|
17
|
+
selectedItems?: ITMTreeItem[];
|
|
18
18
|
allowMultipleSelection?: boolean;
|
|
19
|
-
calculateItemsForNode?: (node:
|
|
20
|
-
itemRender: (item:
|
|
21
|
-
onFocusedItemChanged?: (item:
|
|
22
|
-
onSelectionChanged?: (selectedItems:
|
|
23
|
-
onNodeUpdate?: (updatedNode:
|
|
24
|
-
onDataChanged?: (items:
|
|
25
|
-
shouldDelayFocusOnEvent?: (node:
|
|
26
|
-
onItemContextMenu?: (item:
|
|
19
|
+
calculateItemsForNode?: (node: ITMTreeItem) => Promise<ITMTreeItem[] | undefined>;
|
|
20
|
+
itemRender: (item: ITMTreeItem | null) => JSX.Element;
|
|
21
|
+
onFocusedItemChanged?: (item: ITMTreeItem | null) => void;
|
|
22
|
+
onSelectionChanged?: (selectedItems: ITMTreeItem[]) => void;
|
|
23
|
+
onNodeUpdate?: (updatedNode: ITMTreeItem) => void;
|
|
24
|
+
onDataChanged?: (items: ITMTreeItem[]) => void;
|
|
25
|
+
shouldDelayFocusOnEvent?: (node: ITMTreeItem, event: React.MouseEvent) => boolean;
|
|
26
|
+
onItemContextMenu?: (item: ITMTreeItem, e: React.MouseEvent) => void;
|
|
27
27
|
autoSelectChildren?: boolean;
|
|
28
28
|
itemsPerPage?: number;
|
|
29
29
|
showLoadMoreButton?: boolean;
|
|
30
|
+
enableVirtualization?: boolean;
|
|
30
31
|
}
|
|
31
|
-
declare const TMTreeView:
|
|
32
|
+
declare const TMTreeView: ({ dataSource, focusedItem, selectedItems, allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged, shouldDelayFocusOnEvent, onItemContextMenu, autoSelectChildren, itemsPerPage, showLoadMoreButton, enableVirtualization }: ITMTreeViewProps) => import("react/jsx-runtime").JSX.Element;
|
|
32
33
|
export default TMTreeView;
|
|
34
|
+
export declare const StyledTreeContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
|
|
35
|
+
export declare const StyledItemContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
|
|
33
36
|
export declare const StyledTreeNode: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$isSelected"> & {
|
|
34
37
|
$isSelected?: boolean;
|
|
35
38
|
}, never> & Partial<Pick<import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$isSelected"> & {
|
|
@@ -1,9 +1,147 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useRef, memo } from 'react';
|
|
3
|
+
import { List } from 'react-window';
|
|
3
4
|
import styled from 'styled-components';
|
|
4
5
|
import { IconArrowLeft, IconArrowRight, IconChevronDown, IconChevronRight, SDKUI_Localizator } from '../../helper';
|
|
5
6
|
import TMButton from './TMButton';
|
|
6
|
-
|
|
7
|
+
// Componente riga virtualizzata memoizzato
|
|
8
|
+
const VirtualRowComponent = memo(({ ariaAttributes, index, style, flattenedItems, focusedItemKey, selectedItemKeys, allowMultipleSelection, hasVisibleItems, handleNodeToggle, handleNodeClick, handleCheckboxChange, hasPartialChildSelection, itemRender, onItemContextMenu }) => {
|
|
9
|
+
const item = flattenedItems[index];
|
|
10
|
+
if (!item)
|
|
11
|
+
return null;
|
|
12
|
+
const { node, depth } = item;
|
|
13
|
+
const isSelected = node.key === focusedItemKey;
|
|
14
|
+
return (_jsx("div", { ...ariaAttributes, "data-node-key": node.key, style: {
|
|
15
|
+
...style,
|
|
16
|
+
paddingLeft: depth * 20,
|
|
17
|
+
display: 'flex',
|
|
18
|
+
alignItems: 'center',
|
|
19
|
+
width: 'fit-content',
|
|
20
|
+
minWidth: '100%',
|
|
21
|
+
paddingRight: 10,
|
|
22
|
+
boxSizing: 'border-box'
|
|
23
|
+
}, children: _jsxs(StyledTreeNode, { "$isSelected": isSelected, children: [_jsx("div", { style: {
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
minHeight: '18px',
|
|
28
|
+
minWidth: '18px',
|
|
29
|
+
maxHeight: '18px',
|
|
30
|
+
maxWidth: '18px',
|
|
31
|
+
flexShrink: 0
|
|
32
|
+
}, onClick: (e) => { handleNodeToggle(node.key, e.ctrlKey); }, children: hasVisibleItems(node)
|
|
33
|
+
? node.expanded
|
|
34
|
+
? _jsx(IconChevronDown, { cursor: 'pointer', fontSize: 14 })
|
|
35
|
+
: _jsx(IconChevronRight, { cursor: 'pointer', fontSize: 14 })
|
|
36
|
+
: _jsx("div", { style: { height: '18px', width: '18px' } }) }), allowMultipleSelection && (_jsx("input", { type: "checkbox", checked: selectedItemKeys.has(node.key), onChange: (e) => handleCheckboxChange(node, e.target.checked), onClick: (e) => e.stopPropagation(), style: { flexShrink: 0 }, ref: input => {
|
|
37
|
+
if (input) {
|
|
38
|
+
// Imposta lo stato visuale "trattino" sulla checkbox quando il container
|
|
39
|
+
// ha alcuni figli selezionati ma non tutti. Necessario usare ref perché
|
|
40
|
+
// "indeterminate" è una proprietà DOM, non un attributo HTML.
|
|
41
|
+
input.indeterminate = hasPartialChildSelection(node);
|
|
42
|
+
}
|
|
43
|
+
} })), _jsx(StyledItemContent, { onClick: (e) => { handleNodeClick(node, e); }, onContextMenu: (e) => {
|
|
44
|
+
if (onItemContextMenu) {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
onItemContextMenu(node, e);
|
|
47
|
+
}
|
|
48
|
+
}, children: itemRender(node) })] }) }));
|
|
49
|
+
}, (prevProps, nextProps) => {
|
|
50
|
+
// Custom comparison: re-render solo se i dati rilevanti per questa riga cambiano
|
|
51
|
+
const prevItem = prevProps.flattenedItems[prevProps.index];
|
|
52
|
+
const nextItem = nextProps.flattenedItems[nextProps.index];
|
|
53
|
+
if (!prevItem || !nextItem)
|
|
54
|
+
return prevItem === nextItem;
|
|
55
|
+
const prevNode = prevItem.node;
|
|
56
|
+
const nextNode = nextItem.node;
|
|
57
|
+
// Controlla se questa riga specifica è cambiata
|
|
58
|
+
return (prevNode.key === nextNode.key &&
|
|
59
|
+
prevNode.expanded === nextNode.expanded &&
|
|
60
|
+
prevItem.depth === nextItem.depth &&
|
|
61
|
+
(prevNode.key === prevProps.focusedItemKey) === (nextNode.key === nextProps.focusedItemKey) &&
|
|
62
|
+
prevProps.selectedItemKeys.has(prevNode.key) === nextProps.selectedItemKeys.has(nextNode.key) &&
|
|
63
|
+
prevProps.allowMultipleSelection === nextProps.allowMultipleSelection);
|
|
64
|
+
});
|
|
65
|
+
const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged, shouldDelayFocusOnEvent, onItemContextMenu, autoSelectChildren = true, itemsPerPage = 100, showLoadMoreButton = true, enableVirtualization = false }) => {
|
|
66
|
+
// Altezza fissa per ogni riga nella virtualizzazione
|
|
67
|
+
const VIRTUAL_ROW_HEIGHT = 26;
|
|
68
|
+
const listRef = useRef(null);
|
|
69
|
+
const containerRef = useRef(null);
|
|
70
|
+
const [containerSize, setContainerSize] = React.useState({ width: 0, height: 0 });
|
|
71
|
+
// Ref per selectedItems - permette alle callback memoizzate di accedere sempre al valore più recente
|
|
72
|
+
const selectedItemsRef = useRef(selectedItems);
|
|
73
|
+
selectedItemsRef.current = selectedItems;
|
|
74
|
+
// Ref per handleCheckboxChange - permette all'useEffect di accedere alla funzione prima che sia definita
|
|
75
|
+
const handleCheckboxChangeRef = useRef(() => { });
|
|
76
|
+
// Filtra gli items da mostrare in base alla paginazione (definito prima per essere usato da flattenTreeWithDepth)
|
|
77
|
+
const getVisibleItems = useCallback((node) => {
|
|
78
|
+
if (!node.items)
|
|
79
|
+
return [];
|
|
80
|
+
const totalItems = node.items.length;
|
|
81
|
+
// Se non c'è paginazione attiva o gli items sono pochi, mostra tutti
|
|
82
|
+
if (totalItems <= itemsPerPage || !showLoadMoreButton) {
|
|
83
|
+
return node.items;
|
|
84
|
+
}
|
|
85
|
+
// Altrimenti mostra solo gli items della pagina corrente
|
|
86
|
+
const currentPage = node.currentPage ?? 0;
|
|
87
|
+
const startIndex = currentPage * itemsPerPage;
|
|
88
|
+
const endIndex = startIndex + itemsPerPage;
|
|
89
|
+
return node.items.slice(startIndex, endIndex);
|
|
90
|
+
}, [itemsPerPage, showLoadMoreButton]);
|
|
91
|
+
// Misura le dimensioni del container per react-window
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!enableVirtualization || !containerRef.current)
|
|
94
|
+
return;
|
|
95
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
const { width, height } = entry.contentRect;
|
|
98
|
+
setContainerSize({ width, height });
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
resizeObserver.observe(containerRef.current);
|
|
102
|
+
return () => resizeObserver.disconnect();
|
|
103
|
+
}, [enableVirtualization]);
|
|
104
|
+
// Flatten tree con informazioni di profondità per la virtualizzazione
|
|
105
|
+
const flattenTreeWithDepth = useCallback((nodes, depth = 0, parentKey) => {
|
|
106
|
+
let flatList = [];
|
|
107
|
+
nodes.forEach(node => {
|
|
108
|
+
if (!node.hidden) {
|
|
109
|
+
flatList.push({ node, depth, parentKey });
|
|
110
|
+
if (node.expanded && node.items) {
|
|
111
|
+
const visibleItems = getVisibleItems(node);
|
|
112
|
+
flatList = flatList.concat(flattenTreeWithDepth(visibleItems, depth + 1, node.key));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return flatList;
|
|
117
|
+
}, [getVisibleItems]);
|
|
118
|
+
// Lista piatta per la virtualizzazione
|
|
119
|
+
const flattenedItems = useMemo(() => {
|
|
120
|
+
if (!enableVirtualization)
|
|
121
|
+
return [];
|
|
122
|
+
return flattenTreeWithDepth(dataSource);
|
|
123
|
+
}, [enableVirtualization, dataSource, flattenTreeWithDepth]);
|
|
124
|
+
// Scroll verso l'elemento focalizzato quando cambia (navigazione con frecce)
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (!focusedItem?.key)
|
|
127
|
+
return;
|
|
128
|
+
if (enableVirtualization) {
|
|
129
|
+
// Lista virtualizzata: usa scrollToRow per garantire che l'elemento sia visibile
|
|
130
|
+
const index = flattenedItems.findIndex(item => item.node.key === focusedItem.key);
|
|
131
|
+
if (index >= 0 && listRef.current) {
|
|
132
|
+
listRef.current.scrollToRow({ index, align: 'smart' });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// Lista standard: usa scrollIntoView
|
|
137
|
+
if (containerRef.current) {
|
|
138
|
+
const element = containerRef.current.querySelector(`[data-node-key="${focusedItem.key}"]`);
|
|
139
|
+
if (element) {
|
|
140
|
+
element.scrollIntoView({ block: 'nearest', inline: 'nearest' });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}, [focusedItem?.key, enableVirtualization, flattenedItems]);
|
|
7
145
|
useEffect(() => {
|
|
8
146
|
const handleKeyDown = (event) => {
|
|
9
147
|
if (!focusedItem)
|
|
@@ -33,9 +171,14 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
33
171
|
handled = true;
|
|
34
172
|
}
|
|
35
173
|
break;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
174
|
+
case ' ':
|
|
175
|
+
case 'Spacebar': // IE/Edge legacy
|
|
176
|
+
if (allowMultipleSelection) {
|
|
177
|
+
const isCurrentlySelected = selectedItemsRef.current.some(item => item.key === focusedItem.key);
|
|
178
|
+
handleCheckboxChangeRef.current(focusedItem, !isCurrentlySelected);
|
|
179
|
+
handled = true;
|
|
180
|
+
}
|
|
181
|
+
break;
|
|
39
182
|
// case '*':
|
|
40
183
|
// handleExpandAllNodes();
|
|
41
184
|
// break;
|
|
@@ -57,7 +200,7 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
57
200
|
return () => {
|
|
58
201
|
window.removeEventListener('keydown', handleKeyDown, true);
|
|
59
202
|
};
|
|
60
|
-
}, [focusedItem, dataSource, onFocusedItemChanged]);
|
|
203
|
+
}, [focusedItem, dataSource, onFocusedItemChanged, allowMultipleSelection]);
|
|
61
204
|
const findNextItem = (nodes, currentItem) => {
|
|
62
205
|
const flatList = flattenTree(nodes);
|
|
63
206
|
const currentIndex = flatList.findIndex(item => item.key === currentItem.key);
|
|
@@ -162,7 +305,9 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
162
305
|
onFocusedItemChanged?.(node); // Chiama onFocusedItemChanged immediatamente
|
|
163
306
|
}
|
|
164
307
|
}, [onFocusedItemChanged, calculateItemsForNode, onNodeUpdate]);
|
|
165
|
-
const handleCheckboxChange = (node, checked) => {
|
|
308
|
+
const handleCheckboxChange = useCallback((node, checked) => {
|
|
309
|
+
// Usa la ref per accedere sempre al valore più recente di selectedItems
|
|
310
|
+
const currentSelectedItems = selectedItemsRef.current;
|
|
166
311
|
// Funzione helper per trovare il parent di un nodo e verificare se tutti i suoi figli sono selezionati
|
|
167
312
|
const findAndCheckParents = (items, targetNode, currentSelection) => {
|
|
168
313
|
const parentsToAdd = [];
|
|
@@ -199,11 +344,14 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
199
344
|
if (node.isContainer && autoSelectChildren) {
|
|
200
345
|
// Quando selezioni un container, aggiungi il container stesso + tutti i figli (se autoSelectChildren è true)
|
|
201
346
|
const allChildren = flattenTree(node.items || []);
|
|
202
|
-
|
|
347
|
+
// Rimuovi eventuali duplicati: filtra gli elementi già presenti nella selezione
|
|
348
|
+
const childrenKeys = new Set(allChildren.map(child => child.key));
|
|
349
|
+
const filteredSelectedItems = currentSelectedItems.filter(item => !childrenKeys.has(item.key) && item.key !== node.key);
|
|
350
|
+
newSelectedItems = [...filteredSelectedItems, node, ...allChildren];
|
|
203
351
|
}
|
|
204
|
-
else if (!
|
|
352
|
+
else if (!currentSelectedItems.some(item => item.key === node.key)) {
|
|
205
353
|
// Quando selezioni un figlio o un container con autoSelectChildren=false, aggiungi solo il nodo
|
|
206
|
-
newSelectedItems = [...
|
|
354
|
+
newSelectedItems = [...currentSelectedItems, node];
|
|
207
355
|
// Verifica se selezionando questo figlio sono ora selezionati tutti i figli del parent (solo se autoSelectChildren è true)
|
|
208
356
|
if (autoSelectChildren) {
|
|
209
357
|
const parentsToAdd = findAndCheckParents(dataSource, node, newSelectedItems);
|
|
@@ -211,17 +359,17 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
211
359
|
}
|
|
212
360
|
}
|
|
213
361
|
else {
|
|
214
|
-
newSelectedItems =
|
|
362
|
+
newSelectedItems = currentSelectedItems;
|
|
215
363
|
}
|
|
216
364
|
}
|
|
217
365
|
else if (node.isContainer && autoSelectChildren) {
|
|
218
366
|
// Quando deselezioni un container, rimuovi il container stesso + tutti i figli (solo se autoSelectChildren è true)
|
|
219
367
|
const childKeys = flattenTree(node.items || []).map(item => item.key);
|
|
220
|
-
newSelectedItems =
|
|
368
|
+
newSelectedItems = currentSelectedItems.filter(item => item.key !== node.key && !childKeys.includes(item.key));
|
|
221
369
|
}
|
|
222
370
|
else {
|
|
223
371
|
// Quando deselezioni un figlio o un container con autoSelectChildren=false, rimuovi solo il nodo
|
|
224
|
-
newSelectedItems =
|
|
372
|
+
newSelectedItems = currentSelectedItems.filter(item => item.key !== node.key);
|
|
225
373
|
// Se il figlio apparteneva a un parent che era selezionato, rimuovi anche il parent (solo se autoSelectChildren è true)
|
|
226
374
|
if (autoSelectChildren && !node.isContainer) {
|
|
227
375
|
const removeParentContainers = (items) => {
|
|
@@ -243,28 +391,10 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
243
391
|
}
|
|
244
392
|
}
|
|
245
393
|
onSelectionChanged?.(newSelectedItems);
|
|
246
|
-
};
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
// ...node,
|
|
251
|
-
// expanded: true,
|
|
252
|
-
// items: node.items ? expandAll(node.items as T[]) : node.items
|
|
253
|
-
// }));
|
|
254
|
-
// };
|
|
255
|
-
// setTreeData(prevData => expandAll(prevData));
|
|
256
|
-
// };
|
|
257
|
-
// const handleCollapseAllNodes = () => {
|
|
258
|
-
// const collapseAll = (nodes: T[]): T[] => {
|
|
259
|
-
// return nodes.map(node => ({
|
|
260
|
-
// ...node,
|
|
261
|
-
// expanded: false,
|
|
262
|
-
// items: node.items ? collapseAll(node.items as T[]) : node.items
|
|
263
|
-
// }));
|
|
264
|
-
// };
|
|
265
|
-
// setTreeData(prevData => collapseAll(prevData));
|
|
266
|
-
// };
|
|
267
|
-
const isIndeterminate = (node) => {
|
|
394
|
+
}, [autoSelectChildren, dataSource, onSelectionChanged]);
|
|
395
|
+
// Aggiorna la ref con l'ultima versione di handleCheckboxChange
|
|
396
|
+
handleCheckboxChangeRef.current = handleCheckboxChange;
|
|
397
|
+
const hasPartialChildSelection = (node) => {
|
|
268
398
|
// Lo stato indeterminate ha senso solo quando autoSelectChildren è true
|
|
269
399
|
if (!autoSelectChildren)
|
|
270
400
|
return false;
|
|
@@ -275,13 +405,6 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
275
405
|
const selectedCount = childKeys.filter(key => selectedChildKeys.includes(key)).length;
|
|
276
406
|
return selectedCount > 0 && selectedCount < childKeys.length;
|
|
277
407
|
};
|
|
278
|
-
const isFullySelected = (node) => {
|
|
279
|
-
if (!node.isContainer || !node.items)
|
|
280
|
-
return false;
|
|
281
|
-
const childKeys = flattenTree(node.items).map(item => item.key);
|
|
282
|
-
const selectedChildKeys = selectedItems.map(item => item.key);
|
|
283
|
-
return childKeys.every(key => selectedChildKeys.includes(key));
|
|
284
|
-
};
|
|
285
408
|
const hasVisibleItems = (node) => {
|
|
286
409
|
// If node has explicit isExpandible value, use that
|
|
287
410
|
if (node.isExpandible !== undefined) {
|
|
@@ -312,21 +435,6 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
312
435
|
const updatedData = updateNodePage(dataSource);
|
|
313
436
|
onDataChanged?.(updatedData);
|
|
314
437
|
}, [dataSource, onDataChanged, onNodeUpdate]);
|
|
315
|
-
// Filtra gli items da mostrare in base alla paginazione
|
|
316
|
-
const getVisibleItems = useCallback((node) => {
|
|
317
|
-
if (!node.items)
|
|
318
|
-
return [];
|
|
319
|
-
const totalItems = node.items.length;
|
|
320
|
-
// Se non c'è paginazione attiva o gli items sono pochi, mostra tutti
|
|
321
|
-
if (totalItems <= itemsPerPage || !showLoadMoreButton) {
|
|
322
|
-
return node.items;
|
|
323
|
-
}
|
|
324
|
-
// Altrimenti mostra solo gli items della pagina corrente
|
|
325
|
-
const currentPage = node.currentPage ?? 0;
|
|
326
|
-
const startIndex = currentPage * itemsPerPage;
|
|
327
|
-
const endIndex = startIndex + itemsPerPage;
|
|
328
|
-
return node.items.slice(startIndex, endIndex);
|
|
329
|
-
}, [itemsPerPage, showLoadMoreButton]);
|
|
330
438
|
// Verifica se c'è bisogno del paginatore
|
|
331
439
|
const needsPagination = useCallback((node) => {
|
|
332
440
|
if (!showLoadMoreButton || !node.items)
|
|
@@ -340,7 +448,7 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
340
448
|
return Math.ceil(node.items.length / itemsPerPage);
|
|
341
449
|
}, [itemsPerPage]);
|
|
342
450
|
const renderTree = useCallback((nodes) => {
|
|
343
|
-
return nodes.map(node => !node.hidden && (_jsxs("div", { style: { width: '100%', margin: 0, padding: 0 }, children: [_jsxs(StyledTreeNode, { "$isSelected": node.key === focusedItem?.key, children: [_jsx("div", { style: {
|
|
451
|
+
return nodes.map(node => !node.hidden && (_jsxs("div", { style: { width: 'fit-content', minWidth: '100%', margin: 0, padding: 0 }, children: [_jsxs(StyledTreeNode, { "$isSelected": node.key === focusedItem?.key, "data-node-key": node.key, children: [_jsx("div", { style: {
|
|
344
452
|
display: 'flex',
|
|
345
453
|
alignItems: 'center',
|
|
346
454
|
justifyContent: 'center',
|
|
@@ -355,28 +463,86 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
355
463
|
: _jsx(IconChevronRight, { cursor: 'pointer', fontSize: 14 })
|
|
356
464
|
: _jsx("div", { style: { height: '18px', width: '18px' } }) }), allowMultipleSelection && (_jsx("input", { type: "checkbox", checked: selectedItems.some(item => item.key === node.key), onChange: (e) => handleCheckboxChange(node, e.target.checked), onClick: (e) => e.stopPropagation(), style: { flexShrink: 0 }, ref: input => {
|
|
357
465
|
if (input) {
|
|
358
|
-
|
|
466
|
+
// Imposta lo stato visuale "trattino" (➖) sulla checkbox quando il container
|
|
467
|
+
// ha alcuni figli selezionati ma non tutti. Necessario usare ref perché
|
|
468
|
+
// "indeterminate" è una proprietà DOM, non un attributo HTML.
|
|
469
|
+
input.indeterminate = hasPartialChildSelection(node);
|
|
359
470
|
}
|
|
360
|
-
} })), _jsx(
|
|
471
|
+
} })), _jsx(StyledItemContent, { onClick: (e) => { handleNodeClick(node, e); }, onContextMenu: (e) => {
|
|
361
472
|
if (onItemContextMenu) {
|
|
362
473
|
e.preventDefault();
|
|
363
474
|
onItemContextMenu(node, e);
|
|
364
475
|
}
|
|
365
|
-
}, children: itemRender(node) })] }), node.expanded && node.items && (_jsxs("div", { style: { paddingLeft: 20, width: '100%' }, children: [renderTree(getVisibleItems(node)), needsPagination(node) && (_jsxs(StyledStickyPaginator, { children: [_jsx(TMButton, { btnStyle: 'icon', onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) - 1), showTooltip: false, caption: "\u25C4", icon: _jsx(IconArrowLeft, { color: 'white' }), disabled: (node.currentPage ?? 0) <= 0 }), _jsx("span", { style: { fontSize: '11px', whiteSpace: 'nowrap', fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', minWidth: 0, color: 'white' }, children: SDKUI_Localizator.PaginationInfo.replaceParams((node.currentPage ?? 0) + 1, getTotalPages(node), node.items?.length ?? 0) }), _jsx(TMButton, { btnStyle: 'icon', onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) + 1), showTooltip: false, caption: "\u25BA", icon: _jsx(IconArrowRight, { color: 'white' }), disabled: (node.currentPage ?? 0) >= getTotalPages(node) - 1 })] }))] }))] }, node.key)));
|
|
476
|
+
}, children: itemRender(node) })] }), node.expanded && node.items && (_jsxs("div", { style: { paddingLeft: 20, width: 'fit-content', minWidth: '100%' }, children: [renderTree(getVisibleItems(node)), needsPagination(node) && (_jsxs(StyledStickyPaginator, { children: [_jsx(TMButton, { btnStyle: 'icon', onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) - 1), showTooltip: false, caption: "\u25C4", icon: _jsx(IconArrowLeft, { color: 'white' }), disabled: (node.currentPage ?? 0) <= 0 }), _jsx("span", { style: { fontSize: '11px', whiteSpace: 'nowrap', fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', minWidth: 0, color: 'white' }, children: SDKUI_Localizator.PaginationInfo.replaceParams((node.currentPage ?? 0) + 1, getTotalPages(node), node.items?.length ?? 0) }), _jsx(TMButton, { btnStyle: 'icon', onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) + 1), showTooltip: false, caption: "\u25BA", icon: _jsx(IconArrowRight, { color: 'white' }), disabled: (node.currentPage ?? 0) >= getTotalPages(node) - 1 })] }))] }))] }, node.key)));
|
|
366
477
|
}, [handleNodeClick, handleNodeToggle, handleCheckboxChange, focusedItem, selectedItems, allowMultipleSelection, getVisibleItems, needsPagination, handlePageChange, getTotalPages, onItemContextMenu]);
|
|
367
|
-
|
|
478
|
+
// Calcola selectedItemKeys ad ogni render per garantire sincronizzazione con selectedItems
|
|
479
|
+
const selectedItemKeys = new Set(selectedItems.map(s => s.key));
|
|
480
|
+
// Memoizza rowPropsData per evitare re-render della List
|
|
481
|
+
const rowPropsData = useMemo(() => ({
|
|
482
|
+
flattenedItems,
|
|
483
|
+
focusedItemKey: focusedItem?.key,
|
|
484
|
+
selectedItemKeys,
|
|
485
|
+
allowMultipleSelection,
|
|
486
|
+
hasVisibleItems,
|
|
487
|
+
handleNodeToggle,
|
|
488
|
+
handleNodeClick,
|
|
489
|
+
handleCheckboxChange,
|
|
490
|
+
hasPartialChildSelection: hasPartialChildSelection,
|
|
491
|
+
itemRender,
|
|
492
|
+
onItemContextMenu
|
|
493
|
+
}), [
|
|
494
|
+
flattenedItems,
|
|
495
|
+
focusedItem?.key,
|
|
496
|
+
selectedItemKeys,
|
|
497
|
+
allowMultipleSelection,
|
|
498
|
+
hasVisibleItems,
|
|
499
|
+
handleNodeToggle,
|
|
500
|
+
handleNodeClick,
|
|
501
|
+
handleCheckboxChange,
|
|
502
|
+
hasPartialChildSelection,
|
|
503
|
+
itemRender,
|
|
504
|
+
onItemContextMenu
|
|
505
|
+
]);
|
|
506
|
+
// Render virtualizzato con react-window v2
|
|
507
|
+
if (enableVirtualization) {
|
|
508
|
+
return (_jsx(StyledTreeContainer, { ref: containerRef, children: containerSize.height > 0 && (_jsx(List, { listRef: listRef, rowCount: flattenedItems.length, rowHeight: VIRTUAL_ROW_HEIGHT, rowComponent: VirtualRowComponent, rowProps: rowPropsData, style: { height: containerSize.height, width: '100%' }, overscanCount: 5 })) }));
|
|
509
|
+
}
|
|
510
|
+
// Render standard (non virtualizzato) con scrolling orizzontale
|
|
511
|
+
return (_jsx(StyledTreeContainer, { ref: containerRef, children: _jsx("div", { children: renderTree(dataSource) }) }));
|
|
368
512
|
};
|
|
369
513
|
export default TMTreeView;
|
|
514
|
+
// Container principale con scrolling orizzontale
|
|
515
|
+
export const StyledTreeContainer = styled.div `
|
|
516
|
+
height: 100%;
|
|
517
|
+
width: 100%;
|
|
518
|
+
overflow-y: auto;
|
|
519
|
+
overflow-x: auto;
|
|
520
|
+
padding: 0px 0px 2px 2px;
|
|
521
|
+
|
|
522
|
+
/* Contenitore interno che si espande per accomodare nodi annidati */
|
|
523
|
+
& > div {
|
|
524
|
+
width: fit-content;
|
|
525
|
+
min-width: 100%;
|
|
526
|
+
}
|
|
527
|
+
`;
|
|
528
|
+
// Contenuto dell'item - niente ellipsis per permettere scrolling orizzontale del container
|
|
529
|
+
export const StyledItemContent = styled.div `
|
|
530
|
+
display: flex;
|
|
531
|
+
align-items: center;
|
|
532
|
+
flex-shrink: 0;
|
|
533
|
+
white-space: nowrap;
|
|
534
|
+
`;
|
|
370
535
|
export const StyledTreeNode = styled.div `
|
|
371
536
|
display: flex;
|
|
372
537
|
flex-direction: row;
|
|
373
|
-
width:
|
|
374
|
-
min-width:
|
|
538
|
+
width: fit-content;
|
|
539
|
+
min-width: 100%;
|
|
375
540
|
min-height: 22px;
|
|
376
541
|
max-height: 30px;
|
|
377
542
|
gap: 5px;
|
|
378
543
|
align-items: center;
|
|
379
544
|
padding: 0;
|
|
545
|
+
padding-right: 10px; /* Spazio extra a destra per evitare che il testo tocchi il bordo */
|
|
380
546
|
margin: 0;
|
|
381
547
|
background: ${(props) => props.$isSelected ? 'oklch(from var(--dx-color-primary) l c h / .2) !important' : 'transparent'};
|
|
382
548
|
|
|
@@ -13,6 +13,8 @@ interface ITMDcmtIconProps {
|
|
|
13
13
|
tooltipContent?: JSX.Element | string;
|
|
14
14
|
openInOffice?: (selectedDcmtsOrFocused: Array<DcmtInfo>) => Promise<void>;
|
|
15
15
|
onDownloadDcmtsAsync?: (inputDcmts: DcmtInfo[] | undefined, downloadType: DownloadTypes, downloadMode: DownloadModes, onFileDownloaded?: (dcmtFile: File | undefined) => void, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>) => Promise<void>;
|
|
16
|
+
/** Se true, renderizza il wait panel nel body tramite Portal (centrato a schermo intero) */
|
|
17
|
+
usePortal?: boolean;
|
|
16
18
|
}
|
|
17
|
-
declare const TMDcmtIcon: ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode, tooltipContent, openInOffice, onDownloadDcmtsAsync }: ITMDcmtIconProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
declare const TMDcmtIcon: ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode, tooltipContent, openInOffice, onDownloadDcmtsAsync, usePortal }: ITMDcmtIconProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
20
|
export default TMDcmtIcon;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useMemo } from 'react';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
3
4
|
import styled from 'styled-components';
|
|
4
5
|
import { getFileIcon } from '../../../helper';
|
|
5
6
|
import TMTooltip from '../../base/TMTooltip';
|
|
@@ -15,7 +16,7 @@ const StyledCellRenderDcmtIcon = styled.div `
|
|
|
15
16
|
overflow: visible;
|
|
16
17
|
position: relative;
|
|
17
18
|
`;
|
|
18
|
-
const TMDcmtIcon = ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode = "none", tooltipContent, openInOffice, onDownloadDcmtsAsync }) => {
|
|
19
|
+
const TMDcmtIcon = ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode = "none", tooltipContent, openInOffice, onDownloadDcmtsAsync, usePortal = false }) => {
|
|
19
20
|
const { downloadDcmtsAsync, showWaitPanel, waitPanelTitle, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, abortController } = useDcmtOperations();
|
|
20
21
|
const deviceType = useDeviceType();
|
|
21
22
|
let isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
|
|
@@ -56,43 +57,15 @@ const TMDcmtIcon = ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isS
|
|
|
56
57
|
}, ...(deviceType === DeviceType.MOBILE
|
|
57
58
|
? { onClick: handleDownloadAction } // Su mobile, un singolo click sull'icona avvia il download
|
|
58
59
|
: { onDoubleClick: handleDownloadAction } // Su desktop, un doppio click sull'icona avvia il download
|
|
59
|
-
), children: [icon, isLexProt == 1 && _jsx("div", { style: { position: 'absolute', left: '-7px', top: isShared ? undefined : '2px' }, children: _jsx(TMTooltip, { content: "Protezione LEX", children: _jsx(IconLexProtLock, { color: 'blue', fontSize: 13 }) }) }), isShared == 1 && _jsx("div", { style: { position: 'absolute', top: '-7px', left: '-5px' }, children: _jsx(TMTooltip, { content: "Documento condiviso", children: _jsx(IconShared, { fontSize: 16 }) }) }), isSigned == 1 && _jsx("div", { style: { position: 'absolute', bottom: '-4px', right: '-7px' }, children: _jsx(TMTooltip, { content: "Documento firmato", children: _jsx(IconSignature, { fontSize: 28 }) }) }), showWaitPanel &&
|
|
60
|
-
_jsx(TMWaitPanel, { title: waitPanelTitle, showSecondary: showSecondary, textSecondary: waitPanelTextSecondary, valueSecondary: waitPanelValueSecondary, maxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); } })] }));
|
|
60
|
+
), children: [icon, isLexProt == 1 && _jsx("div", { style: { position: 'absolute', left: '-7px', top: isShared ? undefined : '2px' }, children: _jsx(TMTooltip, { content: "Protezione LEX", children: _jsx(IconLexProtLock, { color: 'blue', fontSize: 13 }) }) }), isShared == 1 && _jsx("div", { style: { position: 'absolute', top: '-7px', left: '-5px' }, children: _jsx(TMTooltip, { content: "Documento condiviso", children: _jsx(IconShared, { fontSize: 16 }) }) }), isSigned == 1 && _jsx("div", { style: { position: 'absolute', bottom: '-4px', right: '-7px' }, children: _jsx(TMTooltip, { content: "Documento firmato", children: _jsx(IconSignature, { fontSize: 28 }) }) }), showWaitPanel && (usePortal ? createPortal(_jsx(TMWaitPanel, { title: waitPanelTitle, showSecondary: showSecondary, textSecondary: waitPanelTextSecondary, valueSecondary: waitPanelValueSecondary, maxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); }, useHighZIndex: true }), document.body) : (_jsx(TMWaitPanel, { title: waitPanelTitle, showSecondary: showSecondary, textSecondary: waitPanelTextSecondary, valueSecondary: waitPanelValueSecondary, maxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); } })))] }));
|
|
61
61
|
};
|
|
62
62
|
export default TMDcmtIcon;
|
|
63
63
|
function IconLexProtLock(props) {
|
|
64
|
-
return (_jsxs("svg", { viewBox: "0 0 512 512", height: "1em", width: "1em", ...props, children: [_jsx("path", { fill: "#455A64", d: "M256,0c-76.544,0.094-138.573,62.122-138.667,138.667V224c0,5.891,4.776,10.667,10.667,10.667h42.667\r\n c5.891,0,10.667-4.776,10.667-10.667v-85.333C181.333,97.429,214.763,64,256,64s74.667,33.429,74.667,74.667V224\r\n c0,5.891,4.776,10.667,10.667,10.667H384c5.891,0,10.667-4.776,10.667-10.667v-85.333C394.573,62.122,332.544,0.094,256,0z" }), _jsx("path", { fill: "#FFC107", d: "M128,213.333h256c29.455,0,53.333,23.878,53.333,53.333v192C437.333,488.122,413.455,512,384,512H128\r\n c-29.455,0-53.333-23.878-53.333-53.333v-192C74.667,237.211,98.545,213.333,128,213.333z" }), _jsx("path", { fill: "#455A64", d: "M309.333,330.667c0.124-29.455-23.653-53.434-53.108-53.558\r\n c-29.455-0.124-53.434,23.653-53.558,53.108c-0.086,20.36,11.427,38.992,29.674,48.023l-8.235,57.6\r\n c-0.825,5.833,3.235,11.23,9.068,12.055c0.494,0.07,0.993,0.105,1.492,0.105h42.667c5.891,0.06,10.715-4.667,10.774-10.558\r\n c0.005-0.543-0.03-1.086-0.108-1.623l-8.235-57.6C297.788,369.199,309.216,350.82,309.333,330.667z" }), _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " })] })
|
|
65
|
-
// <svg
|
|
66
|
-
// viewBox="0 0 24 24"
|
|
67
|
-
// fill="currentColor"
|
|
68
|
-
// height="1em"
|
|
69
|
-
// width="1em"
|
|
70
|
-
// {...props}
|
|
71
|
-
// >
|
|
72
|
-
// <path d="M12 2C9.243 2 7 4.243 7 7v3H6a2 2 0 00-2 2v8a2 2 0 002 2h12a2 2 0 002-2v-8a2 2 0 00-2-2h-1V7c0-2.757-2.243-5-5-5zM9 7c0-1.654 1.346-3 3-3s3 1.346 3 3v3H9V7zm4 10.723V20h-2v-2.277a1.993 1.993 0 01.567-3.677A2.001 2.001 0 0114 16a1.99 1.99 0 01-1 1.723z" />
|
|
73
|
-
// </svg>
|
|
74
|
-
);
|
|
64
|
+
return (_jsxs("svg", { viewBox: "0 0 512 512", height: "1em", width: "1em", ...props, children: [_jsx("path", { fill: "#455A64", d: "M256,0c-76.544,0.094-138.573,62.122-138.667,138.667V224c0,5.891,4.776,10.667,10.667,10.667h42.667\r\n c5.891,0,10.667-4.776,10.667-10.667v-85.333C181.333,97.429,214.763,64,256,64s74.667,33.429,74.667,74.667V224\r\n c0,5.891,4.776,10.667,10.667,10.667H384c5.891,0,10.667-4.776,10.667-10.667v-85.333C394.573,62.122,332.544,0.094,256,0z" }), _jsx("path", { fill: "#FFC107", d: "M128,213.333h256c29.455,0,53.333,23.878,53.333,53.333v192C437.333,488.122,413.455,512,384,512H128\r\n c-29.455,0-53.333-23.878-53.333-53.333v-192C74.667,237.211,98.545,213.333,128,213.333z" }), _jsx("path", { fill: "#455A64", d: "M309.333,330.667c0.124-29.455-23.653-53.434-53.108-53.558\r\n c-29.455-0.124-53.434,23.653-53.558,53.108c-0.086,20.36,11.427,38.992,29.674,48.023l-8.235,57.6\r\n c-0.825,5.833,3.235,11.23,9.068,12.055c0.494,0.07,0.993,0.105,1.492,0.105h42.667c5.891,0.06,10.715-4.667,10.774-10.558\r\n c0.005-0.543-0.03-1.086-0.108-1.623l-8.235-57.6C297.788,369.199,309.216,350.82,309.333,330.667z" }), _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " }), " ", _jsx("g", { children: " " })] }));
|
|
75
65
|
}
|
|
76
66
|
function IconShared(props) {
|
|
77
67
|
return (_jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", height: "1em", width: "1em", ...props, children: _jsx("path", { d: "M11 9V5l7 7-7 7v-4.1c-5 0-8.5 1.6-11 5.1 1-5 4-10 11-11m6-1V5l7 7-7 7v-3l4-4-4-4z" }) }));
|
|
78
68
|
}
|
|
79
69
|
function IconSignature(props) {
|
|
80
|
-
return (
|
|
81
|
-
// <svg viewBox="0 0 128 128" fill="currentColor"
|
|
82
|
-
// height="1em"
|
|
83
|
-
// width="1em"
|
|
84
|
-
// {...props}>
|
|
85
|
-
// <g><path d="m128 82.7c0-.3-.1-.6-.2-.8l-6.4-10.9c-2.2-3.7-4.8-7.1-7.9-10.2l-39.8-39.8c-2.7-2.7-7-2.7-9.7 0s-2.7 7 0 9.7l39.8 39.8c3.1 3.1 6.5 5.7 10.2 7.9l8.3 4.8c-.3.2-.7.5-1 .7-1.4 1-2.9 2-4.3 3.1-1.2.9-2.3 1.9-3.3 2.9-2.5 2.2-4.8 4.3-7.8 5.6-3.5 1.5-8.9 2.2-12.6-.9-.7-.6-1.4-1.4-2.2-2.2-2-2.2-4.3-4.7-7.8-4.6-2.9.1-4.9 2-6.7 3.7-.8.8-1.6 1.5-2.4 2-1 .6-2.1.9-3.2.9 1.9-3.5 2.5-7.1 1.7-10.5-.6-2.4-3.1-8.7-7.7-8.5-1.8.1-3.3 1-4.3 2.6-2.2 3.5-1.4 9.7-.4 12.2 1 2.4 2.6 4.4 4.5 5.9-3.9 4.3-9.6 7.4-15.9 8.6-6.4 1.2-12.9-.7-18.2-4.8 4.7-2 9.1-5.2 12.7-9.4 5.7-6.8 8-14.5 6.1-21.1-1.2-4.1-3.8-7.2-7.8-8.9-4.7-2-10.7-1.6-15.6 1.1-11.1 6.1-12.2 20.3-6.8 30.6 1.1 2.1 2.3 4 3.7 5.7-.5.1-1 .1-1.4.1-4.5.1-8.3-1.4-11.4-4.7-9.8-10.2-7-27.9 1.1-38.5 8.4-11 23.5-14.9 35.1-9.1 1 .5 2.2.1 2.7-.9s.1-2.2-.9-2.7c-13.2-6.6-30.4-2.2-40 10.2-9.2 12-12.2 32-.9 43.7 3.9 4 8.9 6.1 14.4 5.9 1.5 0 3-.3 4.5-.6 5.3 4.9 11.9 7.7 18.7 7.7 1.5 0 3-.1 4.6-.4 7.7-1.4 14.4-5.2 18.9-10.6 2.7.8 5.4.4 7.8-1.1 1.1-.7 2.1-1.6 3-2.5 1.4-1.4 2.7-2.5 4-2.6 1.6 0 2.8 1.2 4.7 3.3.8.9 1.6 1.8 2.6 2.6 4.2 3.5 10.8 4.1 16.8 1.5 3.6-1.6 6.3-4 8.9-6.3 1-.9 2.1-1.9 3.2-2.7 1.3-1 2.6-1.9 4-2.9 1.2-.8 2.5-1.7 3.7-2.6.7-.6 1-1.3.9-2zm-12-7.8c-3.4-2-6.5-4.4-9.4-7.2l-39.8-39.8c-1.1-1.1-1.1-2.9 0-4 .6-.6 1.3-.8 2-.8s1.5.3 2 .8l39.8 39.8c2.8 2.8 5.3 6 7.2 9.4l2.7 4.6zm-93.1 15.4c-4.5-8.5-3.8-20.3 5.2-25.2 2.2-1.2 4.8-1.8 7.3-1.8 1.7 0 3.4.3 4.9.9 1.9.8 4.4 2.6 5.5 6.3 2.1 7.6-3 14.7-5.3 17.4-3.5 4.2-8.2 7.4-12.9 9-1.9-2-3.4-4.2-4.7-6.6zm44.3 2.6c-1.4-1-2.5-2.5-3.2-4.2-.7-1.8-1.2-6.5.1-8.6.3-.5.6-.7 1.1-.7 1.2 0 3 3 3.5 5.4.8 3.2-.3 6.1-1.5 8.1z"></path></g>
|
|
86
|
-
// </svg>
|
|
87
|
-
_jsx("svg", { height: "1em", viewBox: "0 0 450 450", width: "1em", fill: "currentColor", ...props, children: _jsx("g", { children: _jsx("g", { children: _jsxs("g", { clipRule: "evenodd", fill: "rgb(0,0,0)", fillRule: "evenodd", children: [_jsx("path", { d: "m366.6 67.8 1.1-4c.4-1.5.6-3 .6-4.5 0-8.1-5.5-15.2-13.3-17.3-9.5-2.5-19.3 3.2-21.8 12.8l-20.4 77.9 34.6 9z" }), _jsx("path", { d: "m234.9 198.9h148.6v35.7h-148.6z", transform: "matrix(.253 -.968 .968 .253 21.311 461.088)" }), _jsx("path", { d: "m292.8 316 8.4 2.2 4.5-17.3-34.6-9.1-4.5 17.4 8.3 2.2z" }), _jsx("path", { d: "m275.3 319.7-12.7 14.7 5.4 40.3 24.4-32.5-3.9-19.1zm6.5 23.3c-.8 2.9-3.7 4.6-6.6 3.9s-4.6-3.7-3.9-6.6 3.7-4.6 6.6-3.9 4.6 3.7 3.9 6.6z" }), _jsx("path", { d: "m395.6 71.5-20.3-5.5-2 7.7 16.5 4.4-24.8 95c-.6 2.1.7 4.3 2.8 4.8.3.1.7.1 1 .1 1.8 0 3.4-1.2 3.8-3l25.8-98.8c.6-2-.7-4.2-2.8-4.7z" }), _jsx("path", { d: "" }), _jsx("path", { d: "m243.4 379.8c-1.8-1.2-4.3-.8-5.5 1.1-9.6 14.1-29.9 19.6-45.3 12.2-.5-.2-.9-.5-1.4-.7-3.5-1.8-7.9-4-12.8-2.7-2.7.7-4.7 2.3-6.5 3.6-1.5 1.2-2.8 2.2-3.9 2.2-2 .1-4-3-5-5.9-.2-.5-.4-1-.5-1.5-1.4-4.1-3.1-9.1-7.8-11.8-5.8-3.3-12.9-.9-17.4 3-2.4 2-4.2 4.4-6 6.7-1.2 1.5-2.3 2.9-3.4 4.1-7.5 7.9-20.3 10-30.2 5.6 7.6-6.9 13-15.5 15.4-24.9s1-21.1-7.8-25.8c-4.5-2.4-9.9-2.4-15.2.2-4.4 2.2-8.4 5.9-10.9 10.3-3.9 7-5.1 15.4-3.3 23.8 1.4 6.3 4.3 12 8.4 16.5-8.4 4.9-18.2 7.3-27.8 6.1-2.2-.3-4.2 1.2-4.5 3.4s1.2 4.2 3.4 4.5c2.1.3 4.1.4 6.2.4 10 0 20.1-3.1 29.1-9 6.1 3.7 13.5 5.4 21.1 4.7 8.5-.8 16.3-4.4 21.8-10.2 1.5-1.5 2.7-3.1 3.9-4.7 1.6-2.1 3.1-4 4.9-5.6 2.4-2 6-3.4 8.3-2.1 2.1 1.2 3.1 4.2 4.2 7.5.2.5.4 1.1.6 1.6 2.5 7 7.1 11.1 12.4 11.1h.6c3.6-.2 6.2-2.2 8.3-3.9 1.3-1 2.5-2 3.6-2.2 2-.5 4.5.8 7.2 2.1.5.3 1 .5 1.5.7 5.7 2.7 11.9 4 18.2 4 14.4 0 29-6.9 37.1-18.9 1.3-1.8.9-4.3-1-5.5zm-152.6 11.3c-8.1-8-10.4-21.8-4.8-31.7 2.5-4.5 7.5-8.2 12-8.2 1.2 0 2.3.3 3.4.8 5 2.7 5.5 10.6 3.9 16.8-2.2 8.7-7.5 16.5-14.5 22.3z" })] }) }) }) })
|
|
88
|
-
// <svg
|
|
89
|
-
// viewBox="0 0 24 24"
|
|
90
|
-
// fill="currentColor"
|
|
91
|
-
// height="1em"
|
|
92
|
-
// width="1em"
|
|
93
|
-
// {...props}
|
|
94
|
-
// >
|
|
95
|
-
// <path d="M22 22H2v-2h20v2M2.26 16.83L5.09 14l-2.83-2.83 1.41-1.41 2.83 2.83 2.83-2.83 1.41 1.41L7.91 14l2.83 2.83-1.41 1.41-2.83-2.83-2.83 2.83-1.41-1.41z" />
|
|
96
|
-
// </svg>
|
|
97
|
-
);
|
|
70
|
+
return (_jsx("svg", { height: "1em", viewBox: "0 0 450 450", width: "1em", fill: "currentColor", ...props, children: _jsx("g", { children: _jsx("g", { children: _jsxs("g", { clipRule: "evenodd", fill: "rgb(0,0,0)", fillRule: "evenodd", children: [_jsx("path", { d: "m366.6 67.8 1.1-4c.4-1.5.6-3 .6-4.5 0-8.1-5.5-15.2-13.3-17.3-9.5-2.5-19.3 3.2-21.8 12.8l-20.4 77.9 34.6 9z" }), _jsx("path", { d: "m234.9 198.9h148.6v35.7h-148.6z", transform: "matrix(.253 -.968 .968 .253 21.311 461.088)" }), _jsx("path", { d: "m292.8 316 8.4 2.2 4.5-17.3-34.6-9.1-4.5 17.4 8.3 2.2z" }), _jsx("path", { d: "m275.3 319.7-12.7 14.7 5.4 40.3 24.4-32.5-3.9-19.1zm6.5 23.3c-.8 2.9-3.7 4.6-6.6 3.9s-4.6-3.7-3.9-6.6 3.7-4.6 6.6-3.9 4.6 3.7 3.9 6.6z" }), _jsx("path", { d: "m395.6 71.5-20.3-5.5-2 7.7 16.5 4.4-24.8 95c-.6 2.1.7 4.3 2.8 4.8.3.1.7.1 1 .1 1.8 0 3.4-1.2 3.8-3l25.8-98.8c.6-2-.7-4.2-2.8-4.7z" }), _jsx("path", { d: "" }), _jsx("path", { d: "m243.4 379.8c-1.8-1.2-4.3-.8-5.5 1.1-9.6 14.1-29.9 19.6-45.3 12.2-.5-.2-.9-.5-1.4-.7-3.5-1.8-7.9-4-12.8-2.7-2.7.7-4.7 2.3-6.5 3.6-1.5 1.2-2.8 2.2-3.9 2.2-2 .1-4-3-5-5.9-.2-.5-.4-1-.5-1.5-1.4-4.1-3.1-9.1-7.8-11.8-5.8-3.3-12.9-.9-17.4 3-2.4 2-4.2 4.4-6 6.7-1.2 1.5-2.3 2.9-3.4 4.1-7.5 7.9-20.3 10-30.2 5.6 7.6-6.9 13-15.5 15.4-24.9s1-21.1-7.8-25.8c-4.5-2.4-9.9-2.4-15.2.2-4.4 2.2-8.4 5.9-10.9 10.3-3.9 7-5.1 15.4-3.3 23.8 1.4 6.3 4.3 12 8.4 16.5-8.4 4.9-18.2 7.3-27.8 6.1-2.2-.3-4.2 1.2-4.5 3.4s1.2 4.2 3.4 4.5c2.1.3 4.1.4 6.2.4 10 0 20.1-3.1 29.1-9 6.1 3.7 13.5 5.4 21.1 4.7 8.5-.8 16.3-4.4 21.8-10.2 1.5-1.5 2.7-3.1 3.9-4.7 1.6-2.1 3.1-4 4.9-5.6 2.4-2 6-3.4 8.3-2.1 2.1 1.2 3.1 4.2 4.2 7.5.2.5.4 1.1.6 1.6 2.5 7 7.1 11.1 12.4 11.1h.6c3.6-.2 6.2-2.2 8.3-3.9 1.3-1 2.5-2 3.6-2.2 2-.5 4.5.8 7.2 2.1.5.3 1 .5 1.5.7 5.7 2.7 11.9 4 18.2 4 14.4 0 29-6.9 37.1-18.9 1.3-1.8.9-4.3-1-5.5zm-152.6 11.3c-8.1-8-10.4-21.8-4.8-31.7 2.5-4.5 7.5-8.2 12-8.2 1.2 0 2.3.3 3.4.8 5 2.7 5.5 10.6 3.9 16.8-2.2 8.7-7.5 16.5-14.5 22.3z" })] }) }) }) }));
|
|
98
71
|
}
|
|
@@ -99,7 +99,7 @@ const TMFileUploader = ({ fromDTD, deviceType = DeviceType.DESKTOP, onClose, onF
|
|
|
99
99
|
let content = !uploadedFile ?
|
|
100
100
|
_jsxs("div", { style: { display: 'flex', gap: 10, width: '100%', height: '100%' }, children: [_jsx(HiddenInput, { id: "fileInput", type: "file", onChange: handleInputChange }), _jsxs(UploadContainer, { ref: uploaderRef, tabIndex: 0, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, style: { backgroundColor: dragOver ? '#76b1e6' : 'white' }, onDoubleClick: browseHandler, "$isRequired": isRequired, children: [_jsxs("div", { style: { display: 'flex', gap: '10px', flexDirection: 'column', position: 'absolute', right: 5, top: 5 }, children: [_jsx(TMButton, { btnStyle: 'icon', caption: 'Sfoglia', color: isRequired && !uploadedFile ? 'error' : 'primary', onClick: browseHandler, icon: _jsx(IconFolderOpen, { fontSize: 22 }) }), showScannerIcon && isScannerLicenseConfigured() && onScanRequest && _jsx(TMButton, { btnStyle: 'icon', caption: 'Scanner', color: 'primary', onClick: () => { onScanRequest((file) => { onFileUpload?.(file); }); }, icon: _jsx(IconScanner, { fontSize: 22 }) }), showScannerIcon && isScannerLicenseConfigured() && !onScanRequest && _jsx(TMButton, { btnStyle: 'icon', caption: 'Scanner', color: 'primary', onClick: () => { ShowAlert({ message: SDKUI_Localizator.ScanFeatureUnavailableInThisContext, mode: 'info', duration: 3000, title: 'Scanner' }); }, icon: _jsx(IconScanner, { fontSize: 22 }) })] }), _jsx("p", { style: { fontSize: '1.2rem', fontWeight: 'bold' }, children: deviceType === DeviceType.MOBILE ? SDKUI_Localizator.ClickToBrowseFile : SDKUI_Localizator.DragOrDoubleClickToBrowseFile }), isRequired && _jsxs("p", { style: { fontWeight: 'bold' }, children: [" ", SDKUI_Localizator.RequiredField, " "] })] })] }) :
|
|
101
101
|
_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 10, width: '100%', height: '100%' }, children: [_jsxs("div", { style: { backgroundColor: 'white', padding: '5px 10px', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: TMColors.primaryColor }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 5 }, children: [_jsx("p", { children: "File name:" }), _jsxs("div", { style: { fontWeight: 'bold' }, children: [fileName, " ", _jsxs("span", { children: [" ", ` (${formatBytes(fileSize)})`, " "] })] })] }), uploadedFile && _jsx(TMButton, { btnStyle: 'icon', color: 'error', caption: 'Pulisci', onClick: () => clearFile(true), icon: _jsx(IconClear, { fontSize: 22 }) })] }), extensionHandler(fileExt) === FileExtensionHandler.READY_TO_SHOW ? _jsx(TMFileViewer, { fileBlob: uploadedFile, isResizingActive: isResizingActive }) :
|
|
102
|
-
_jsx("div", { style: { backgroundColor: '#f6dbdb', padding: '5px 10px', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: TMColors.error }, children: _jsxs("div", { children: [" ",
|
|
102
|
+
_jsx("div", { style: { backgroundColor: '#f6dbdb', padding: '5px 10px', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: TMColors.error }, children: _jsxs("div", { children: [" ", SDKUI_Localizator.PreviewNotAvailable, fileExt && _jsx("b", { children: ` (*.${fileExt})` })] }) })] });
|
|
103
103
|
const innerContent = (_jsxs("div", { style: { width: '100%', height: '100%', padding: '2px', display: 'flex', flexDirection: 'column', gap: 10 }, children: [enableDragDropOverlay && _jsx(TMDragDropOverlay, { handleFile: handleFile, refocusAfterFileInput: refocusAfterFileInput }), content] }));
|
|
104
104
|
const toolbar = useMemo(() => {
|
|
105
105
|
return (_jsxs(_Fragment, { children: [(isPdfEditorAvailable(fromDTD, fileExt) && openFileUploaderPdfEditor) && (_jsx(TMCommandsContextMenu, { target: "#TMPanel-FileUploader-Commands-Header", menuItems: [
|