@reltio/graph 1.4.1584 → 1.4.1586-mui5
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/index.ts +1 -0
- package/package.json +26 -9
- package/public/bundle.js +205 -0
- package/public/bundle.js.LICENSE.txt +88 -0
- package/public/package.json +29 -0
- package/scripts/build/index.js +20 -0
- package/src/__tests__/GraphView.test.tsx +25 -0
- package/src/components/CircleLayout/CircleLayout.tsx +76 -0
- package/src/components/CircleLayout/__tests__/CircleLayout.test.tsx +194 -0
- package/src/components/GotoButton/GotoButton.tsx +23 -0
- package/src/components/GotoButton/__tests__/GotoButton.test.tsx +33 -0
- package/src/components/GotoButton/styles.ts +15 -0
- package/src/components/GraphArea/GraphArea.tsx +113 -0
- package/src/components/GraphArea/__tests__/GraphArea.test.tsx +202 -0
- package/src/components/GraphArea/styles.ts +30 -0
- package/src/components/GraphLayoutSelector/GraphLayoutSelector.tsx +43 -0
- package/src/components/GraphLayoutSelector/__tests__/GraphLayoutSelector.spec.tsx +44 -0
- package/src/components/GraphLayoutSelector/styles.ts +15 -0
- package/src/components/GraphPerspectiveView/GraphPerspectiveView.tsx +58 -0
- package/src/components/GraphPerspectiveView/__tests__/GraphPerspectiveView.test.tsx +115 -0
- package/src/components/GraphPerspectiveView/__tests__/useGraphLoader.test.tsx +1519 -0
- package/src/components/GraphPerspectiveView/__tests__/useRelationshipTable.test.tsx +1003 -0
- package/src/components/GraphPerspectiveView/__tests__/useSelectedEntity.test.tsx +373 -0
- package/src/components/GraphPerspectiveView/styles.ts +34 -0
- package/src/components/GraphRightSidePanel/GraphRightSidePanel.tsx +27 -0
- package/src/components/GraphRightSidePanel/__tests__/GraphRightSidePanel.test.tsx +18 -0
- package/src/components/GraphRightSidePanel/icons/relationship-icon.svg +3 -0
- package/src/components/GraphRightSidePanel/styles.ts +8 -0
- package/src/components/GraphTypeSelector/GraphTypeSelector.tsx +56 -0
- package/src/components/GraphTypeSelector/__tests__/GraphTypeSelector.test.tsx +109 -0
- package/src/components/GraphTypeSelector/styles.ts +17 -0
- package/src/components/HierarchyLayout/HierarchyLayout.ts +102 -0
- package/src/components/HierarchyLayout/__tests__/HierarchyLayout.spec.tsx +241 -0
- package/src/components/HierarchyLayout/__tests__/buildHierarchy.spec.ts +130 -0
- package/src/components/HierarchyLayout/__tests__/calculations.spec.ts +230 -0
- package/src/components/HierarchyLayout/buildHierarchy.ts +109 -0
- package/src/components/HierarchyLayout/calculations.ts +86 -0
- package/src/components/RightPanelEntityDetails/RightPanelEntityDetails.tsx +33 -0
- package/src/components/RightPanelEntityDetails/__tests__/RightPanelEntityDetails.test.tsx +39 -0
- package/src/components/RightPanelEntityDetails/styles.ts +12 -0
- package/src/components/RightPanelProfileBand/RightPanelProfileBand.tsx +33 -0
- package/src/components/RightPanelProfileBand/__tests__/RightPanelProfileBand.test.tsx +67 -0
- package/src/components/RightPanelProfileBand/styles.ts +8 -0
- package/src/components/RightPanelRelationship/RightPanelRelationship.tsx +25 -0
- package/src/components/RightPanelRelationship/__tests__/RightPanelRelationship.test.tsx +18 -0
- package/src/components/RightPanelRelationship/components/CollapsibleTable/CollapsibleTable.tsx +100 -0
- package/src/components/RightPanelRelationship/components/CollapsibleTable/TableHead.tsx +38 -0
- package/src/components/RightPanelRelationship/components/CollapsibleTable/__tests__/CollapsibleTable.test.tsx +169 -0
- package/src/components/RightPanelRelationship/components/CollapsibleTable/__tests__/TableHead.test.tsx +107 -0
- package/src/components/RightPanelRelationship/components/CollapsibleTable/styles.ts +38 -0
- package/src/components/RightPanelRelationship/components/CollapsibleTable/types.ts +20 -0
- package/src/components/RightPanelRelationship/components/DeleteRelationDialog/DeleteRelationDialog.tsx +34 -0
- package/src/components/RightPanelRelationship/components/DeleteRelationDialog/__tests__/DeleteRelationDialog.test.tsx +46 -0
- package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/GraphAddRelationButton.tsx +43 -0
- package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/GraphAddRelationDialog.tsx +121 -0
- package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/__tests__/GraphAddRelationButton.test.tsx +80 -0
- package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/__tests__/GraphAddRelationDialog.test.tsx +262 -0
- package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/__tests__/mockdata.ts +75 -0
- package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/styles.ts +25 -0
- package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/useCreatableInOutRelationTypes.ts +13 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/RelationshipTable.tsx +126 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/__tests__/RelationshipTable.test.tsx +176 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/ControlsCellRenderer.tsx +59 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/DefaultCellRenderer.tsx +29 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/ExpandedRowRenderer.tsx +94 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/HeadCellRenderer.tsx +34 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/ProfileCellRenderer.tsx +41 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/ControlsCellRenderer.test.tsx +80 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/DefaultCellRenderer.test.tsx +47 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/ExpandedRowRenderer.test.tsx +166 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/HeadCellRenderer.test.tsx +23 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/ProfileCellRenderer.test.tsx +47 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/components/DeleteRelationButton.tsx +32 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/components/__tests__/DeleteRelationButton.test.tsx +28 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/styles.ts +113 -0
- package/src/components/RightPanelRelationship/components/RelationshipTable/styles.ts +36 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsFilters.tsx +41 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsFiltersDialog/RelationshipsFiltersDialog.tsx +91 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsFiltersDialog/__tests__/RelationshipsFilterDialog.test.tsx +192 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsFiltersDialog/styles.ts +34 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsSearchTextField/RelationshipsSearchTextField.tsx +31 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsSearchTextField/__tests__/RelationshipsSearchTextField.test.tsx +43 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsSearchTextField/styles.ts +17 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/__tests__/RelationshipsFilters.test.tsx +76 -0
- package/src/components/RightPanelRelationship/components/RelationshipsFilters/styles.ts +19 -0
- package/src/components/RightPanelRelationship/styles.ts +20 -0
- package/src/components/SigmaCustomRenderers/SigmaCustomRenderersContainer.tsx +16 -0
- package/src/components/SigmaGraphContainer/SigmaGraphContainer.tsx +55 -0
- package/src/components/SigmaGraphContainer/__tests__/SigmaGraphContainer.test.tsx +25 -0
- package/src/components/SigmaGraphResizer/SigmaGraphResizer.tsx +13 -0
- package/src/components/SigmaGraphResizer/__tests__/SigmaGraphResizer.test.tsx +28 -0
- package/src/components/TreeLayout/TreeLayout.tsx +33 -0
- package/src/components/TreeLayout/__tests__/TreeLayout.test.tsx +42 -0
- package/src/components/TreeLayout/styles.ts +10 -0
- package/src/components/ZoomSlider/ZoomSlider.tsx +90 -0
- package/src/components/ZoomSlider/__tests__/ZoomSlider.test.tsx +84 -0
- package/src/components/ZoomSlider/styles.ts +57 -0
- package/src/constants/index.ts +1 -0
- package/src/contexts/GraphStateContext.tsx +19 -0
- package/src/contexts/SigmaCustomRenderersContext.ts +20 -0
- package/src/helpers/relationsHelpers.ts +9 -0
- package/src/hooks/__tests__/useGraphLayout.test.tsx +825 -0
- package/src/hooks/__tests__/useGraphLayoutSelector.test.tsx +19 -0
- package/src/hooks/__tests__/useSelfRelationLoopsRenderer.test.ts +198 -0
- package/src/hooks/__tests__/useSigmaCustomRenderers.test.ts +273 -0
- package/src/hooks/__tests__/useTooltipRenderer.test.ts +289 -0
- package/src/hooks/useGraphLayout.ts +308 -0
- package/src/hooks/useGraphLayoutSelector.ts +19 -0
- package/src/hooks/useGraphLoader.ts +279 -0
- package/src/hooks/useGraphRightSidePanelElements.tsx +36 -0
- package/src/hooks/useGraphState.ts +40 -0
- package/src/hooks/useGraphType.ts +32 -0
- package/src/hooks/useRelationshipTable.ts +212 -0
- package/src/hooks/useRelationshipTableFilters.ts +43 -0
- package/src/hooks/useSelectedEntity.ts +89 -0
- package/src/hooks/useSelfRelationLoopsRenderer.ts +52 -0
- package/src/hooks/useSigmaCustomRenderers.ts +112 -0
- package/src/hooks/useTooltipRenderer.ts +80 -0
- package/src/index.tsx +37 -0
- package/src/rendering/canvas/__tests__/hover.spec.ts +31 -0
- package/src/rendering/canvas/__tests__/label.spec.ts +64 -0
- package/src/rendering/canvas/__tests__/nodeBackground.spec.ts +99 -0
- package/src/rendering/canvas/__tests__/selfRelationLoop.spec.ts +88 -0
- package/src/rendering/canvas/__tests__/tooltip.spec.ts +33 -0
- package/src/rendering/canvas/hover.ts +13 -0
- package/src/rendering/canvas/label.ts +33 -0
- package/src/rendering/canvas/nodeBackground.ts +61 -0
- package/src/rendering/canvas/selfRelationLoop.ts +108 -0
- package/src/rendering/canvas/tooltip.ts +38 -0
- package/src/rendering/icons/collapseIcon.inline.svg.ts +6 -0
- package/src/rendering/icons/expandIcon.inline.svg.ts +5 -0
- package/src/rendering/icons/no_photo.inline.svg.ts +13 -0
- package/src/rendering/webgl/edge.arrowHead.ts +87 -0
- package/src/rendering/webgl/edge.clamped.ts +246 -0
- package/src/rendering/webgl/edge.reversedArrowHead.ts +14 -0
- package/src/rendering/webgl/helpers/__tests__/imageHelper.spec.ts +36 -0
- package/src/rendering/webgl/helpers/imageHelper.ts +13 -0
- package/src/rendering/webgl/image.ts +115 -0
- package/src/rendering/webgl/node.border.ts +78 -0
- package/src/rendering/webgl/node.buttons.ts +241 -0
- package/src/rendering/webgl/node.image.ts +169 -0
- package/src/rendering/webgl/shaders/edge.clamped.vert.glsl.ts +55 -0
- package/src/rendering/webgl/shaders/node.border.frag.glsl.ts +30 -0
- package/src/rendering/webgl/shaders/node.border.vert.glsl.ts +37 -0
- package/src/rendering/webgl/shaders/node.buttons.frag.glsl.ts +32 -0
- package/src/rendering/webgl/shaders/node.buttons.vert.glsl.ts +49 -0
- package/src/rendering/webgl/shaders/node.image.frag.glsl.ts +46 -0
- package/src/rendering/webgl/shaders/node.image.vert.glsl.ts +42 -0
- package/src/types/graphDataTypes.ts +143 -0
- package/src/types/sigmaCustomRenderersTypes.ts +13 -0
- package/src/utils/__tests__/graph.spec.ts +152 -0
- package/src/utils/__tests__/graphLayout.spec.ts +125 -0
- package/src/utils/__tests__/hopsData.spec.ts +456 -0
- package/src/utils/__tests__/processResponceToGraph.spec.ts +165 -0
- package/src/utils/graph.ts +83 -0
- package/src/utils/graphLayout.ts +70 -0
- package/src/utils/hopsData.ts +198 -0
- package/src/utils/processResponseToGraph.ts +32 -0
- package/tsconfig.json +4 -0
- package/webpack.config.js +10 -0
- package/bundle.js +0 -2
- package/bundle.js.LICENSE.txt +0 -54
- /package/{5271a9e7b6651c852e93.png → public/5271a9e7b6651c852e93.png} +0 -0
- /package/{main.css → public/main.css} +0 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import {GraphLayout} from '@reltio/mdm-sdk';
|
|
2
|
+
import {
|
|
3
|
+
calculateXPos,
|
|
4
|
+
calculateYPos,
|
|
5
|
+
getAngleOfRotation,
|
|
6
|
+
getMaxLvlSize,
|
|
7
|
+
getMaxQuantityNodesOnOneLvl,
|
|
8
|
+
isSimpleGraph
|
|
9
|
+
} from '../calculations';
|
|
10
|
+
|
|
11
|
+
describe('calculations behavior', () => {
|
|
12
|
+
it('calculateXPos should work correctly', () => {
|
|
13
|
+
expect(
|
|
14
|
+
calculateXPos({
|
|
15
|
+
quantityAtLvl: 10,
|
|
16
|
+
posAtLvl: 2,
|
|
17
|
+
max: 10,
|
|
18
|
+
isEvenRow: true,
|
|
19
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
20
|
+
shouldUseCheckboardPattern: true
|
|
21
|
+
})
|
|
22
|
+
).toBe(25);
|
|
23
|
+
|
|
24
|
+
expect(
|
|
25
|
+
calculateXPos({
|
|
26
|
+
quantityAtLvl: 10,
|
|
27
|
+
posAtLvl: 4,
|
|
28
|
+
max: 10,
|
|
29
|
+
isEvenRow: true,
|
|
30
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
31
|
+
shouldUseCheckboardPattern: true
|
|
32
|
+
})
|
|
33
|
+
).toBe(45);
|
|
34
|
+
|
|
35
|
+
expect(
|
|
36
|
+
calculateXPos({
|
|
37
|
+
quantityAtLvl: 10,
|
|
38
|
+
posAtLvl: 2,
|
|
39
|
+
max: 10,
|
|
40
|
+
isEvenRow: false,
|
|
41
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
42
|
+
shouldUseCheckboardPattern: true
|
|
43
|
+
})
|
|
44
|
+
).toBe(20);
|
|
45
|
+
|
|
46
|
+
expect(
|
|
47
|
+
calculateXPos({
|
|
48
|
+
quantityAtLvl: 10,
|
|
49
|
+
posAtLvl: 5,
|
|
50
|
+
max: 10,
|
|
51
|
+
isEvenRow: true,
|
|
52
|
+
layout: GraphLayout.VERTICAL_TB,
|
|
53
|
+
shouldUseCheckboardPattern: true
|
|
54
|
+
})
|
|
55
|
+
).toBe(50);
|
|
56
|
+
|
|
57
|
+
expect(
|
|
58
|
+
calculateXPos({
|
|
59
|
+
quantityAtLvl: 10,
|
|
60
|
+
posAtLvl: 7,
|
|
61
|
+
max: 10,
|
|
62
|
+
isEvenRow: true,
|
|
63
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
64
|
+
shouldUseCheckboardPattern: false
|
|
65
|
+
})
|
|
66
|
+
).toBe(70);
|
|
67
|
+
|
|
68
|
+
expect(
|
|
69
|
+
calculateXPos({
|
|
70
|
+
quantityAtLvl: 1,
|
|
71
|
+
posAtLvl: 0,
|
|
72
|
+
max: 10,
|
|
73
|
+
isEvenRow: true,
|
|
74
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
75
|
+
shouldUseCheckboardPattern: true
|
|
76
|
+
})
|
|
77
|
+
).toBe(45);
|
|
78
|
+
|
|
79
|
+
expect(
|
|
80
|
+
calculateXPos({
|
|
81
|
+
quantityAtLvl: 1,
|
|
82
|
+
posAtLvl: 0,
|
|
83
|
+
max: 5,
|
|
84
|
+
isEvenRow: true,
|
|
85
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
86
|
+
shouldUseCheckboardPattern: true
|
|
87
|
+
})
|
|
88
|
+
).toBe(20);
|
|
89
|
+
|
|
90
|
+
expect(
|
|
91
|
+
calculateXPos({
|
|
92
|
+
quantityAtLvl: 5,
|
|
93
|
+
posAtLvl: 3,
|
|
94
|
+
max: 10,
|
|
95
|
+
isEvenRow: true,
|
|
96
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
97
|
+
shouldUseCheckboardPattern: true
|
|
98
|
+
})
|
|
99
|
+
).toBe(60);
|
|
100
|
+
|
|
101
|
+
expect(
|
|
102
|
+
calculateXPos({
|
|
103
|
+
quantityAtLvl: 4,
|
|
104
|
+
posAtLvl: 2,
|
|
105
|
+
max: 8,
|
|
106
|
+
isEvenRow: true,
|
|
107
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
108
|
+
shouldUseCheckboardPattern: true
|
|
109
|
+
})
|
|
110
|
+
).toBe(42);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('calculateYPos should work correctly', () => {
|
|
114
|
+
expect(
|
|
115
|
+
calculateYPos({
|
|
116
|
+
quantityAtLvl: 10,
|
|
117
|
+
rowNumber: 5,
|
|
118
|
+
isEvenItem: true,
|
|
119
|
+
layout: GraphLayout.VERTICAL_TB,
|
|
120
|
+
shouldUseCheckboardPattern: true
|
|
121
|
+
})
|
|
122
|
+
).toBe(55);
|
|
123
|
+
|
|
124
|
+
expect(
|
|
125
|
+
calculateYPos({
|
|
126
|
+
quantityAtLvl: 10,
|
|
127
|
+
rowNumber: 8,
|
|
128
|
+
isEvenItem: true,
|
|
129
|
+
layout: GraphLayout.VERTICAL_TB,
|
|
130
|
+
shouldUseCheckboardPattern: true
|
|
131
|
+
})
|
|
132
|
+
).toBe(85);
|
|
133
|
+
|
|
134
|
+
expect(
|
|
135
|
+
calculateYPos({
|
|
136
|
+
quantityAtLvl: 10,
|
|
137
|
+
rowNumber: 5,
|
|
138
|
+
isEvenItem: true,
|
|
139
|
+
layout: GraphLayout.VERTICAL_TB,
|
|
140
|
+
shouldUseCheckboardPattern: false
|
|
141
|
+
})
|
|
142
|
+
).toBe(50);
|
|
143
|
+
|
|
144
|
+
expect(
|
|
145
|
+
calculateYPos({
|
|
146
|
+
quantityAtLvl: 10,
|
|
147
|
+
rowNumber: 1,
|
|
148
|
+
isEvenItem: true,
|
|
149
|
+
layout: GraphLayout.HORIZONTAL_LR,
|
|
150
|
+
shouldUseCheckboardPattern: true
|
|
151
|
+
})
|
|
152
|
+
).toBe(10);
|
|
153
|
+
|
|
154
|
+
expect(
|
|
155
|
+
calculateYPos({
|
|
156
|
+
quantityAtLvl: 10,
|
|
157
|
+
rowNumber: 3,
|
|
158
|
+
isEvenItem: false,
|
|
159
|
+
layout: GraphLayout.VERTICAL_TB,
|
|
160
|
+
shouldUseCheckboardPattern: true
|
|
161
|
+
})
|
|
162
|
+
).toBe(30);
|
|
163
|
+
|
|
164
|
+
expect(
|
|
165
|
+
calculateYPos({
|
|
166
|
+
quantityAtLvl: 1,
|
|
167
|
+
rowNumber: 0,
|
|
168
|
+
isEvenItem: true,
|
|
169
|
+
layout: GraphLayout.VERTICAL_TB,
|
|
170
|
+
shouldUseCheckboardPattern: true
|
|
171
|
+
})
|
|
172
|
+
).toBe(0);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe('getAngleOfRotation', () => {
|
|
176
|
+
it('should return correctly angle for Horizontal layout', () => {
|
|
177
|
+
expect(getAngleOfRotation(GraphLayout.HORIZONTAL_LR)).toBe(270);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should return correctly angle for Vertical layout', () => {
|
|
181
|
+
expect(getAngleOfRotation(GraphLayout.VERTICAL_TB)).toBe(180);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('getMaxLvlSize', () => {
|
|
186
|
+
it('should return max level size correctly', () => {
|
|
187
|
+
expect(getMaxLvlSize([['node1'], ['node2', 'node3', 'node4'], ['node5', 'node6']])).toBe(3);
|
|
188
|
+
expect(getMaxLvlSize([['node1'], ['node2', 'node3'], ['node4', 'node5']])).toBe(2);
|
|
189
|
+
expect(getMaxLvlSize([['node1'], ['node2', 'node3'], ['node4', 'node5', 'node6', 'node7']])).toBe(4);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('isSimpleGraph', () => {
|
|
194
|
+
it('should return true for lengths shorter than 100', () => {
|
|
195
|
+
expect(isSimpleGraph(50)).toBe(true);
|
|
196
|
+
expect(isSimpleGraph(1)).toBe(true);
|
|
197
|
+
expect(isSimpleGraph(80)).toBe(true);
|
|
198
|
+
expect(isSimpleGraph(99)).toBe(true);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should return false for lengths longer than 100', () => {
|
|
202
|
+
expect(isSimpleGraph(100)).toBe(false);
|
|
203
|
+
expect(isSimpleGraph(150)).toBe(false);
|
|
204
|
+
expect(isSimpleGraph(200)).toBe(false);
|
|
205
|
+
expect(isSimpleGraph(1000)).toBe(false);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe('getMaxQuantityNodesOnOneLvl', () => {
|
|
210
|
+
it('should return default max quantity nodes at level for nodesLength shorter than 100', () => {
|
|
211
|
+
expect(getMaxQuantityNodesOnOneLvl(10, GraphLayout.HORIZONTAL_LR)).toBe(10);
|
|
212
|
+
expect(getMaxQuantityNodesOnOneLvl(50, GraphLayout.VERTICAL_TB)).toBe(10);
|
|
213
|
+
expect(getMaxQuantityNodesOnOneLvl(80, GraphLayout.HORIZONTAL_LR)).toBe(10);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should calculate max quantity nodes at level for nodesLength longer than 100 and Horizontal layout', () => {
|
|
217
|
+
expect(getMaxQuantityNodesOnOneLvl(120, GraphLayout.HORIZONTAL_LR)).toBe(8);
|
|
218
|
+
expect(getMaxQuantityNodesOnOneLvl(200, GraphLayout.HORIZONTAL_LR)).toBe(10);
|
|
219
|
+
expect(getMaxQuantityNodesOnOneLvl(500, GraphLayout.HORIZONTAL_LR)).toBe(16);
|
|
220
|
+
expect(getMaxQuantityNodesOnOneLvl(1000, GraphLayout.HORIZONTAL_LR)).toBe(22);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('should calculate max quantity nodes at level for nodesLength longer than 100 and Vertical layout', () => {
|
|
224
|
+
expect(getMaxQuantityNodesOnOneLvl(120, GraphLayout.VERTICAL_TB)).toBe(16);
|
|
225
|
+
expect(getMaxQuantityNodesOnOneLvl(200, GraphLayout.VERTICAL_TB)).toBe(21);
|
|
226
|
+
expect(getMaxQuantityNodesOnOneLvl(500, GraphLayout.VERTICAL_TB)).toBe(34);
|
|
227
|
+
expect(getMaxQuantityNodesOnOneLvl(1000, GraphLayout.VERTICAL_TB)).toBe(47);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import Graph from 'graphology';
|
|
2
|
+
import {GraphologyGraphData, Node, Edge, NodesHierarchy} from '../../types/graphDataTypes';
|
|
3
|
+
|
|
4
|
+
const getFirstLvlNodes = (edgesWithoutLoops: Edge[], nodes: Node[], selectedNode: string): Set<string> => {
|
|
5
|
+
const firstLvlNodesIds = new Set<string>();
|
|
6
|
+
nodes.forEach((node) => {
|
|
7
|
+
if (!edgesWithoutLoops.some((edge) => edge.to === node.id)) {
|
|
8
|
+
firstLvlNodesIds.add(node.id);
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
if (!firstLvlNodesIds.size) {
|
|
12
|
+
firstLvlNodesIds.add(selectedNode);
|
|
13
|
+
}
|
|
14
|
+
return firstLvlNodesIds;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const canFindChildNodes = (nodesIds: Set<string>, edgesWithoutLoops: Edge[], processedNodes) => {
|
|
18
|
+
const children = new Set<string>();
|
|
19
|
+
nodesIds.forEach((nodeId) => {
|
|
20
|
+
edgesWithoutLoops.forEach((edge) => {
|
|
21
|
+
if (edge.from === nodeId && !processedNodes.has(edge.to)) {
|
|
22
|
+
children.add(edge.to);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
return !!children.size;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const findChildNodeIds = (
|
|
30
|
+
parentNodes: Set<string>,
|
|
31
|
+
nodesArr: NodesHierarchy,
|
|
32
|
+
processedNodes: Set<string>,
|
|
33
|
+
edgesWithoutLoops: Edge[]
|
|
34
|
+
): NodesHierarchy => {
|
|
35
|
+
const currentLvlNodeIds = new Set<string>();
|
|
36
|
+
if (!nodesArr.length) {
|
|
37
|
+
nodesArr.push(Array.from(parentNodes));
|
|
38
|
+
}
|
|
39
|
+
parentNodes.forEach((nodeId) => {
|
|
40
|
+
processedNodes.add(nodeId);
|
|
41
|
+
edgesWithoutLoops.forEach((edge) => {
|
|
42
|
+
if (edge.from === nodeId && !parentNodes.has(edge.to) && !processedNodes.has(edge.to)) {
|
|
43
|
+
currentLvlNodeIds.add(edge.to);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
if (currentLvlNodeIds.size) {
|
|
48
|
+
nodesArr.push(Array.from(currentLvlNodeIds));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (canFindChildNodes(currentLvlNodeIds, edgesWithoutLoops, processedNodes)) {
|
|
52
|
+
return findChildNodeIds(currentLvlNodeIds, nodesArr, processedNodes, edgesWithoutLoops);
|
|
53
|
+
} else return nodesArr;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const splitLongLevels = (
|
|
57
|
+
nodes: string[],
|
|
58
|
+
finalHierarchyNodesArr: NodesHierarchy,
|
|
59
|
+
nodesHierarchy: NodesHierarchy,
|
|
60
|
+
level: number,
|
|
61
|
+
maxQuantityNodesOnOneLvl: number
|
|
62
|
+
): NodesHierarchy => {
|
|
63
|
+
if (nodes.length <= maxQuantityNodesOnOneLvl) {
|
|
64
|
+
finalHierarchyNodesArr[level] = [...nodes];
|
|
65
|
+
}
|
|
66
|
+
if (nodes.length > maxQuantityNodesOnOneLvl) {
|
|
67
|
+
const extraNodes = nodes.slice(maxQuantityNodesOnOneLvl);
|
|
68
|
+
const remainingNodes = nodes.slice(0, maxQuantityNodesOnOneLvl);
|
|
69
|
+
|
|
70
|
+
finalHierarchyNodesArr[level] = remainingNodes;
|
|
71
|
+
finalHierarchyNodesArr[level + 1] = nodesHierarchy[level + 1]
|
|
72
|
+
? [...nodesHierarchy[level + 1], ...extraNodes]
|
|
73
|
+
: extraNodes;
|
|
74
|
+
}
|
|
75
|
+
if (finalHierarchyNodesArr[level + 1] || nodesHierarchy[level + 1]) {
|
|
76
|
+
level++;
|
|
77
|
+
const nodes = finalHierarchyNodesArr[level] || nodesHierarchy[level];
|
|
78
|
+
return splitLongLevels(nodes, finalHierarchyNodesArr, nodesHierarchy, level, maxQuantityNodesOnOneLvl);
|
|
79
|
+
} else {
|
|
80
|
+
return finalHierarchyNodesArr;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const buildHierarchyNodes = (
|
|
85
|
+
graphData: GraphologyGraphData,
|
|
86
|
+
selectedNode: string,
|
|
87
|
+
maxQuantityNodesOnOneLvl = 10
|
|
88
|
+
): NodesHierarchy => {
|
|
89
|
+
const nodes = graphData.nodes;
|
|
90
|
+
const edgesWithoutLoops = graphData.edges.filter((edge) => edge.from !== edge.to);
|
|
91
|
+
const firstLvlNodeIds = getFirstLvlNodes(edgesWithoutLoops, nodes, selectedNode);
|
|
92
|
+
|
|
93
|
+
const nodesHierarchy = findChildNodeIds(firstLvlNodeIds, [], new Set<string>(), edgesWithoutLoops);
|
|
94
|
+
const finalHierarchyNodesArr = splitLongLevels(nodesHierarchy[0], [], nodesHierarchy, 0, maxQuantityNodesOnOneLvl);
|
|
95
|
+
|
|
96
|
+
return finalHierarchyNodesArr;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const extractDataFromGraph = (graph: Graph): GraphologyGraphData => {
|
|
100
|
+
const nodes = graph.nodes().map((id) => ({id, name: ''} as Node));
|
|
101
|
+
const edges = graph.mapEdges((edge, attributes, source, target) => ({
|
|
102
|
+
from: source,
|
|
103
|
+
to: target,
|
|
104
|
+
key: edge,
|
|
105
|
+
relationTypeUri: attributes.relationTypeUri,
|
|
106
|
+
direction: attributes.direction
|
|
107
|
+
}));
|
|
108
|
+
return {nodes, edges};
|
|
109
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {GraphLayout} from '@reltio/mdm-sdk';
|
|
2
|
+
import {NodesHierarchy} from '../../types/graphDataTypes';
|
|
3
|
+
|
|
4
|
+
const X_MARGIN = 10;
|
|
5
|
+
const Y_MARGIN = 10;
|
|
6
|
+
|
|
7
|
+
type CalculateYPosProps = {
|
|
8
|
+
quantityAtLvl: number;
|
|
9
|
+
rowNumber: number;
|
|
10
|
+
isEvenItem: boolean;
|
|
11
|
+
layout: GraphLayout;
|
|
12
|
+
shouldUseCheckboardPattern: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const calculateYPos = ({
|
|
16
|
+
quantityAtLvl,
|
|
17
|
+
rowNumber,
|
|
18
|
+
isEvenItem,
|
|
19
|
+
layout,
|
|
20
|
+
shouldUseCheckboardPattern
|
|
21
|
+
}: CalculateYPosProps) => {
|
|
22
|
+
const isVerticalHierarchy = layout === GraphLayout.VERTICAL_TB;
|
|
23
|
+
const hasSingleNodeAtLvl = quantityAtLvl === 1;
|
|
24
|
+
return shouldUseCheckboardPattern && isVerticalHierarchy && isEvenItem && !hasSingleNodeAtLvl
|
|
25
|
+
? rowNumber * Y_MARGIN + Y_MARGIN / 2
|
|
26
|
+
: rowNumber * Y_MARGIN;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type CalculateXPosProps = {
|
|
30
|
+
quantityAtLvl: number;
|
|
31
|
+
posAtLvl: number;
|
|
32
|
+
max: number;
|
|
33
|
+
isEvenRow: boolean;
|
|
34
|
+
layout: GraphLayout;
|
|
35
|
+
shouldUseCheckboardPattern: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const calculateXPos = ({
|
|
39
|
+
quantityAtLvl,
|
|
40
|
+
posAtLvl,
|
|
41
|
+
max,
|
|
42
|
+
isEvenRow,
|
|
43
|
+
layout,
|
|
44
|
+
shouldUseCheckboardPattern
|
|
45
|
+
}: CalculateXPosProps) => {
|
|
46
|
+
const isHorizontalHierarchy = layout === GraphLayout.HORIZONTAL_LR;
|
|
47
|
+
const hasSingleNodeAtLvl = quantityAtLvl === 1;
|
|
48
|
+
const hasMaxNodesAtLvl = quantityAtLvl === max;
|
|
49
|
+
|
|
50
|
+
if (hasMaxNodesAtLvl) {
|
|
51
|
+
return shouldUseCheckboardPattern && isEvenRow && isHorizontalHierarchy
|
|
52
|
+
? posAtLvl * X_MARGIN + X_MARGIN / 2
|
|
53
|
+
: posAtLvl * X_MARGIN;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (hasSingleNodeAtLvl) {
|
|
57
|
+
return ((max - 1) * X_MARGIN) / 2;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return (((max - 1) * X_MARGIN) / (quantityAtLvl + 1)) * (posAtLvl + 1);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const getAngleOfRotation = (layout: GraphLayout) => {
|
|
64
|
+
switch (layout) {
|
|
65
|
+
case GraphLayout.VERTICAL_TB:
|
|
66
|
+
return 180;
|
|
67
|
+
case GraphLayout.HORIZONTAL_LR:
|
|
68
|
+
return 270;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export const getMaxLvlSize = (hierarchyNodes: NodesHierarchy) => {
|
|
73
|
+
const sizes = hierarchyNodes.map((nodes) => nodes.length);
|
|
74
|
+
return Math.max(...sizes);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const isSimpleGraph = (nodesLength: number) => nodesLength < 100;
|
|
78
|
+
|
|
79
|
+
export const getMaxQuantityNodesOnOneLvl = (nodesLength: number, layout: GraphLayout) => {
|
|
80
|
+
if (isSimpleGraph(nodesLength)) {
|
|
81
|
+
return 10;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const multiplier = layout === GraphLayout.VERTICAL_TB ? 1.5 : 0.7;
|
|
85
|
+
return Math.round(Math.sqrt(nodesLength) * multiplier);
|
|
86
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {pick} from 'ramda';
|
|
3
|
+
import {Entity} from '@reltio/mdm-sdk';
|
|
4
|
+
import {AttributesView, withContext, LinearLoadIndicator} from '@reltio/components';
|
|
5
|
+
import {GraphStateContext} from '../../contexts/GraphStateContext';
|
|
6
|
+
|
|
7
|
+
import {useStyles} from './styles';
|
|
8
|
+
import i18n from 'ui-i18n';
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
selectedEntity?: Entity;
|
|
12
|
+
selectedEntityLoading?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const RightPanelEntityDetails = ({selectedEntity, selectedEntityLoading}: Props) => {
|
|
16
|
+
const styles = useStyles();
|
|
17
|
+
return (
|
|
18
|
+
<div className={styles.wrapper}>
|
|
19
|
+
{selectedEntityLoading && <LinearLoadIndicator />}
|
|
20
|
+
<AttributesView
|
|
21
|
+
entity={selectedEntity}
|
|
22
|
+
caption={i18n.text('Entity details')}
|
|
23
|
+
className={styles.noShadowBlock}
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default withContext(
|
|
30
|
+
GraphStateContext,
|
|
31
|
+
pick(['selectedEntity', 'selectedEntityLoading']),
|
|
32
|
+
RightPanelEntityDetails
|
|
33
|
+
);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {mount} from 'enzyme';
|
|
3
|
+
import {AttributesView} from '@reltio/components';
|
|
4
|
+
|
|
5
|
+
import RightPanelEntityDetails from '../RightPanelEntityDetails';
|
|
6
|
+
import {GraphStateContext} from '../../../contexts/GraphStateContext';
|
|
7
|
+
import {GraphState} from '../../../types/graphDataTypes';
|
|
8
|
+
|
|
9
|
+
jest.mock('@reltio/components', () => ({
|
|
10
|
+
...jest.requireActual<Record<string, unknown>>('@reltio/components'),
|
|
11
|
+
AttributesView: () => null
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
const setUp = ({selectedEntity = null, selectedEntityLoading = false} = {}) =>
|
|
15
|
+
mount(
|
|
16
|
+
<GraphStateContext.Provider value={{selectedEntity, selectedEntityLoading} as GraphState}>
|
|
17
|
+
<RightPanelEntityDetails />
|
|
18
|
+
</GraphStateContext.Provider>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
describe('RightPanelEntityDetails tests', () => {
|
|
22
|
+
it('should render AttributesView with selectedEntity from context', () => {
|
|
23
|
+
const selectedEntity = {uri: 'uri1'};
|
|
24
|
+
const component = setUp({selectedEntity});
|
|
25
|
+
const attributesView = component.find(AttributesView);
|
|
26
|
+
expect(attributesView).toHaveLength(1);
|
|
27
|
+
expect(attributesView.prop('entity')).toBe(selectedEntity);
|
|
28
|
+
expect(attributesView.prop('caption')).toBe('Entity details');
|
|
29
|
+
expect(attributesView.prop('className')).toContain('noShadowBlock');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should render empty AttributesView while entity is loading', () => {
|
|
33
|
+
const component = setUp({selectedEntityLoading: true});
|
|
34
|
+
const attributesView = component.find(AttributesView);
|
|
35
|
+
expect(attributesView).toHaveLength(1);
|
|
36
|
+
expect(attributesView.prop('entity')).toBe(null);
|
|
37
|
+
expect(attributesView.prop('caption')).toBe('Entity details');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {pick} from 'ramda';
|
|
3
|
+
import {useSelector} from 'react-redux';
|
|
4
|
+
import {Entity, getEntityUriForLink} from '@reltio/mdm-sdk';
|
|
5
|
+
import {EntityUriLink, ProfileBand, withContext} from '@reltio/components';
|
|
6
|
+
import mdmModule from '@reltio/mdm-module';
|
|
7
|
+
import {GraphStateContext} from '../../contexts/GraphStateContext';
|
|
8
|
+
import {useStyles} from './styles';
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
selectedEntity?: Entity;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const RightPanelProfileBand = ({selectedEntity}: Props) => {
|
|
15
|
+
const styles = useStyles();
|
|
16
|
+
|
|
17
|
+
const entityUri = useSelector(mdmModule.selectors.getEntityUri);
|
|
18
|
+
const selectedEntityUri = selectedEntity?.uri;
|
|
19
|
+
|
|
20
|
+
const renderLabel = (label: string) => {
|
|
21
|
+
if (entityUri === selectedEntityUri) return label;
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<EntityUriLink className={styles.link} value={getEntityUriForLink(selectedEntity)} screen="graph">
|
|
25
|
+
{label}
|
|
26
|
+
</EntityUriLink>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return <ProfileBand entity={selectedEntity} renderLabel={renderLabel} />;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default withContext(GraphStateContext, pick(['selectedEntity']), RightPanelProfileBand);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {mount, ReactWrapper} from 'enzyme';
|
|
3
|
+
import * as reactRedux from 'react-redux';
|
|
4
|
+
import {EntityUriLink, ProfileBand} from '@reltio/components';
|
|
5
|
+
|
|
6
|
+
import RightPanelProfileBand from '../RightPanelProfileBand';
|
|
7
|
+
import {GraphStateContext} from '../../../contexts/GraphStateContext';
|
|
8
|
+
import {GraphState} from '../../../types/graphDataTypes';
|
|
9
|
+
|
|
10
|
+
jest.mock('@reltio/components', () => ({
|
|
11
|
+
...jest.requireActual<Record<string, unknown>>('@reltio/components'),
|
|
12
|
+
ProfileBand: () => null,
|
|
13
|
+
EntityUriLink: () => null
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
const store = {
|
|
17
|
+
profile: {
|
|
18
|
+
entity: {
|
|
19
|
+
uri: 'uri1'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const setUp = ({selectedEntity = null} = {}) =>
|
|
25
|
+
mount(
|
|
26
|
+
<GraphStateContext.Provider value={{selectedEntity} as GraphState}>
|
|
27
|
+
<RightPanelProfileBand />
|
|
28
|
+
</GraphStateContext.Provider>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
describe('RightPanelProfileBand tests', () => {
|
|
32
|
+
beforeAll(() => {
|
|
33
|
+
jest.spyOn(reactRedux, 'useSelector').mockImplementation((selector) => selector(store));
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
afterAll(() => {
|
|
37
|
+
jest.clearAllMocks();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should render ProfileBand with selectedEntity from context', () => {
|
|
41
|
+
const selectedEntity = {uri: 'uri2'};
|
|
42
|
+
const component = setUp({selectedEntity});
|
|
43
|
+
const profileBand = component.find(ProfileBand);
|
|
44
|
+
expect(profileBand).toHaveLength(1);
|
|
45
|
+
expect(profileBand.prop('entity')).toBe(selectedEntity);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should render standart label if selected entity equals current entity', () => {
|
|
49
|
+
const selectedEntity = {uri: store.profile.entity.uri};
|
|
50
|
+
const component = setUp({selectedEntity});
|
|
51
|
+
const label = component.find(ProfileBand).prop('renderLabel')('label');
|
|
52
|
+
expect(label).toBe('label');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should wrap label to EntityUriLink with correct props if selected entity does not equal current entity', () => {
|
|
56
|
+
const selectedEntity = {uri: 'uri2'};
|
|
57
|
+
const component = setUp({selectedEntity});
|
|
58
|
+
const label = new ReactWrapper(component.find(ProfileBand).prop('renderLabel')('label') as React.ReactElement);
|
|
59
|
+
expect(label.find(EntityUriLink)).toHaveLength(1);
|
|
60
|
+
expect(label.props()).toEqual({
|
|
61
|
+
className: 'link',
|
|
62
|
+
value: 'uri2',
|
|
63
|
+
screen: 'graph',
|
|
64
|
+
children: 'label'
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Typography from '@mui/material/Typography';
|
|
3
|
+
|
|
4
|
+
import i18n from 'ui-i18n';
|
|
5
|
+
import RelationshipTable from './components/RelationshipTable/RelationshipTable';
|
|
6
|
+
import RelationshipsFilters from './components/RelationshipsFilters/RelationshipsFilters';
|
|
7
|
+
import GraphAddRelationButton from './components/GraphAddRelationDialog/GraphAddRelationButton';
|
|
8
|
+
import {useStyles} from './styles';
|
|
9
|
+
|
|
10
|
+
const RightPanelRelationship = () => {
|
|
11
|
+
const styles = useStyles();
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div className={styles.wrapper}>
|
|
15
|
+
<div className={styles.caption}>
|
|
16
|
+
<Typography variant="subtitle1">{i18n.text('Relationships')}</Typography>
|
|
17
|
+
<GraphAddRelationButton />
|
|
18
|
+
</div>
|
|
19
|
+
<RelationshipsFilters />
|
|
20
|
+
<RelationshipTable />
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default RightPanelRelationship;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {shallow} from 'enzyme';
|
|
3
|
+
|
|
4
|
+
import RightPanelRelationship from '../RightPanelRelationship';
|
|
5
|
+
import RelationshipTable from '../components/RelationshipTable/RelationshipTable';
|
|
6
|
+
import RelationshipsFilters from '../components/RelationshipsFilters/RelationshipsFilters';
|
|
7
|
+
import GraphAddRelationButton from '../components/GraphAddRelationDialog/GraphAddRelationButton';
|
|
8
|
+
|
|
9
|
+
const setUp = () => shallow(<RightPanelRelationship />);
|
|
10
|
+
|
|
11
|
+
describe('RightPanelRelationship tests', () => {
|
|
12
|
+
it('should render main components', () => {
|
|
13
|
+
const component = setUp();
|
|
14
|
+
expect(component.find(GraphAddRelationButton)).toHaveLength(1);
|
|
15
|
+
expect(component.find(RelationshipsFilters)).toHaveLength(1);
|
|
16
|
+
expect(component.find(RelationshipTable)).toHaveLength(1);
|
|
17
|
+
});
|
|
18
|
+
});
|