@topconsultnpm/sdkui-react 6.21.0-t3 → 6.21.0-t4
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/NewComponents/ContextMenu/TMContextMenu.js +23 -18
- package/lib/components/base/TMPopUp.js +3 -3
- package/lib/components/base/TMTreeView.d.ts +16 -13
- package/lib/components/base/TMTreeView.js +230 -64
- package/lib/components/choosers/TMDistinctValues.js +1 -1
- package/lib/components/editors/TMTextBox.d.ts +1 -0
- package/lib/components/editors/TMTextBox.js +2 -1
- package/lib/components/features/documents/TMDcmtForm.d.ts +2 -0
- package/lib/components/features/documents/TMDcmtForm.js +2 -1
- 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.d.ts +2 -0
- package/lib/components/features/documents/TMMasterDetailDcmts.js +54 -14
- package/lib/components/features/documents/TMMergeToPdfForm.d.ts +2 -1
- package/lib/components/features/documents/TMMergeToPdfForm.js +91 -48
- package/lib/components/features/documents/TMRelationViewer.d.ts +12 -10
- package/lib/components/features/documents/TMRelationViewer.js +401 -96
- package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +4 -3
- package/lib/components/features/documents/copyAndMergeDcmtsShared.js +47 -23
- package/lib/components/features/documents/mergePdfUtils.d.ts +52 -0
- package/lib/components/features/documents/mergePdfUtils.js +268 -0
- package/lib/components/features/search/TMSearch.d.ts +2 -0
- package/lib/components/features/search/TMSearch.js +2 -2
- package/lib/components/features/search/TMSearchResult.d.ts +2 -0
- package/lib/components/features/search/TMSearchResult.js +58 -9
- package/lib/components/viewers/TMTidViewer.js +14 -2
- package/lib/helper/Enum_Localizator.js +1 -0
- package/lib/helper/SDKUI_Globals.d.ts +1 -0
- package/lib/helper/SDKUI_Globals.js +1 -0
- package/lib/helper/SDKUI_Localizator.d.ts +34 -0
- package/lib/helper/SDKUI_Localizator.js +352 -12
- package/lib/helper/TMUtils.d.ts +33 -1
- package/lib/helper/TMUtils.js +104 -1
- package/lib/helper/certificateImportHelper.d.ts +43 -0
- package/lib/helper/certificateImportHelper.js +403 -0
- package/lib/helper/helpers.js +9 -0
- package/lib/helper/index.d.ts +1 -0
- package/lib/helper/index.js +1 -0
- package/lib/hooks/useDcmtOperations.d.ts +2 -1
- package/lib/hooks/useDcmtOperations.js +10 -2
- package/lib/hooks/useDocumentOperations.d.ts +2 -0
- package/lib/hooks/useDocumentOperations.js +28 -6
- package/lib/services/platform_services.d.ts +1 -1
- package/lib/ts/types.d.ts +2 -1
- package/lib/ts/types.js +1 -0
- package/package.json +3 -2
|
@@ -395,26 +395,31 @@ const TMContextMenu = ({ items, trigger = 'right', children, target, externalCon
|
|
|
395
395
|
];
|
|
396
396
|
});
|
|
397
397
|
};
|
|
398
|
-
// Caps overflowing submenus with max-height + scroll so every item stays reachable.
|
|
399
398
|
useLayoutEffect(() => {
|
|
400
399
|
if (hoveredSubmenus.length === 0)
|
|
401
400
|
return;
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
401
|
+
const capSubmenus = () => {
|
|
402
|
+
const padding = 8;
|
|
403
|
+
const submenus = document.querySelectorAll('[data-submenu="true"]');
|
|
404
|
+
submenus.forEach(el => {
|
|
405
|
+
el.style.maxHeight = '';
|
|
406
|
+
el.style.overflowY = '';
|
|
407
|
+
el.style.overflowX = '';
|
|
408
|
+
const rect = el.getBoundingClientRect();
|
|
409
|
+
const opensUp = el.dataset.openUp === 'true';
|
|
410
|
+
const available = opensUp
|
|
411
|
+
? rect.bottom - padding
|
|
412
|
+
: window.innerHeight - rect.top - padding;
|
|
413
|
+
if (rect.height <= available)
|
|
414
|
+
return;
|
|
415
|
+
el.style.maxHeight = `${Math.max(80, available)}px`;
|
|
416
|
+
el.style.overflowY = 'auto';
|
|
417
|
+
el.style.overflowX = 'hidden';
|
|
418
|
+
});
|
|
419
|
+
};
|
|
420
|
+
capSubmenus();
|
|
421
|
+
window.addEventListener('resize', capSubmenus);
|
|
422
|
+
return () => window.removeEventListener('resize', capSubmenus);
|
|
418
423
|
}, [hoveredSubmenus]);
|
|
419
424
|
const handleMouseLeave = (depth = 0) => {
|
|
420
425
|
if (isMobile)
|
|
@@ -495,6 +500,6 @@ const TMContextMenu = ({ items, trigger = 'right', children, target, externalCon
|
|
|
495
500
|
// display: 'inline-block',
|
|
496
501
|
WebkitTouchCallout: isIOS ? 'none' : undefined,
|
|
497
502
|
WebkitUserSelect: isIOS ? 'none' : undefined,
|
|
498
|
-
}, children: children })), menuState.visible && createPortal(_jsxs(_Fragment, { children: [_jsxs(S.MenuContainer, { ref: menuRef, "$x": menuState.position.x, "$y": menuState.position.y, "$openLeft": openLeft, "$openUp": openUp, "$isPositioned": isCalculated, "$externalControl": !!externalControl, "$needsScroll": needsScroll, "$maxHeight": maxHeight, children: [isMobile && menuState.parentNames.length > 0 && (_jsxs(S.MobileMenuHeader, { children: [_jsx(S.BackButton, { onClick: handleBack, "aria-label": "Go back", children: _jsx(IconArrowLeft, {}) }), _jsx(S.HeaderTitle, { children: currentParentName })] })), renderMenuItems(currentMenu, 0)] }), !isMobile && hoveredSubmenus.map((submenu, idx) => (_jsx(S.Submenu, { "$parentRect": submenu.parentRect, "$openUp": submenu.openUp, "data-submenu": "true", onMouseEnter: handleSubmenuMouseEnter, onMouseLeave: () => handleMouseLeave(submenu.depth), children: renderMenuItems(submenu.items, submenu.depth) }, `submenu-${submenu.depth}-${idx}`)))] }), document.body)] }));
|
|
503
|
+
}, children: children })), menuState.visible && createPortal(_jsxs(_Fragment, { children: [_jsxs(S.MenuContainer, { ref: menuRef, "$x": menuState.position.x, "$y": menuState.position.y, "$openLeft": openLeft, "$openUp": openUp, "$isPositioned": isCalculated, "$externalControl": !!externalControl, "$needsScroll": needsScroll, "$maxHeight": maxHeight, children: [isMobile && menuState.parentNames.length > 0 && (_jsxs(S.MobileMenuHeader, { children: [_jsx(S.BackButton, { onClick: handleBack, "aria-label": "Go back", children: _jsx(IconArrowLeft, {}) }), _jsx(S.HeaderTitle, { children: currentParentName })] })), renderMenuItems(currentMenu, 0)] }), !isMobile && hoveredSubmenus.map((submenu, idx) => (_jsx(S.Submenu, { "$parentRect": submenu.parentRect, "$openUp": submenu.openUp, "data-submenu": "true", "data-open-up": submenu.openUp ? 'true' : 'false', onMouseEnter: handleSubmenuMouseEnter, onMouseLeave: () => handleMouseLeave(submenu.depth), children: renderMenuItems(submenu.items, submenu.depth) }, `submenu-${submenu.depth}-${idx}`)))] }), document.body)] }));
|
|
499
504
|
};
|
|
500
505
|
export default TMContextMenu;
|
|
@@ -23,8 +23,8 @@ export var ButtonNames;
|
|
|
23
23
|
// Dimensioni minime di default per i popup
|
|
24
24
|
const DEFAULT_MIN_WIDTH = 500;
|
|
25
25
|
const DEFAULT_MIN_HEIGHT = 400;
|
|
26
|
-
// filtr
|
|
27
|
-
const
|
|
26
|
+
// filtr sensitive keys from all errors.
|
|
27
|
+
const SENSITIVE_KEYS = ['password', 'username'];
|
|
28
28
|
const redactSensitiveJsonString = (value) => {
|
|
29
29
|
const trimmed = value.trim();
|
|
30
30
|
const looksLikeJson = (trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'));
|
|
@@ -46,7 +46,7 @@ const redactSensitiveValue = (value) => {
|
|
|
46
46
|
return value;
|
|
47
47
|
const result = {};
|
|
48
48
|
for (const key of Object.keys(value)) {
|
|
49
|
-
result[key] = key.toLowerCase()
|
|
49
|
+
result[key] = SENSITIVE_KEYS.includes(key.toLowerCase()) ? '***' : redactSensitiveValue(value[key]);
|
|
50
50
|
}
|
|
51
51
|
return result;
|
|
52
52
|
};
|
|
@@ -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) => React.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
|
|
|
@@ -11,7 +11,7 @@ import TMPanel from '../base/TMPanel';
|
|
|
11
11
|
import TMModal from '../base/TMModal';
|
|
12
12
|
import { useDataListItem } from '../../hooks/useDataListItem';
|
|
13
13
|
import { useDataUserIdItem } from '../../hooks/useDataUserIdItem';
|
|
14
|
-
const StyledDistinctValues = styled.div `display: flex; flex-direction: column; height: 100%; overflow: hidden; gap: 10px;`;
|
|
14
|
+
const StyledDistinctValues = styled.div `display: flex; flex-direction: column; height: 100%; overflow: hidden; gap: 10px; position: relative;`;
|
|
15
15
|
const TMDistinctValues = ({ tid, mid, layoutMode = LayoutModes.None, allowAppendMode = true, showHeader = true, isModal, separator = " ", onSelectionChanged, onClosePanelCallback }) => {
|
|
16
16
|
const [focusedItem, setFocusedItem] = useState();
|
|
17
17
|
const [dataSource, setDataSource] = useState([]);
|
|
@@ -17,6 +17,7 @@ export interface ITMTextBox extends ITMEditorBase {
|
|
|
17
17
|
onClick?: () => void;
|
|
18
18
|
onValueChanged?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
19
19
|
onBlur?: (value: string | undefined) => void;
|
|
20
|
+
onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
20
21
|
}
|
|
21
22
|
declare const TMTextBox: React.FunctionComponent<ITMTextBox>;
|
|
22
23
|
export default TMTextBox;
|
|
@@ -34,7 +34,7 @@ const StyledTextBoxEditorButton = styled.div `
|
|
|
34
34
|
border-bottom-color: ${TMColors.primary};
|
|
35
35
|
}
|
|
36
36
|
`;
|
|
37
|
-
const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, precision, fromModal = false, scale, showClearButton, validationItems = [], label = '', readOnly = false, formulaItems = [], buttons = [], isModifiedWhen, placeHolder, elementStyle, width = '100%', maxValue, minValue, fontSize = FontSize.defaultFontSize, icon, labelPosition = 'left', value, disabled = false, type = 'text', onClick, onValueChanged, onBlur, borderRadius, allowedPattern }) => {
|
|
37
|
+
const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, precision, fromModal = false, scale, showClearButton, validationItems = [], label = '', readOnly = false, formulaItems = [], buttons = [], isModifiedWhen, placeHolder, elementStyle, width = '100%', maxValue, minValue, fontSize = FontSize.defaultFontSize, icon, labelPosition = 'left', value, disabled = false, type = 'text', onClick, onValueChanged, onBlur, onKeyDown, borderRadius, allowedPattern }) => {
|
|
38
38
|
const [initialType, setInitialType] = useState(type);
|
|
39
39
|
const [currentType, setCurrentType] = useState(type);
|
|
40
40
|
const [currentValue, setCurrentValue] = useState(value);
|
|
@@ -283,6 +283,7 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
283
283
|
if (!scale && (e.key == "." || e.key == ","))
|
|
284
284
|
e.preventDefault();
|
|
285
285
|
}
|
|
286
|
+
onKeyDown?.(e);
|
|
286
287
|
}, "$isMobile": deviceType === DeviceType.MOBILE, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, "$fontSize": fontSize, "$maxValue": maxValue, "$width": width, "$type": currentType, "$borderRadius": borderRadius, style: { paddingRight: `${calculateRightPadding()}px`, cursor: onClick ? 'pointer' : undefined } }), (initialType === 'password' || initialType === 'secureText') && _jsx(StyledShowPasswordIcon, { onClick: toggleShowPassword, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, children: showPasswordIcon() }), initialType !== 'password' &&
|
|
287
288
|
_jsxs("div", { style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', position: 'absolute', right: type === 'number' ? '25px' : '6px', top: label.length > 0 ? '20px' : '3px', pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
|
|
288
289
|
_jsx(StyledTextBoxEditorButton, { onClick: () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { DcmtTypeDescriptor, HomeBlogPost, LayoutModes, ObjectRef, SearchResultDescriptor, TaskDescriptor, ValidationItem } from '@topconsultnpm/sdk-ts';
|
|
3
3
|
import { DcmtInfo, FormModes, MetadataValueDescriptorEx, TaskContext } from '../../../ts';
|
|
4
|
+
import { IntesiCertificateData } from '../../../helper';
|
|
4
5
|
/**
|
|
5
6
|
* Definisce il contesto da cui è stato invocato il TMDcmtForm.
|
|
6
7
|
* Permette di gestire logiche diverse in base alla provenienza.
|
|
@@ -75,6 +76,7 @@ interface ITMDcmtFormProps {
|
|
|
75
76
|
mid: number;
|
|
76
77
|
value: string;
|
|
77
78
|
}>, tid?: number) => void;
|
|
79
|
+
fetchRemoteCertificates?: (email: string) => Promise<IntesiCertificateData[]>;
|
|
78
80
|
datagridUtility?: {
|
|
79
81
|
onRefreshSearchAsyncDatagrid?: () => Promise<void>;
|
|
80
82
|
onRefreshDataRowsAsync?: (() => Promise<void>);
|
|
@@ -57,7 +57,7 @@ export var InvocationContext;
|
|
|
57
57
|
let abortControllerLocal = new AbortController();
|
|
58
58
|
;
|
|
59
59
|
//#endregion
|
|
60
|
-
const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMode = FormModes.Update, invocationContext = InvocationContext.Default, showHeader = true, showBackButton = true, showDcmtFormSidebar = true, isClosable = false, showTodoDcmtForm = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, isModal = false, titleModal, widthModal = "100%", heightModal = "100%", allowNavigation = true, canNext, canPrev, count, itemIndex, onNext, onPrev, inputFile = null, inputMids = [], connectorFileSave = undefined, isSharedDcmt = false, sharedSourceTID, sharedSourceDID, allowRelations = true, allowButtonsRefs = false, openS4TViewer = false, enableDragDropOverlay = false, onClose, onSavedAsyncCallback, onSaveRecents, onWFOperationCompleted, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, onTaskCompleted, onTaskCreateRequest, moreInfoTasks, taskFormDialogComponent, handleNavigateToWGs, handleNavigateToDossiers, onReferenceClick, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, s4TViewerDialogComponent, onScanRequest, passToSearch, datagridUtility }) => {
|
|
60
|
+
const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMode = FormModes.Update, invocationContext = InvocationContext.Default, showHeader = true, showBackButton = true, showDcmtFormSidebar = true, isClosable = false, showTodoDcmtForm = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, isModal = false, titleModal, widthModal = "100%", heightModal = "100%", allowNavigation = true, canNext, canPrev, count, itemIndex, onNext, onPrev, inputFile = null, inputMids = [], connectorFileSave = undefined, isSharedDcmt = false, sharedSourceTID, sharedSourceDID, allowRelations = true, allowButtonsRefs = false, openS4TViewer = false, enableDragDropOverlay = false, onClose, onSavedAsyncCallback, onSaveRecents, onWFOperationCompleted, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, onTaskCompleted, onTaskCreateRequest, moreInfoTasks, taskFormDialogComponent, handleNavigateToWGs, handleNavigateToDossiers, onReferenceClick, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, s4TViewerDialogComponent, onScanRequest, passToSearch, fetchRemoteCertificates, datagridUtility }) => {
|
|
61
61
|
const { onRefreshSearchAsyncDatagrid, onRefreshBlogDatagrid, onRefreshPreviewDatagrid } = datagridUtility || {};
|
|
62
62
|
const floatingBarContainerRef = useRef(null);
|
|
63
63
|
const [id, setID] = useState('');
|
|
@@ -395,6 +395,7 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
|
|
|
395
395
|
currentSearchResults,
|
|
396
396
|
currentMetadataValues: formData,
|
|
397
397
|
allUsers,
|
|
398
|
+
fetchRemoteCertificates,
|
|
398
399
|
datagridUtility: {
|
|
399
400
|
onRefreshBlogDatagrid,
|
|
400
401
|
onRefreshPreviewDatagrid,
|
|
@@ -14,6 +14,8 @@ interface ITMDcmtIconProps {
|
|
|
14
14
|
tooltipContent?: JSX.Element | string;
|
|
15
15
|
openInOffice?: (selectedDcmtsOrFocused: Array<DcmtInfo>) => Promise<void>;
|
|
16
16
|
onDownloadDcmtsAsync?: (inputDcmts: DcmtInfo[] | undefined, downloadType: DownloadTypes, downloadMode: DownloadModes, onFileDownloaded?: (dcmtFile: File | undefined) => void, confirmAttachments?: (list: FileDescriptor[]) => Promise<string[] | undefined>) => Promise<void>;
|
|
17
|
+
/** Se true, renderizza il wait panel nel body tramite Portal (centrato a schermo intero) */
|
|
18
|
+
usePortal?: boolean;
|
|
17
19
|
}
|
|
18
|
-
declare const TMDcmtIcon: ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode, tooltipContent, openInOffice, onDownloadDcmtsAsync }: ITMDcmtIconProps) => React.JSX.Element;
|
|
20
|
+
declare const TMDcmtIcon: ({ fileExtension, fileCount, isLexProt, isSigned, isMail, isShared, tid, did, downloadMode, tooltipContent, openInOffice, onDownloadDcmtsAsync, usePortal }: ITMDcmtIconProps) => React.JSX.Element;
|
|
19
21
|
export default TMDcmtIcon;
|