@topconsultnpm/sdkui-react-beta 6.12.36 → 6.12.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/lib/components/base/Styled.d.ts +12 -0
  2. package/lib/components/base/Styled.js +49 -3
  3. package/lib/components/base/TMFloatingToolbar.d.ts +9 -0
  4. package/lib/components/base/TMFloatingToolbar.js +99 -0
  5. package/lib/components/base/TMRightSidebar.d.ts +0 -4
  6. package/lib/components/base/TMRightSidebar.js +2 -10
  7. package/lib/components/base/TMShowAllOrMaxItemsButton.d.ts +8 -0
  8. package/lib/components/base/TMShowAllOrMaxItemsButton.js +14 -0
  9. package/lib/components/base/TMTreeView.d.ts +27 -0
  10. package/lib/components/base/TMTreeView.js +199 -0
  11. package/lib/components/grids/TMBlogs.d.ts +84 -0
  12. package/lib/components/grids/TMBlogs.js +566 -0
  13. package/lib/components/grids/TMBlogsUtils.d.ts +83 -0
  14. package/lib/components/grids/TMBlogsUtils.js +258 -0
  15. package/lib/components/index.d.ts +2 -0
  16. package/lib/components/index.js +2 -0
  17. package/lib/components/query/TMBatchUpdateForm.d.ts +12 -0
  18. package/lib/components/query/TMBatchUpdateForm.js +149 -0
  19. package/lib/components/query/TMDcmtBlog.d.ts +7 -0
  20. package/lib/components/query/TMDcmtBlog.js +33 -0
  21. package/lib/components/query/TMDcmtForm.d.ts +32 -0
  22. package/lib/components/query/TMDcmtForm.js +544 -0
  23. package/lib/components/query/TMDcmtIcon.d.ts +10 -0
  24. package/lib/components/query/TMDcmtIcon.js +52 -0
  25. package/lib/components/query/TMDcmtPreview.d.ts +26 -0
  26. package/lib/components/query/TMDcmtPreview.js +200 -0
  27. package/lib/components/query/TMFileUploader.d.ts +11 -0
  28. package/lib/components/query/TMFileUploader.js +101 -0
  29. package/lib/components/query/TMMasterDetailDcmts.d.ts +23 -0
  30. package/lib/components/query/TMMasterDetailDcmts.js +475 -0
  31. package/lib/components/query/TMQueryEditor.js +2 -2
  32. package/lib/components/query/TMQueryResultForm.d.ts +1 -7
  33. package/lib/components/query/TMQueryResultForm.js +1 -9
  34. package/lib/components/query/TMWorkflowPopup.d.ts +29 -0
  35. package/lib/components/query/TMWorkflowPopup.js +131 -0
  36. package/lib/components/search/TMSearchResult.d.ts +31 -0
  37. package/lib/components/search/TMSearchResult.js +727 -0
  38. package/lib/components/search/TMSearchResultsMenuItems.d.ts +6 -0
  39. package/lib/components/search/TMSearchResultsMenuItems.js +376 -0
  40. package/lib/helper/Enum_Localizator.d.ts +2 -1
  41. package/lib/helper/Enum_Localizator.js +20 -1
  42. package/lib/helper/SDKUI_Localizator.d.ts +24 -0
  43. package/lib/helper/SDKUI_Localizator.js +240 -0
  44. package/lib/helper/dcmtsHelper.d.ts +4 -0
  45. package/lib/helper/dcmtsHelper.js +15 -0
  46. package/lib/helper/helpers.d.ts +2 -1
  47. package/lib/helper/helpers.js +74 -1
  48. package/lib/helper/queryHelper.d.ts +7 -1
  49. package/lib/helper/queryHelper.js +105 -1
  50. package/lib/hooks/useDcmtOperations.d.ts +24 -0
  51. package/lib/hooks/useDcmtOperations.js +387 -0
  52. package/lib/hooks/useInputDialog.d.ts +5 -0
  53. package/lib/hooks/useInputDialog.js +73 -0
  54. package/lib/hooks/usePreventFileDrop.d.ts +3 -0
  55. package/lib/hooks/usePreventFileDrop.js +37 -0
  56. package/lib/index.d.ts +0 -1
  57. package/lib/index.js +0 -1
  58. package/lib/services/platform_services.d.ts +1 -1
  59. package/lib/ts/types.d.ts +54 -1
  60. package/lib/ts/types.js +34 -0
  61. package/package.json +1 -1
@@ -2,6 +2,9 @@ import React from 'react';
2
2
  import { ResultTypes } from '@topconsultnpm/sdk-ts-beta';
3
3
  import { TMColors } from '../../utils/theme';
4
4
  export declare const StyledDivHorizontal: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
5
+ export declare const StyledMultiViewPanel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
6
+ $isVisible: boolean;
7
+ }>> & string;
5
8
  export declare const StyledParagraph: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, never>> & string;
6
9
  export declare const StyledToolbarForm: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
7
10
  export declare const StyledPanelPage: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
@@ -33,3 +36,12 @@ export declare const StyledChartOverlay: import("styled-components/dist/types").
33
36
  export declare const StyledBtnLoadChart: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
34
37
  $backgroundColor?: string;
35
38
  }>> & string;
39
+ export declare const StyledFormButtonsContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
40
+ export declare const StyledToolbarCardContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
41
+ export declare const StyledAnimatedComponentScaleColor: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
42
+ $delay?: string;
43
+ $scale?: number;
44
+ }>> & string;
45
+ export declare const StyledAnimatedComponentOpacity: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
46
+ $delay?: string;
47
+ }>> & string;
@@ -1,5 +1,5 @@
1
1
  import { jsxs as _jsxs } from "react/jsx-runtime";
2
- import styled from 'styled-components';
2
+ import styled, { keyframes } from 'styled-components';
3
3
  import { ResultTypes } from '@topconsultnpm/sdk-ts-beta';
4
4
  import { FontSize, TMColors } from '../../utils/theme';
5
5
  export const StyledDivHorizontal = styled.div `
@@ -8,6 +8,15 @@ export const StyledDivHorizontal = styled.div `
8
8
  align-items: center;
9
9
  justify-content: flex-start;
10
10
  `;
11
+ export const StyledMultiViewPanel = styled.div `
12
+ display: flex;
13
+ width: 100%;
14
+ height: 100%;
15
+ position: ${(props) => props.$isVisible ? 'relative' : 'absolute'};
16
+ left: ${(props) => props.$isVisible ? '0px' : '-9999px'};
17
+ top: ${(props) => props.$isVisible ? '0px' : '-9999px'};
18
+ top: ${(props) => props.$isVisible ? 'visible' : '-hidden'};
19
+ `;
11
20
  export const StyledParagraph = styled.p `
12
21
  display: flex;
13
22
  flex-direction: row;
@@ -126,7 +135,7 @@ export const StyledChartOverlay = styled.div `
126
135
  position: absolute;
127
136
  align-items: center;
128
137
  justify-content: center;
129
- background-color: ${(props) => props.$backgroundColor ? props.$backgroundColor : 'black'};
138
+ background-color: ${(props) => props.$backgroundColor ?? 'black'};
130
139
  `;
131
140
  export const StyledBtnLoadChart = styled.button `
132
141
  display: flex;
@@ -145,7 +154,7 @@ export const StyledBtnLoadChart = styled.button `
145
154
  cursor: pointer;
146
155
  transform: translateY(1px);
147
156
  box-shadow: 1px 1px #bbbbbb;
148
- background-color: ${(props) => props.$backgroundColor ? props.$backgroundColor : 'orange'};
157
+ background-color: ${(props) => props.$backgroundColor ?? 'orange'};
149
158
  .iconrefresh {
150
159
  transition:.5s;
151
160
  transform: rotate(180deg);
@@ -157,3 +166,40 @@ export const StyledBtnLoadChart = styled.button `
157
166
  box-shadow: 0 0 1px #bbbbbb;
158
167
  }
159
168
  `;
169
+ export const StyledFormButtonsContainer = styled.div `
170
+ display: flex;
171
+ justify-content: center;
172
+ align-items: center;
173
+ padding: 10px;
174
+ position: relative;
175
+ width: 100%;
176
+ min-width: max-content;
177
+ gap: 80px;
178
+ `;
179
+ export const StyledToolbarCardContainer = styled.div `
180
+ background-color: #ffffff;
181
+ width: 100%;
182
+ height: 100%;
183
+ display: flex;
184
+ flex-direction: column;
185
+ gap: 10px;
186
+ `;
187
+ //#region Animations
188
+ const scaleAndColorChange = (scaleValue) => keyframes `
189
+ 0% { transform: scale(1); color: white; }
190
+ 50% { transform: scale(${scaleValue}); color: orange; }
191
+ 100% { transform: scale(1); color: white; }
192
+ `;
193
+ const opacityChange = keyframes `
194
+ from { opacity: 0; }
195
+ to { opacity: 1; }
196
+ `;
197
+ export const StyledAnimatedComponentScaleColor = styled.div `
198
+ animation: ${props => scaleAndColorChange(props.$scale ?? 1.5)} 400ms ease-in-out ;
199
+ animation-delay: ${props => props.$delay ?? '0'};
200
+ `;
201
+ export const StyledAnimatedComponentOpacity = styled.div `
202
+ opacity: 0;
203
+ animation: ${opacityChange} 400ms ease forwards normal ;
204
+ animation-delay: ${props => props.$delay ?? '0'};
205
+ `;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface ITMFloatingToolbarProps {
3
+ children: React.ReactNode;
4
+ backgroundColor: string | undefined;
5
+ initialLeft?: string;
6
+ initialTop?: string;
7
+ }
8
+ declare const TMFloatingToolbar: ({ children, backgroundColor, initialLeft, initialTop }: ITMFloatingToolbarProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default TMFloatingToolbar;
@@ -0,0 +1,99 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
3
+ import styled from 'styled-components';
4
+ import { IconDraggabledots } from '../../helper/TMIcons';
5
+ const StyledFloatingToolbarContainer = styled.div `
6
+ position: absolute;
7
+ width: max-content;
8
+ height: max-content;
9
+ display: flex;
10
+ flex-direction: row;
11
+ background-color: ${props => `${props.$backgroundColor}a6`};
12
+ left: calc(50% - 90px);
13
+ top: calc(100% - 40px);
14
+ border-radius: 8px;
15
+ z-index: 10;
16
+ &:hover {
17
+ background: ${props => props.$backgroundColor};
18
+ }
19
+ `;
20
+ const StyledFloatingToolbarDraggable = styled.div `
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ width: 25px;
25
+ height: 100%;
26
+ background-color: ${props => `${props.$backgroundColor}FF`};
27
+ border-top-left-radius: 8px;
28
+ border-bottom-left-radius: 8px;
29
+ padding: 10px 0px 10px 0px;
30
+ &:hover {
31
+ cursor: grab;
32
+ }
33
+ `;
34
+ const StyledFloatingToolbar = styled.div `
35
+ width: max-content;
36
+ display: flex;
37
+ flex-direction: row;
38
+ padding: 10px 10px 10px 20px;
39
+ gap: 8px;
40
+ border-radius: 8px;
41
+ `;
42
+ const TMFloatingToolbar = ({ children, backgroundColor, initialLeft, initialTop }) => {
43
+ const boxRef = useRef(null);
44
+ const boxDraggableRef = useRef(null);
45
+ const isClicked = useRef(false);
46
+ const coords = useRef({
47
+ startX: 0,
48
+ startY: 0,
49
+ lastX: 0,
50
+ lastY: 0
51
+ });
52
+ useEffect(() => {
53
+ if (!boxRef.current)
54
+ return;
55
+ if (!boxDraggableRef)
56
+ return;
57
+ let container = boxRef.current?.parentElement;
58
+ if (!container)
59
+ return;
60
+ const box = boxRef.current;
61
+ box.style.top = initialTop ?? `0px`;
62
+ box.style.left = initialLeft ?? `0px`;
63
+ const onMouseDown = (e) => {
64
+ isClicked.current = true;
65
+ coords.current.startX = e.clientX;
66
+ coords.current.startY = e.clientY;
67
+ };
68
+ const onMouseUp = (e) => {
69
+ isClicked.current = false;
70
+ coords.current.lastX = box.offsetLeft;
71
+ coords.current.lastY = box.offsetTop;
72
+ };
73
+ const onMouseMove = (e) => {
74
+ if (!isClicked.current)
75
+ return;
76
+ const nextX = e.clientX - coords.current.startX + coords.current.lastX;
77
+ const nextY = e.clientY - coords.current.startY + coords.current.lastY;
78
+ const screenWidth = container.getBoundingClientRect().width;
79
+ const screenHeight = container.getBoundingClientRect().height;
80
+ const boundedX = Math.max(0, Math.min(screenWidth - box.getBoundingClientRect().width, nextX));
81
+ const boundedY = Math.max(0, Math.min(screenHeight - box.getBoundingClientRect().height, nextY));
82
+ box.style.top = `${boundedY}px`;
83
+ box.style.left = `${boundedX}px`;
84
+ };
85
+ boxDraggableRef.current?.addEventListener('mousedown', onMouseDown);
86
+ window.addEventListener('mouseup', onMouseUp);
87
+ window.addEventListener('mousemove', onMouseMove);
88
+ window.addEventListener('mouseleave', onMouseUp);
89
+ const cleanup = () => {
90
+ boxDraggableRef.current?.removeEventListener('mousedown', onMouseDown);
91
+ window.removeEventListener('mouseup', onMouseUp);
92
+ window.removeEventListener('mousemove', onMouseMove);
93
+ window.removeEventListener('mouseleave', onMouseUp);
94
+ };
95
+ return cleanup;
96
+ }, []);
97
+ return (_jsxs(StyledFloatingToolbarContainer, { ref: boxRef, "$backgroundColor": backgroundColor, children: [_jsx(StyledFloatingToolbarDraggable, { ref: boxDraggableRef, "$backgroundColor": backgroundColor, children: _jsx(IconDraggabledots, { color: 'white' }) }), _jsx(StyledFloatingToolbar, { "$backgroundColor": backgroundColor, children: children })] }));
98
+ };
99
+ export default TMFloatingToolbar;
@@ -17,7 +17,3 @@ export interface ITMRightSidebarProps {
17
17
  }
18
18
  declare const TMRightSidebar: React.FC<ITMRightSidebarProps>;
19
19
  export default TMRightSidebar;
20
- export declare const StyledAnimatedComponentScaleColor: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
21
- $delay?: string;
22
- $scale?: number;
23
- }>> & string;
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from 'react';
3
- import styled, { keyframes } from 'styled-components';
3
+ import styled from 'styled-components';
4
4
  import { TMColors } from '../../utils/theme';
5
+ import { StyledAnimatedComponentScaleColor } from './Styled';
5
6
  const TMRightSidebar = ({ items = [], onItemClick, selectedItem, showPanel = false }) => {
6
7
  const [hoveredItem, setHoveredItem] = useState(null);
7
8
  const [activeItems, setActiveItems] = useState(new Set());
@@ -35,15 +36,6 @@ const TMRightSidebar = ({ items = [], onItemClick, selectedItem, showPanel = fal
35
36
  };
36
37
  export default TMRightSidebar;
37
38
  // Styled Components
38
- const scaleAndColorChange = (scaleValue) => keyframes `
39
- 0% { transform: scale(1); color: white; }
40
- 50% { transform: scale(${scaleValue}); color: orange; }
41
- 100% { transform: scale(1); color: white; }
42
- `;
43
- export const StyledAnimatedComponentScaleColor = styled.div `
44
- animation: ${props => scaleAndColorChange(props.$scale ?? 1.5)} 400ms ease-in-out;
45
- animation-delay: ${props => props.$delay ? props.$delay : '0'};
46
- `;
47
39
  const SidebarContainer = styled.div `
48
40
  width: 30px;
49
41
  height: 100%;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ interface ITMShowAllOrMaxItemsButtonProps {
3
+ showAll: boolean;
4
+ dataSourceLength: number;
5
+ onClick?: () => void;
6
+ }
7
+ declare const TMShowAllOrMaxItemsButton: React.FC<ITMShowAllOrMaxItemsButtonProps>;
8
+ export default TMShowAllOrMaxItemsButton;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { getListMaxItems } from '../../helper';
3
+ import { TMColors } from '../../utils/theme';
4
+ import TMButton from './TMButton';
5
+ import { useDeviceType, DeviceType } from './TMDeviceProvider';
6
+ const TMShowAllOrMaxItemsButton = ({ showAll, dataSourceLength, onClick }) => {
7
+ const deviceType = useDeviceType();
8
+ let maxItems = getListMaxItems(deviceType ?? DeviceType.DESKTOP);
9
+ const captionText = showAll ? "Mostra meno" : `Mostra tutti (+${dataSourceLength - maxItems})`;
10
+ return (_jsx(TMButton, { elementStyle: { position: 'absolute', right: '10px' }, btnStyle: 'icon', caption: captionText, icon: showAll ?
11
+ _jsx("div", { style: { backgroundColor: TMColors.primaryColor, minWidth: '30px', minHeight: '30px', borderRadius: '10px', display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: _jsx("p", { style: { color: 'white' }, children: `-${dataSourceLength - maxItems}` }) }) :
12
+ _jsx("div", { style: { backgroundColor: TMColors.primaryColor, minWidth: '30px', minHeight: '30px', borderRadius: '10px', display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: _jsx("p", { style: { color: 'white' }, children: `+${dataSourceLength - maxItems}` }) }), onClick: () => onClick?.() }));
13
+ };
14
+ export default TMShowAllOrMaxItemsButton;
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ export interface ITMTreeItem {
3
+ key: string | undefined;
4
+ name?: string;
5
+ expanded?: boolean;
6
+ hidden?: boolean;
7
+ isLoaded?: boolean;
8
+ isContainer: boolean;
9
+ items?: ITMTreeItem[];
10
+ }
11
+ interface ITMTreeViewProps<T extends ITMTreeItem> {
12
+ dataSource?: T[];
13
+ focusedItem?: T | null;
14
+ selectedItems?: T[];
15
+ allowMultipleSelection?: boolean;
16
+ calculateItemsForNode?: (node: T) => Promise<T[] | undefined>;
17
+ itemRender: (item: T | null) => JSX.Element;
18
+ onFocusedItemChanged?: (item: T | null) => void;
19
+ onSelectionChanged?: (selectedItems: T[]) => void;
20
+ onNodeUpdate?: (updatedNode: T) => void;
21
+ onDataChanged?: (items: T[]) => void;
22
+ }
23
+ declare const TMTreeView: <T extends ITMTreeItem>({ dataSource, focusedItem, selectedItems, allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged }: ITMTreeViewProps<T>) => import("react/jsx-runtime").JSX.Element;
24
+ export default TMTreeView;
25
+ export declare const StyledTreeNode: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
26
+ $isSelected?: boolean;
27
+ }>> & string;
@@ -0,0 +1,199 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect } from 'react';
3
+ import styled from 'styled-components';
4
+ import { IconChevronDown, IconChevronRight } from '../../helper';
5
+ import { TMColors } from '../../utils/theme';
6
+ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged }) => {
7
+ useEffect(() => {
8
+ const handleKeyDown = (event) => {
9
+ if (!focusedItem)
10
+ return;
11
+ let newFocusedItem = null;
12
+ switch (event.key) {
13
+ case 'ArrowDown':
14
+ newFocusedItem = findNextItem(dataSource, focusedItem);
15
+ break;
16
+ case 'ArrowUp':
17
+ newFocusedItem = findPreviousItem(dataSource, focusedItem);
18
+ break;
19
+ case '+':
20
+ if (!focusedItem.expanded) {
21
+ handleNodeToggle(focusedItem.key, false);
22
+ newFocusedItem = { ...focusedItem, expanded: true };
23
+ }
24
+ break;
25
+ case '-':
26
+ if (focusedItem.expanded) {
27
+ handleNodeToggle(focusedItem.key, false);
28
+ newFocusedItem = { ...focusedItem, expanded: false };
29
+ }
30
+ break;
31
+ // case ' ':
32
+ // allowMultipleSelection && handleCheckboxChange(focusedItem, !selectedItems.some(item => item.key === focusedItem.key));
33
+ // break;
34
+ // case '*':
35
+ // handleExpandAllNodes();
36
+ // break;
37
+ // case '/':
38
+ // handleCollapseAllNodes();
39
+ // break;
40
+ default:
41
+ break;
42
+ }
43
+ if (newFocusedItem)
44
+ onFocusedItemChanged?.(newFocusedItem);
45
+ };
46
+ window.addEventListener('keydown', handleKeyDown);
47
+ return () => {
48
+ window.removeEventListener('keydown', handleKeyDown);
49
+ };
50
+ }, [focusedItem, dataSource, onFocusedItemChanged]);
51
+ const findNextItem = (nodes, currentItem) => {
52
+ const flatList = flattenTree(nodes);
53
+ const currentIndex = flatList.findIndex(item => item.key === currentItem.key);
54
+ return flatList[currentIndex + 1] || null;
55
+ };
56
+ const findPreviousItem = (nodes, currentItem) => {
57
+ const flatList = flattenTree(nodes);
58
+ const currentIndex = flatList.findIndex(item => item.key === currentItem.key);
59
+ return flatList[currentIndex - 1] || null;
60
+ };
61
+ const flattenTree = (nodes) => {
62
+ let flatList = [];
63
+ nodes.forEach(node => {
64
+ if (!node.hidden) {
65
+ flatList.push(node);
66
+ if (node.expanded && node.items) {
67
+ flatList = flatList.concat(flattenTree(node.items));
68
+ }
69
+ }
70
+ });
71
+ return flatList;
72
+ };
73
+ const handleNodeToggle = async (key, ctrlKey) => {
74
+ const updateNodeRecursively = async (nodes) => {
75
+ const updatedNodes = await Promise.all(nodes.map(async (node) => {
76
+ if (node.key === key) {
77
+ if (node.expanded) {
78
+ const updatedNode = { ...node, expanded: false };
79
+ onNodeUpdate?.(updatedNode); // Update parent data
80
+ return updatedNode;
81
+ }
82
+ else {
83
+ let newItems = node.items;
84
+ if (ctrlKey || !node.isLoaded) {
85
+ newItems = await calculateItemsForNode?.(node);
86
+ const updatedNode = { ...node, expanded: true, items: newItems };
87
+ onNodeUpdate?.(updatedNode); // Update parent data
88
+ return updatedNode;
89
+ }
90
+ return { ...node, expanded: true, items: newItems };
91
+ }
92
+ }
93
+ if (node.items) {
94
+ const updatedItems = await updateNodeRecursively(node.items);
95
+ return { ...node, items: updatedItems };
96
+ }
97
+ return node;
98
+ }));
99
+ return updatedNodes;
100
+ };
101
+ updateNodeRecursively(dataSource).then(updatedData => {
102
+ onDataChanged?.(updatedData);
103
+ });
104
+ };
105
+ const handleNodeClick = (node, ctrlKey) => {
106
+ onFocusedItemChanged?.(node);
107
+ handleNodeToggle(node.key, ctrlKey);
108
+ };
109
+ const handleCheckboxChange = (node, checked) => {
110
+ let newSelectedItems;
111
+ if (checked) {
112
+ if (node.isContainer) {
113
+ newSelectedItems = [...selectedItems, ...flattenTree(node.items || [])];
114
+ }
115
+ else if (!selectedItems.some(item => item.key === node.key)) {
116
+ newSelectedItems = [...selectedItems, node];
117
+ }
118
+ else {
119
+ newSelectedItems = selectedItems;
120
+ }
121
+ }
122
+ else if (node.isContainer) {
123
+ const childKeys = flattenTree(node.items || []).map(item => item.key);
124
+ newSelectedItems = selectedItems.filter(item => !childKeys.includes(item.key));
125
+ }
126
+ else {
127
+ newSelectedItems = selectedItems.filter(item => item.key !== node.key);
128
+ }
129
+ onSelectionChanged?.(newSelectedItems);
130
+ };
131
+ // const handleExpandAllNodes = () => {
132
+ // const expandAll = (nodes: T[]): T[] => {
133
+ // return nodes.map(node => ({
134
+ // ...node,
135
+ // expanded: true,
136
+ // items: node.items ? expandAll(node.items as T[]) : node.items
137
+ // }));
138
+ // };
139
+ // setTreeData(prevData => expandAll(prevData));
140
+ // };
141
+ // const handleCollapseAllNodes = () => {
142
+ // const collapseAll = (nodes: T[]): T[] => {
143
+ // return nodes.map(node => ({
144
+ // ...node,
145
+ // expanded: false,
146
+ // items: node.items ? collapseAll(node.items as T[]) : node.items
147
+ // }));
148
+ // };
149
+ // setTreeData(prevData => collapseAll(prevData));
150
+ // };
151
+ const isIndeterminate = (node) => {
152
+ if (!node.isContainer || !node.items)
153
+ return false;
154
+ const childKeys = flattenTree(node.items).map(item => item.key);
155
+ const selectedChildKeys = selectedItems.map(item => item.key);
156
+ const selectedCount = childKeys.filter(key => selectedChildKeys.includes(key)).length;
157
+ return selectedCount > 0 && selectedCount < childKeys.length;
158
+ };
159
+ const isFullySelected = (node) => {
160
+ if (!node.isContainer || !node.items)
161
+ return false;
162
+ const childKeys = flattenTree(node.items).map(item => item.key);
163
+ const selectedChildKeys = selectedItems.map(item => item.key);
164
+ return childKeys.every(key => selectedChildKeys.includes(key));
165
+ };
166
+ const hasVisibleItems = (node) => {
167
+ if (!node.items)
168
+ return false;
169
+ if (node.items.length <= 0)
170
+ return false;
171
+ return node.items.filter(o => !o.hidden).length > 0;
172
+ };
173
+ const renderTree = useCallback((nodes) => {
174
+ return nodes.map(node => !node.hidden && (_jsxs("div", { style: { width: '100%', height: '100%' }, children: [_jsxs(StyledTreeNode, { "$isSelected": node.key === focusedItem?.key, children: [_jsx("div", { style: { display: 'flex', alignItems: 'center', height: '18px', width: '18px' }, onClick: (e) => { handleNodeToggle(node.key, e.ctrlKey); }, children: hasVisibleItems(node)
175
+ ? node.expanded
176
+ ? _jsx(IconChevronDown, { cursor: 'pointer' })
177
+ : _jsx(IconChevronRight, { cursor: 'pointer' })
178
+ : _jsx("div", { style: { height: '18px', width: '18px' } }) }), allowMultipleSelection && (_jsx("input", { type: "checkbox", checked: isFullySelected(node) || selectedItems.some(item => item.key === node.key), onChange: (e) => handleCheckboxChange(node, e.target.checked), onClick: (e) => e.stopPropagation(), ref: input => {
179
+ if (input) {
180
+ input.indeterminate = isIndeterminate(node);
181
+ }
182
+ } })), _jsx("div", { style: { display: 'flex', alignItems: 'center', width: '100%', height: '100%' }, onClick: () => { onFocusedItemChanged?.(node); }, children: itemRender(node) })] }), node.expanded && node.items && (_jsx("div", { style: { paddingLeft: 20, width: '100%' }, children: renderTree(node.items) }))] }, node.key)));
183
+ }, [handleNodeClick, handleNodeToggle, handleCheckboxChange, focusedItem, selectedItems, allowMultipleSelection]);
184
+ return (_jsx("div", { style: { height: '100%', width: '100%', overflowY: 'auto', padding: '2px 5px 2px 2px' }, children: renderTree(dataSource) }));
185
+ };
186
+ export default TMTreeView;
187
+ export const StyledTreeNode = styled.div `
188
+ display: flex;
189
+ flex-direction: row;
190
+ width: 100%;
191
+ height: 25px;
192
+ gap: 5px;
193
+ align-items: center;
194
+ background: ${(props) => props.$isSelected ? 'oklch(from var(--dx-color-primary) l c h / .2) !important' : 'transparent'};
195
+
196
+ /* &:hover {
197
+ background: ${() => `${TMColors.primaryColor}33`};
198
+ } */
199
+ `;
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import { BlogPost, HomeBlogPost, IDCount, UserDescriptor, WorkingGroupDescriptor } from "@topconsultnpm/sdk-ts-beta";
3
+ import { FileItem } from '../base/TMFileManager';
4
+ interface TMBlogsProps {
5
+ /** Component Identifier */
6
+ id: string;
7
+ /** An array of blog posts or home blog posts */
8
+ allData: Array<BlogPost | HomeBlogPost>;
9
+ /** Optional flag to show extended attachments */
10
+ showExtendedAttachments?: boolean;
11
+ /** Optional view mode for displaying blog posts ('thumbnails' or 'details') */
12
+ viewMode?: 'thumbnails' | 'details';
13
+ /** Optional flag to automatically scroll to the bottom of the list */
14
+ scrollToBottom?: boolean;
15
+ /** Optional height of the component (CSS value) */
16
+ height?: string;
17
+ /** Optional width of the component (CSS value) */
18
+ width?: string;
19
+ /** Optional header configuration object */
20
+ header?: {
21
+ /** Flag to display the view mode toggle */
22
+ showViewMode: boolean;
23
+ /** Flag to display filter options */
24
+ showFilters: boolean;
25
+ /** Flag to display the search bar */
26
+ showSearchBar: boolean;
27
+ /** Flag to display a dropdown menu for selecting posts */
28
+ showPostsDropDown: boolean;
29
+ };
30
+ /** Optional flag to show an icon in the component */
31
+ showIconHeader?: boolean;
32
+ /** Optional color for customizing the appearance */
33
+ color?: string;
34
+ /** Optional file system tree structure */
35
+ treeFs?: FileItem;
36
+ /** Optional map storing the latest draft information, where the key is the draft ID */
37
+ draftLatestInfoMap?: Map<number, {
38
+ latestVersion: number;
39
+ folderId: number;
40
+ folderName: string;
41
+ fileExt: string;
42
+ fileSize: string;
43
+ }>;
44
+ /** Optional map storing the archived document information */
45
+ archivedDocumentMap?: Map<number, {
46
+ tid: number;
47
+ did: number;
48
+ fileExt: string;
49
+ fileSize: string;
50
+ }>;
51
+ /** Optional callback function to update the list of visualized blog posts */
52
+ updateVisualizedBlogCallback?: (blogPosts: Array<BlogPost | HomeBlogPost>) => void;
53
+ /** Optional callback to handle clicks on attachment folder files */
54
+ handleClickAttachmentFolderFileCallback?: (folderId: number, draftId: number) => void;
55
+ /** Optional callback to handle navigation to working groups */
56
+ handleNavigateToWGs?: (selectedWorkingGroupId: number) => void;
57
+ /** Optional boolean to control the visibility of an ID */
58
+ showId?: boolean;
59
+ /** Optional setter function to update the visibility state of an ID */
60
+ setShowId?: React.Dispatch<React.SetStateAction<boolean>>;
61
+ /** Optional currect working group */
62
+ currentWorkingGroup?: WorkingGroupDescriptor;
63
+ /** Optional context menu params */
64
+ contextMenuParams?: {
65
+ isShowHideFilterEnabled: boolean;
66
+ isShowHideIDEnaled: boolean;
67
+ isCommentEnabled: boolean;
68
+ isDeleteEnabled: boolean;
69
+ isRestoreEnabled: boolean;
70
+ isRefreshEnabled: boolean;
71
+ isCreateContextualTask: boolean;
72
+ };
73
+ refreshCallback?: () => void;
74
+ /** An array of partecipants */
75
+ participants?: Array<UserDescriptor>;
76
+ /** An array of new blog posts ID */
77
+ newPosts?: Array<IDCount>;
78
+ /** Show Comment Form Callback */
79
+ showCommentFormCallback?: () => void;
80
+ /** Show Task Form Callback */
81
+ showTaskFormCallback?: () => void;
82
+ }
83
+ declare const TMBlogs: (props: TMBlogsProps) => import("react/jsx-runtime").JSX.Element;
84
+ export default TMBlogs;