@centreon/ui 24.4.1-MON-38245-ba-tree-widget.5 → 24.4.1-MON-38194-widgets-display-optimizations.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "24.4.1-MON-38245-ba-tree-widget.5",
3
+ "version": "24.4.1-MON-38194-widgets-display-optimizations.0",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -82,7 +82,7 @@
82
82
  "@vitejs/plugin-react": "^4.2.1",
83
83
  "@vitejs/plugin-react-swc": "^3.6.0",
84
84
  "axios-mock-adapter": "^1.22.0",
85
- "cypress": "^13.7.1",
85
+ "cypress": "^13.7.0",
86
86
  "identity-obj-proxy": "^3.0.0",
87
87
  "jest-transform-stub": "^2.0.0",
88
88
  "mochawesome": "^7.1.3",
@@ -114,20 +114,15 @@
114
114
  "@lexical/selection": "^0.12.6",
115
115
  "@lexical/utils": "^0.12.6",
116
116
  "@react-spring/web": "^9.7.3",
117
- "@visx/clip-path": "^3.3.0",
118
117
  "@visx/curve": "^2.1.0",
119
- "@visx/event": "^3.3.0",
120
118
  "@visx/group": "^3.3.0",
121
- "@visx/hierarchy": "^3.3.0",
122
119
  "@visx/legend": "^3.5.0",
123
120
  "@visx/pattern": "^3.3.0",
124
- "@visx/point": "^3.3.0",
125
121
  "@visx/scale": "^3.5.0",
126
- "@visx/shape": "^2.18.0",
122
+ "@visx/shape": "^2.12.2",
127
123
  "@visx/text": "^3.3.0",
128
124
  "@visx/threshold": "^2.12.2",
129
125
  "@visx/visx": "2.16.0",
130
- "@visx/zoom": "^3.3.0",
131
126
  "anylogger": "^1.0.11",
132
127
  "d3-array": "3.2.4",
133
128
  "humanize-duration": "^3.31.0",
@@ -6,4 +6,3 @@ export { Text as GraphText } from './Text';
6
6
  export { HeatMap } from './HeatMap';
7
7
  export { BarStack } from './BarStack';
8
8
  export { PieChart } from './PieChart';
9
- export * from './Tree';
@@ -13,7 +13,7 @@ const useStyles = makeStyles()((theme) => ({
13
13
  paddingLeft: theme.spacing(2),
14
14
  paddingRight: theme.spacing(2)
15
15
  },
16
- fontSize: '14px',
16
+ fontSize: theme.typography.button.fontSize,
17
17
  height: 'unset',
18
18
  lineHeight: '22px'
19
19
  },
@@ -36,7 +36,7 @@ const useStyles = makeStyles()((theme) => ({
36
36
  color: theme.palette.primary.main
37
37
  },
38
38
 
39
- textWrap: 'noWrap',
39
+ textWrap: 'nowrap',
40
40
  transition: 'unset'
41
41
  }
42
42
  }));
@@ -11,4 +11,3 @@ export * from './ItemComposition';
11
11
  export * from './Avatar';
12
12
  export * from './CollapsibleItem';
13
13
  export * from './Inputs';
14
- export { default as Zoom } from './Zoom/Zoom';
@@ -1,88 +0,0 @@
1
- import { useState } from 'react';
2
-
3
- import { HierarchyPointNode } from '@visx/hierarchy/lib/types';
4
- import { Group } from '@visx/group';
5
- import { gt, isNil, pluck } from 'ramda';
6
-
7
- import { BaseProp, Node, TreeProps } from './models';
8
-
9
- interface Props<TData> extends Pick<TreeProps<TData>, 'children'> {
10
- descendants: Array<HierarchyPointNode<Node<TData>>>;
11
- expandCollapseNode: (targetNode: Node<TData>) => void;
12
- getExpanded: (d: Node<TData>) => Array<Node<TData>> | undefined;
13
- nodeSize: {
14
- height: number;
15
- width: number;
16
- };
17
- }
18
-
19
- const DescendantNodes = <TData extends BaseProp>({
20
- descendants,
21
- children,
22
- expandCollapseNode,
23
- getExpanded,
24
- nodeSize
25
- }: Props<TData>): Array<JSX.Element> => {
26
- const [pressEventTimeStamp, setPressEventTimeStamp] = useState<number | null>(
27
- null
28
- );
29
-
30
- const mouseDown = (e: MouseEvent): void => {
31
- setPressEventTimeStamp(e.timeStamp);
32
- };
33
-
34
- const mouseUp =
35
- (callback) =>
36
- (e: MouseEvent): void => {
37
- if (isNil(pressEventTimeStamp)) {
38
- callback();
39
-
40
- return;
41
- }
42
-
43
- const diffTimeStamp = e.timeStamp - pressEventTimeStamp;
44
-
45
- if (gt(diffTimeStamp, 120)) {
46
- return;
47
- }
48
-
49
- callback();
50
- };
51
-
52
- return descendants.map((node) => {
53
- const top = node.x;
54
- const left = node.y;
55
- const ancestorIds = node
56
- .ancestors()
57
- .map((ancestor) => ancestor.data.data.id);
58
- const descendantIds = node
59
- .descendants()
60
- .map((ancestor) => ancestor.data.data.id);
61
-
62
- const key = `${node.data.data.id}-${node.data.data.name}-${ancestorIds.toString()}-${descendantIds.toString()}`;
63
-
64
- return (
65
- <Group key={key} left={left} top={top}>
66
- <foreignObject
67
- height={nodeSize.height}
68
- width={nodeSize.width}
69
- x={-nodeSize.width / 2}
70
- y={-nodeSize.height / 2}
71
- >
72
- {children({
73
- ancestors: pluck('data', node.ancestors()),
74
- depth: node.depth,
75
- expandCollapseNode,
76
- isExpanded: !!getExpanded(node.data),
77
- node: node.data,
78
- nodeSize,
79
- onMouseDown: mouseDown,
80
- onMouseUp: mouseUp
81
- })}
82
- </foreignObject>
83
- </Group>
84
- );
85
- });
86
- };
87
-
88
- export default DescendantNodes;
@@ -1,77 +0,0 @@
1
- import {
2
- LinkHorizontal,
3
- LinkHorizontalStep,
4
- LinkHorizontalLine
5
- } from '@visx/shape';
6
- import { HierarchyPointLink } from '@visx/hierarchy/lib/types';
7
- import { always, cond, equals, T } from 'ramda';
8
-
9
- import { useTheme } from '@mui/material';
10
-
11
- import { TreeProps, Node, BaseProp } from './models';
12
-
13
- interface Props<TData> extends Pick<TreeProps<TData>, 'treeLink'> {
14
- links: Array<HierarchyPointLink<Node<TData>>>;
15
- }
16
-
17
- const getLinkComponent = cond([
18
- [equals('line'), always(LinkHorizontalLine)],
19
- [equals('step'), always(LinkHorizontalStep)],
20
- [T, always(LinkHorizontal)]
21
- ]);
22
-
23
- const Links = <TData extends BaseProp>({
24
- links,
25
- treeLink
26
- }: Props<TData>): Array<JSX.Element> => {
27
- const theme = useTheme();
28
-
29
- return links.map((link) => {
30
- const ancestorIds = link.target
31
- .ancestors()
32
- .map((ancestor) => ancestor.data.data.id);
33
-
34
- const descendantIds = link.target
35
- .descendants()
36
- .map((ancestor) => ancestor.data.data.id);
37
-
38
- const LinkComponent = getLinkComponent(treeLink?.type);
39
-
40
- const key = `${link.source.data.data.id}-${link.source.data.data.name}-${ancestorIds}_${link.target.data.data.id}-${link.target.data.data.name}-${descendantIds}`;
41
-
42
- return (
43
- <LinkComponent
44
- data={link}
45
- data-testid={`${link.source.data.data.id}_to_${link.target.data.data.id}`}
46
- fill="none"
47
- key={key}
48
- stroke={
49
- treeLink?.getStroke?.({
50
- source: link.source.data.data,
51
- target: link.target.data.data
52
- }) || theme.palette.text.primary
53
- }
54
- strokeDasharray={
55
- treeLink?.getStrokeDasharray?.({
56
- source: link.source.data.data,
57
- target: link.target.data.data
58
- }) || '0'
59
- }
60
- strokeOpacity={
61
- treeLink?.getStrokeOpacity?.({
62
- source: link.source.data.data,
63
- target: link.target.data.data
64
- }) || 1
65
- }
66
- strokeWidth={
67
- treeLink?.getStrokeWidth?.({
68
- source: link.source.data.data,
69
- target: link.target.data.data
70
- }) || '2'
71
- }
72
- />
73
- );
74
- });
75
- };
76
-
77
- export default Links;
@@ -1,32 +0,0 @@
1
- import { useState } from 'react';
2
-
3
- import { ParentSize } from '../..';
4
-
5
- import { BaseProp, TreeProps } from './models';
6
- import { Tree } from './Tree';
7
-
8
- export const StandaloneTree = <TData extends BaseProp>({
9
- tree,
10
- ...props
11
- }: Omit<
12
- TreeProps<TData>,
13
- 'containerHeight' | 'containerWidth'
14
- >): JSX.Element => {
15
- const [currentTree, setTree] = useState(tree);
16
-
17
- return (
18
- <ParentSize>
19
- {({ width, height }) => (
20
- <svg height={height} width={width}>
21
- <Tree
22
- {...props}
23
- changeTree={setTree}
24
- containerHeight={height}
25
- containerWidth={width}
26
- tree={currentTree}
27
- />
28
- </svg>
29
- )}
30
- </ParentSize>
31
- );
32
- };
@@ -1,195 +0,0 @@
1
- import { equals } from 'ramda';
2
-
3
- import {
4
- ComplexData,
5
- complexData,
6
- SimpleData,
7
- simpleData
8
- } from './stories/datas';
9
- import { ComplexContent, SimpleContent } from './stories/contents';
10
-
11
- import { Node, StandaloneTree, TreeProps } from '.';
12
-
13
- const validateTree = (tree): void => {
14
- if (!tree.children) {
15
- cy.contains(tree.data.name).should('be.visible');
16
-
17
- return;
18
- }
19
-
20
- cy.contains(tree.data.name).should('be.visible');
21
- tree.children.forEach((child) => {
22
- validateTree(child);
23
- });
24
- };
25
-
26
- interface InitializeProps
27
- extends Pick<TreeProps<SimpleData | ComplexData>, 'treeLink' | 'children'> {
28
- data?: Node<SimpleData | ComplexData>;
29
- isDefaultExpanded?: (data: SimpleData | ComplexData) => boolean;
30
- }
31
-
32
- const initializeStandaloneTree = ({
33
- data = simpleData,
34
- isDefaultExpanded = undefined,
35
- treeLink,
36
- children = SimpleContent
37
- }: InitializeProps): void => {
38
- cy.mount({
39
- Component: (
40
- <div style={{ height: '99vh' }}>
41
- <StandaloneTree
42
- node={{ height: 70, isDefaultExpanded, width: 70 }}
43
- tree={data}
44
- treeLink={treeLink}
45
- >
46
- {children}
47
- </StandaloneTree>
48
- </div>
49
- )
50
- });
51
- };
52
-
53
- describe('Simple data tree', () => {
54
- it('displays the whole tree', () => {
55
- initializeStandaloneTree({});
56
-
57
- validateTree(simpleData);
58
-
59
- cy.makeSnapshot();
60
- });
61
-
62
- it("collapses a node's childrens when a node is clicked", () => {
63
- initializeStandaloneTree({});
64
-
65
- cy.contains(/^E$/).should('be.visible');
66
- cy.contains(/^E1$/).should('be.visible');
67
-
68
- cy.contains(/^C$/).click();
69
-
70
- cy.contains(/^E$/).should('not.exist');
71
- cy.contains(/^E1$/).should('not.exist');
72
-
73
- cy.makeSnapshot();
74
- });
75
-
76
- it("expands a node's childrens when a node is clicked", () => {
77
- initializeStandaloneTree({});
78
-
79
- cy.contains(/^A$/).click();
80
-
81
- cy.contains(/^A1$/).should('not.exist');
82
- cy.contains(/^A2$/).should('not.exist');
83
- cy.contains(/^A3$/).should('not.exist');
84
- cy.contains(/^C$/).should('not.exist');
85
-
86
- cy.contains(/^A$/).click();
87
-
88
- cy.contains(/^A1$/).should('be.visible');
89
- cy.contains(/^A2$/).should('be.visible');
90
- cy.contains(/^A3$/).should('be.visible');
91
- cy.contains(/^C$/).should('be.visible');
92
-
93
- cy.makeSnapshot();
94
- });
95
-
96
- it('cannot collapses a node when a leaf is clicked', () => {
97
- initializeStandaloneTree({});
98
-
99
- cy.contains(/^Z$/).click();
100
-
101
- cy.contains(/^Z$/).should('be.visible');
102
-
103
- cy.makeSnapshot();
104
- });
105
-
106
- it('expands nodes by default when a prop is set', () => {
107
- initializeStandaloneTree({
108
- isDefaultExpanded: (data: SimpleData) => equals('critical', data.status)
109
- });
110
-
111
- cy.contains(/^T$/).should('be.visible');
112
- cy.contains(/^A$/).should('be.visible');
113
- cy.contains(/^A3$/).should('be.visible');
114
- cy.contains(/^C$/).should('be.visible');
115
- cy.contains(/^E$/).should('be.visible');
116
- cy.contains(/^E1$/).should('be.visible');
117
-
118
- cy.contains(/^B1$/).should('not.exist');
119
- cy.contains(/^D1$/).should('not.exist');
120
-
121
- cy.makeSnapshot();
122
- });
123
-
124
- it('displays customized links when a prop is set', () => {
125
- initializeStandaloneTree({
126
- treeLink: {
127
- getStroke: ({ target }) => (target.status === 'ok' ? 'grey' : 'black'),
128
- getStrokeDasharray: ({ target }) =>
129
- target.status === 'ok' ? '5,5' : '0',
130
- getStrokeOpacity: ({ target }) => (target.status === 'ok' ? 0.8 : 1),
131
- getStrokeWidth: ({ target }) => (target.status === 'ok' ? 1 : 2)
132
- }
133
- });
134
-
135
- cy.contains(/^Z$/).should('be.visible');
136
-
137
- cy.makeSnapshot();
138
- });
139
- });
140
-
141
- describe('Complex data tree', () => {
142
- it('cannot collapse a node when a node is not clickable', () => {
143
- initializeStandaloneTree({
144
- children: ComplexContent,
145
- data: complexData
146
- });
147
-
148
- cy.contains('BA 3').should('be.visible');
149
-
150
- cy.contains('BA 2').click();
151
-
152
- cy.contains('BA 3').should('be.visible');
153
-
154
- cy.makeSnapshot();
155
- });
156
-
157
- it('collapses a node when a node is clickable', () => {
158
- initializeStandaloneTree({
159
- children: ComplexContent,
160
- data: complexData
161
- });
162
-
163
- cy.contains('BA 3').should('be.visible');
164
-
165
- cy.contains('2').click();
166
-
167
- cy.contains('BA 3').should('not.exist');
168
-
169
- cy.makeSnapshot();
170
- });
171
-
172
- it('displays the tree with step links when a prop is set', () => {
173
- initializeStandaloneTree({
174
- treeLink: {
175
- type: 'step'
176
- }
177
- });
178
-
179
- cy.contains('T').should('be.visible');
180
-
181
- cy.makeSnapshot();
182
- });
183
-
184
- it('displays the tree with line links when a prop is set', () => {
185
- initializeStandaloneTree({
186
- treeLink: {
187
- type: 'line'
188
- }
189
- });
190
-
191
- cy.contains('T').should('be.visible');
192
-
193
- cy.makeSnapshot();
194
- });
195
- });
@@ -1,160 +0,0 @@
1
- import { useState } from 'react';
2
-
3
- import { Meta, StoryObj } from '@storybook/react';
4
- import { equals, has } from 'ramda';
5
-
6
- import { Zoom } from '../../components';
7
-
8
- import {
9
- ComplexData,
10
- complexData,
11
- moreComplexData,
12
- SimpleData,
13
- simpleData
14
- } from './stories/datas';
15
- import { ComplexContent, SimpleContent } from './stories/contents';
16
-
17
- import { StandaloneTree, Tree, TreeProps } from '.';
18
-
19
- const meta: Meta<typeof StandaloneTree> = {
20
- component: StandaloneTree
21
- };
22
-
23
- export default meta;
24
- type Story = StoryObj<typeof StandaloneTree>;
25
-
26
- const StandaloneTreeTemplate = (args): JSX.Element => (
27
- <div style={{ height: '90vh', width: '100%' }}>
28
- <StandaloneTree<SimpleData> {...args} />
29
- </div>
30
- );
31
-
32
- const TreeWithZoom = <TData,>({
33
- tree,
34
- ...args
35
- }: TreeProps<TData>): JSX.Element => {
36
- const [currentTree, setTree] = useState(tree);
37
-
38
- return (
39
- <div style={{ height: '90vh', width: '100%' }}>
40
- <Zoom
41
- showMinimap
42
- labels={{
43
- clear: 'Clear'
44
- }}
45
- >
46
- {({ width, height }) => (
47
- <Tree<ComplexData>
48
- {...args}
49
- changeTree={setTree}
50
- containerHeight={height}
51
- containerWidth={width}
52
- tree={currentTree}
53
- />
54
- )}
55
- </Zoom>
56
- </div>
57
- );
58
- };
59
-
60
- export const DefaultStandaloneTree: Story = {
61
- args: {
62
- children: SimpleContent,
63
- node: {
64
- height: 90,
65
- width: 90
66
- },
67
- tree: simpleData
68
- },
69
- render: StandaloneTreeTemplate
70
- };
71
-
72
- export const WithDefaultExpandFilter: Story = {
73
- args: {
74
- children: SimpleContent,
75
- node: {
76
- height: 90,
77
- isDefaultExpanded: (data: SimpleData) => equals('critical', data.status),
78
- width: 90
79
- },
80
- tree: simpleData
81
- },
82
- render: StandaloneTreeTemplate
83
- };
84
-
85
- export const WithStepLink: Story = {
86
- args: {
87
- children: SimpleContent,
88
- node: {
89
- height: 90,
90
- width: 90
91
- },
92
- tree: simpleData,
93
- treeLink: {
94
- type: 'step'
95
- }
96
- },
97
- render: StandaloneTreeTemplate
98
- };
99
-
100
- export const WithCustomLinks: Story = {
101
- args: {
102
- children: SimpleContent,
103
- node: {
104
- height: 90,
105
- width: 90
106
- },
107
- tree: simpleData,
108
- treeLink: {
109
- getStroke: ({ target }) => (target.status === 'ok' ? 'grey' : 'black'),
110
- getStrokeDasharray: ({ target }) =>
111
- target.status === 'ok' ? '5,5' : '0',
112
- getStrokeOpacity: ({ target }) => (target.status === 'ok' ? 0.8 : 1),
113
- getStrokeWidth: ({ target }) => (target.status === 'ok' ? 1 : 2),
114
- type: 'line'
115
- }
116
- },
117
- render: StandaloneTreeTemplate
118
- };
119
-
120
- export const WithComplexData: Story = {
121
- args: {
122
- children: ComplexContent,
123
- node: {
124
- height: 90,
125
- isDefaultExpanded: (data: SimpleData) =>
126
- equals('critical', data.status) || !has('count', data),
127
- width: 90
128
- },
129
- tree: complexData,
130
- treeLink: {
131
- getStroke: ({ target }) => (target.status === 'ok' ? 'grey' : 'black'),
132
- getStrokeDasharray: ({ target }) =>
133
- target.status === 'ok' ? '5,5' : '0',
134
- getStrokeOpacity: ({ target }) => (target.status === 'ok' ? 0.8 : 1),
135
- getStrokeWidth: ({ target }) => (target.status === 'ok' ? 1 : 2)
136
- }
137
- },
138
- render: StandaloneTreeTemplate
139
- };
140
-
141
- export const treeWithZoom: Story = {
142
- args: {
143
- children: ComplexContent,
144
- node: {
145
- height: 90,
146
- isDefaultExpanded: (data: SimpleData) =>
147
- equals('critical', data.status) || !has('count', data),
148
- width: 90
149
- },
150
- tree: moreComplexData,
151
- treeLink: {
152
- getStroke: ({ target }) => (target.status === 'ok' ? 'grey' : 'black'),
153
- getStrokeDasharray: ({ target }) =>
154
- target.status === 'ok' ? '5,5' : '0',
155
- getStrokeOpacity: ({ target }) => (target.status === 'ok' ? 0.8 : 1),
156
- getStrokeWidth: ({ target }) => (target.status === 'ok' ? 1 : 2)
157
- }
158
- },
159
- render: TreeWithZoom
160
- };