@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.
Files changed (164) hide show
  1. package/index.ts +1 -0
  2. package/package.json +26 -9
  3. package/public/bundle.js +205 -0
  4. package/public/bundle.js.LICENSE.txt +88 -0
  5. package/public/package.json +29 -0
  6. package/scripts/build/index.js +20 -0
  7. package/src/__tests__/GraphView.test.tsx +25 -0
  8. package/src/components/CircleLayout/CircleLayout.tsx +76 -0
  9. package/src/components/CircleLayout/__tests__/CircleLayout.test.tsx +194 -0
  10. package/src/components/GotoButton/GotoButton.tsx +23 -0
  11. package/src/components/GotoButton/__tests__/GotoButton.test.tsx +33 -0
  12. package/src/components/GotoButton/styles.ts +15 -0
  13. package/src/components/GraphArea/GraphArea.tsx +113 -0
  14. package/src/components/GraphArea/__tests__/GraphArea.test.tsx +202 -0
  15. package/src/components/GraphArea/styles.ts +30 -0
  16. package/src/components/GraphLayoutSelector/GraphLayoutSelector.tsx +43 -0
  17. package/src/components/GraphLayoutSelector/__tests__/GraphLayoutSelector.spec.tsx +44 -0
  18. package/src/components/GraphLayoutSelector/styles.ts +15 -0
  19. package/src/components/GraphPerspectiveView/GraphPerspectiveView.tsx +58 -0
  20. package/src/components/GraphPerspectiveView/__tests__/GraphPerspectiveView.test.tsx +115 -0
  21. package/src/components/GraphPerspectiveView/__tests__/useGraphLoader.test.tsx +1519 -0
  22. package/src/components/GraphPerspectiveView/__tests__/useRelationshipTable.test.tsx +1003 -0
  23. package/src/components/GraphPerspectiveView/__tests__/useSelectedEntity.test.tsx +373 -0
  24. package/src/components/GraphPerspectiveView/styles.ts +34 -0
  25. package/src/components/GraphRightSidePanel/GraphRightSidePanel.tsx +27 -0
  26. package/src/components/GraphRightSidePanel/__tests__/GraphRightSidePanel.test.tsx +18 -0
  27. package/src/components/GraphRightSidePanel/icons/relationship-icon.svg +3 -0
  28. package/src/components/GraphRightSidePanel/styles.ts +8 -0
  29. package/src/components/GraphTypeSelector/GraphTypeSelector.tsx +56 -0
  30. package/src/components/GraphTypeSelector/__tests__/GraphTypeSelector.test.tsx +109 -0
  31. package/src/components/GraphTypeSelector/styles.ts +17 -0
  32. package/src/components/HierarchyLayout/HierarchyLayout.ts +102 -0
  33. package/src/components/HierarchyLayout/__tests__/HierarchyLayout.spec.tsx +241 -0
  34. package/src/components/HierarchyLayout/__tests__/buildHierarchy.spec.ts +130 -0
  35. package/src/components/HierarchyLayout/__tests__/calculations.spec.ts +230 -0
  36. package/src/components/HierarchyLayout/buildHierarchy.ts +109 -0
  37. package/src/components/HierarchyLayout/calculations.ts +86 -0
  38. package/src/components/RightPanelEntityDetails/RightPanelEntityDetails.tsx +33 -0
  39. package/src/components/RightPanelEntityDetails/__tests__/RightPanelEntityDetails.test.tsx +39 -0
  40. package/src/components/RightPanelEntityDetails/styles.ts +12 -0
  41. package/src/components/RightPanelProfileBand/RightPanelProfileBand.tsx +33 -0
  42. package/src/components/RightPanelProfileBand/__tests__/RightPanelProfileBand.test.tsx +67 -0
  43. package/src/components/RightPanelProfileBand/styles.ts +8 -0
  44. package/src/components/RightPanelRelationship/RightPanelRelationship.tsx +25 -0
  45. package/src/components/RightPanelRelationship/__tests__/RightPanelRelationship.test.tsx +18 -0
  46. package/src/components/RightPanelRelationship/components/CollapsibleTable/CollapsibleTable.tsx +100 -0
  47. package/src/components/RightPanelRelationship/components/CollapsibleTable/TableHead.tsx +38 -0
  48. package/src/components/RightPanelRelationship/components/CollapsibleTable/__tests__/CollapsibleTable.test.tsx +169 -0
  49. package/src/components/RightPanelRelationship/components/CollapsibleTable/__tests__/TableHead.test.tsx +107 -0
  50. package/src/components/RightPanelRelationship/components/CollapsibleTable/styles.ts +38 -0
  51. package/src/components/RightPanelRelationship/components/CollapsibleTable/types.ts +20 -0
  52. package/src/components/RightPanelRelationship/components/DeleteRelationDialog/DeleteRelationDialog.tsx +34 -0
  53. package/src/components/RightPanelRelationship/components/DeleteRelationDialog/__tests__/DeleteRelationDialog.test.tsx +46 -0
  54. package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/GraphAddRelationButton.tsx +43 -0
  55. package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/GraphAddRelationDialog.tsx +121 -0
  56. package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/__tests__/GraphAddRelationButton.test.tsx +80 -0
  57. package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/__tests__/GraphAddRelationDialog.test.tsx +262 -0
  58. package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/__tests__/mockdata.ts +75 -0
  59. package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/styles.ts +25 -0
  60. package/src/components/RightPanelRelationship/components/GraphAddRelationDialog/useCreatableInOutRelationTypes.ts +13 -0
  61. package/src/components/RightPanelRelationship/components/RelationshipTable/RelationshipTable.tsx +126 -0
  62. package/src/components/RightPanelRelationship/components/RelationshipTable/__tests__/RelationshipTable.test.tsx +176 -0
  63. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/ControlsCellRenderer.tsx +59 -0
  64. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/DefaultCellRenderer.tsx +29 -0
  65. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/ExpandedRowRenderer.tsx +94 -0
  66. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/HeadCellRenderer.tsx +34 -0
  67. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/ProfileCellRenderer.tsx +41 -0
  68. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/ControlsCellRenderer.test.tsx +80 -0
  69. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/DefaultCellRenderer.test.tsx +47 -0
  70. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/ExpandedRowRenderer.test.tsx +166 -0
  71. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/HeadCellRenderer.test.tsx +23 -0
  72. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/__tests__/ProfileCellRenderer.test.tsx +47 -0
  73. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/components/DeleteRelationButton.tsx +32 -0
  74. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/components/__tests__/DeleteRelationButton.test.tsx +28 -0
  75. package/src/components/RightPanelRelationship/components/RelationshipTable/cell-renderers/styles.ts +113 -0
  76. package/src/components/RightPanelRelationship/components/RelationshipTable/styles.ts +36 -0
  77. package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsFilters.tsx +41 -0
  78. package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsFiltersDialog/RelationshipsFiltersDialog.tsx +91 -0
  79. package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsFiltersDialog/__tests__/RelationshipsFilterDialog.test.tsx +192 -0
  80. package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsFiltersDialog/styles.ts +34 -0
  81. package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsSearchTextField/RelationshipsSearchTextField.tsx +31 -0
  82. package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsSearchTextField/__tests__/RelationshipsSearchTextField.test.tsx +43 -0
  83. package/src/components/RightPanelRelationship/components/RelationshipsFilters/RelationshipsSearchTextField/styles.ts +17 -0
  84. package/src/components/RightPanelRelationship/components/RelationshipsFilters/__tests__/RelationshipsFilters.test.tsx +76 -0
  85. package/src/components/RightPanelRelationship/components/RelationshipsFilters/styles.ts +19 -0
  86. package/src/components/RightPanelRelationship/styles.ts +20 -0
  87. package/src/components/SigmaCustomRenderers/SigmaCustomRenderersContainer.tsx +16 -0
  88. package/src/components/SigmaGraphContainer/SigmaGraphContainer.tsx +55 -0
  89. package/src/components/SigmaGraphContainer/__tests__/SigmaGraphContainer.test.tsx +25 -0
  90. package/src/components/SigmaGraphResizer/SigmaGraphResizer.tsx +13 -0
  91. package/src/components/SigmaGraphResizer/__tests__/SigmaGraphResizer.test.tsx +28 -0
  92. package/src/components/TreeLayout/TreeLayout.tsx +33 -0
  93. package/src/components/TreeLayout/__tests__/TreeLayout.test.tsx +42 -0
  94. package/src/components/TreeLayout/styles.ts +10 -0
  95. package/src/components/ZoomSlider/ZoomSlider.tsx +90 -0
  96. package/src/components/ZoomSlider/__tests__/ZoomSlider.test.tsx +84 -0
  97. package/src/components/ZoomSlider/styles.ts +57 -0
  98. package/src/constants/index.ts +1 -0
  99. package/src/contexts/GraphStateContext.tsx +19 -0
  100. package/src/contexts/SigmaCustomRenderersContext.ts +20 -0
  101. package/src/helpers/relationsHelpers.ts +9 -0
  102. package/src/hooks/__tests__/useGraphLayout.test.tsx +825 -0
  103. package/src/hooks/__tests__/useGraphLayoutSelector.test.tsx +19 -0
  104. package/src/hooks/__tests__/useSelfRelationLoopsRenderer.test.ts +198 -0
  105. package/src/hooks/__tests__/useSigmaCustomRenderers.test.ts +273 -0
  106. package/src/hooks/__tests__/useTooltipRenderer.test.ts +289 -0
  107. package/src/hooks/useGraphLayout.ts +308 -0
  108. package/src/hooks/useGraphLayoutSelector.ts +19 -0
  109. package/src/hooks/useGraphLoader.ts +279 -0
  110. package/src/hooks/useGraphRightSidePanelElements.tsx +36 -0
  111. package/src/hooks/useGraphState.ts +40 -0
  112. package/src/hooks/useGraphType.ts +32 -0
  113. package/src/hooks/useRelationshipTable.ts +212 -0
  114. package/src/hooks/useRelationshipTableFilters.ts +43 -0
  115. package/src/hooks/useSelectedEntity.ts +89 -0
  116. package/src/hooks/useSelfRelationLoopsRenderer.ts +52 -0
  117. package/src/hooks/useSigmaCustomRenderers.ts +112 -0
  118. package/src/hooks/useTooltipRenderer.ts +80 -0
  119. package/src/index.tsx +37 -0
  120. package/src/rendering/canvas/__tests__/hover.spec.ts +31 -0
  121. package/src/rendering/canvas/__tests__/label.spec.ts +64 -0
  122. package/src/rendering/canvas/__tests__/nodeBackground.spec.ts +99 -0
  123. package/src/rendering/canvas/__tests__/selfRelationLoop.spec.ts +88 -0
  124. package/src/rendering/canvas/__tests__/tooltip.spec.ts +33 -0
  125. package/src/rendering/canvas/hover.ts +13 -0
  126. package/src/rendering/canvas/label.ts +33 -0
  127. package/src/rendering/canvas/nodeBackground.ts +61 -0
  128. package/src/rendering/canvas/selfRelationLoop.ts +108 -0
  129. package/src/rendering/canvas/tooltip.ts +38 -0
  130. package/src/rendering/icons/collapseIcon.inline.svg.ts +6 -0
  131. package/src/rendering/icons/expandIcon.inline.svg.ts +5 -0
  132. package/src/rendering/icons/no_photo.inline.svg.ts +13 -0
  133. package/src/rendering/webgl/edge.arrowHead.ts +87 -0
  134. package/src/rendering/webgl/edge.clamped.ts +246 -0
  135. package/src/rendering/webgl/edge.reversedArrowHead.ts +14 -0
  136. package/src/rendering/webgl/helpers/__tests__/imageHelper.spec.ts +36 -0
  137. package/src/rendering/webgl/helpers/imageHelper.ts +13 -0
  138. package/src/rendering/webgl/image.ts +115 -0
  139. package/src/rendering/webgl/node.border.ts +78 -0
  140. package/src/rendering/webgl/node.buttons.ts +241 -0
  141. package/src/rendering/webgl/node.image.ts +169 -0
  142. package/src/rendering/webgl/shaders/edge.clamped.vert.glsl.ts +55 -0
  143. package/src/rendering/webgl/shaders/node.border.frag.glsl.ts +30 -0
  144. package/src/rendering/webgl/shaders/node.border.vert.glsl.ts +37 -0
  145. package/src/rendering/webgl/shaders/node.buttons.frag.glsl.ts +32 -0
  146. package/src/rendering/webgl/shaders/node.buttons.vert.glsl.ts +49 -0
  147. package/src/rendering/webgl/shaders/node.image.frag.glsl.ts +46 -0
  148. package/src/rendering/webgl/shaders/node.image.vert.glsl.ts +42 -0
  149. package/src/types/graphDataTypes.ts +143 -0
  150. package/src/types/sigmaCustomRenderersTypes.ts +13 -0
  151. package/src/utils/__tests__/graph.spec.ts +152 -0
  152. package/src/utils/__tests__/graphLayout.spec.ts +125 -0
  153. package/src/utils/__tests__/hopsData.spec.ts +456 -0
  154. package/src/utils/__tests__/processResponceToGraph.spec.ts +165 -0
  155. package/src/utils/graph.ts +83 -0
  156. package/src/utils/graphLayout.ts +70 -0
  157. package/src/utils/hopsData.ts +198 -0
  158. package/src/utils/processResponseToGraph.ts +32 -0
  159. package/tsconfig.json +4 -0
  160. package/webpack.config.js +10 -0
  161. package/bundle.js +0 -2
  162. package/bundle.js.LICENSE.txt +0 -54
  163. /package/{5271a9e7b6651c852e93.png → public/5271a9e7b6651c852e93.png} +0 -0
  164. /package/{main.css → public/main.css} +0 -0
@@ -0,0 +1,202 @@
1
+ import React from 'react';
2
+ import {mount} from 'enzyme';
3
+ import {identity} from 'ramda';
4
+ import {act} from 'react-dom/test-utils';
5
+ import {MultiGraph} from 'graphology';
6
+ import {GraphLayout} from '@reltio/mdm-sdk';
7
+
8
+ import GraphArea from '../GraphArea';
9
+ import {GraphStateContext} from '../../../contexts/GraphStateContext';
10
+ import {SigmaGraphContainer} from '../../SigmaGraphContainer/SigmaGraphContainer';
11
+ import CircleLayout from '../../CircleLayout/CircleLayout';
12
+ import {GraphState} from '../../../types/graphDataTypes';
13
+ import GraphTypeSelector from '../../GraphTypeSelector/GraphTypeSelector';
14
+ import GraphLayoutSelector from '../../GraphLayoutSelector/GraphLayoutSelector';
15
+ import HierarchyLayout from '../../HierarchyLayout/HierarchyLayout';
16
+ import SigmaGraphResizer from '../../SigmaGraphResizer/SigmaGraphResizer';
17
+ import ZoomSlider from '../../ZoomSlider/ZoomSlider';
18
+ import GotoButton from '../../GotoButton/GotoButton';
19
+ import TreeLayout from '../../TreeLayout/TreeLayout';
20
+
21
+ jest.mock('../../SigmaGraphContainer/SigmaGraphContainer', () => ({
22
+ SigmaGraphContainer: ({children}) => <div>{children}</div> //eslint-disable-line
23
+ }));
24
+
25
+ jest.mock('../../GraphTypeSelector/GraphTypeSelector', () => () => null);
26
+
27
+ jest.mock('../../CircleLayout/CircleLayout', () => () => null);
28
+ jest.mock('../../HierarchyLayout/HierarchyLayout', () => () => null);
29
+ jest.mock('../../SigmaGraphResizer/SigmaGraphResizer', () => () => null);
30
+
31
+ jest.mock('../../ZoomSlider/ZoomSlider', () => () => null);
32
+ jest.mock('../../GotoButton/GotoButton', () => () => null);
33
+ jest.mock('../../TreeLayout/TreeLayout', () => () => null);
34
+
35
+ const setUp = ({
36
+ data = null,
37
+ graphologyGraph = null,
38
+ selectedEntity = null,
39
+ onEntitySelect = identity,
40
+ onExpandEntity = identity,
41
+ onCollapseEntity = identity,
42
+ filters = {},
43
+ layout = null,
44
+ setLayout = identity,
45
+ graphTypeUri = null
46
+ } = {}) =>
47
+ mount(
48
+ <GraphStateContext.Provider
49
+ value={
50
+ {
51
+ data,
52
+ graphologyGraph,
53
+ selectedEntity,
54
+ onEntitySelect,
55
+ onExpandEntity,
56
+ onCollapseEntity,
57
+ relationshipTable: {filters},
58
+ layout,
59
+ setLayout,
60
+ graphTypeUri
61
+ } as GraphState
62
+ }
63
+ >
64
+ <GraphArea />
65
+ </GraphStateContext.Provider>
66
+ );
67
+
68
+ describe('GraphArea tests', () => {
69
+ it('should not render anything if GraphStateContext.Provider.value.data is not defined', () => {
70
+ const component = setUp();
71
+ expect(component.find(SigmaGraphContainer)).toHaveLength(0);
72
+ expect(component.find(CircleLayout)).toHaveLength(0);
73
+ expect(component.find(SigmaGraphResizer)).toHaveLength(0);
74
+ expect(component.find(ZoomSlider)).toHaveLength(0);
75
+ expect(component.find(GotoButton)).toHaveLength(0);
76
+ });
77
+
78
+ it('should render SigmaGraphContainer and CircleLayout if GraphStateContext.Provider.value.graphologyGraph is defined and layout is tree', () => {
79
+ const data = {
80
+ entities: [{uri: 'uri1'}, {uri: 'uri2'}],
81
+ relations: []
82
+ };
83
+ const graphologyGraph = new MultiGraph();
84
+ const selectedEntity = {uri: 'uri2'};
85
+ const onEntitySelect = jest.fn();
86
+ const onExpandEntity = jest.fn();
87
+ const onCollapseEntity = jest.fn();
88
+ const filters = {entityTypesUris: ['hcp'], relationTypesUris: []};
89
+ const setLayout = jest.fn();
90
+ const component = setUp({
91
+ data,
92
+ graphologyGraph,
93
+ selectedEntity,
94
+ onEntitySelect,
95
+ onExpandEntity,
96
+ onCollapseEntity,
97
+ filters,
98
+ layout: GraphLayout.SIMPLE_NETWORK,
99
+ setLayout
100
+ });
101
+ expect(component.find(SigmaGraphContainer)).toHaveLength(1);
102
+
103
+ const findCircleLayout = () => component.find(SigmaGraphContainer).find(CircleLayout);
104
+
105
+ const circleLayout = findCircleLayout();
106
+ expect(circleLayout).toHaveLength(1);
107
+ expect(circleLayout.prop('data')).toBe(data);
108
+ expect(circleLayout.prop('graph')).toBe(graphologyGraph);
109
+ expect(circleLayout.prop('selectedNode')).toBe(selectedEntity.uri);
110
+ expect(circleLayout.prop('onNodeClick')).toBe(onEntitySelect);
111
+ expect(circleLayout.prop('onNodeExpand')).toBe(onExpandEntity);
112
+ expect(circleLayout.prop('onNodeCollapse')).toBe(onCollapseEntity);
113
+ expect(circleLayout.prop('filters')).toBe(filters);
114
+ expect(circleLayout.prop('layout')).toBe(GraphLayout.SIMPLE_NETWORK);
115
+
116
+ expect(component.find(SigmaGraphContainer).find(SigmaGraphResizer)).toHaveLength(1);
117
+
118
+ const graphLayoutSelector = component.find(GraphLayoutSelector);
119
+ act(() => {
120
+ graphLayoutSelector.prop('onChangeHandler')(GraphLayout.DIRECTED_NETWORK);
121
+ });
122
+ expect(setLayout).toHaveBeenCalledWith(GraphLayout.DIRECTED_NETWORK);
123
+ });
124
+
125
+ it('should render HierarchyLayout if HierarchyLayout is selected', () => {
126
+ const data = {
127
+ entities: [{uri: 'uri1'}, {uri: 'uri2'}],
128
+ relations: []
129
+ };
130
+ const graphologyGraph = new MultiGraph();
131
+ const selectedEntity = {uri: 'uri2'};
132
+ const onEntitySelect = jest.fn();
133
+ const onExpandEntity = jest.fn();
134
+ const onCollapseEntity = jest.fn();
135
+ const filters = {entityTypesUris: ['hcp'], relationTypesUris: ['rel1']};
136
+ const component = setUp({
137
+ data,
138
+ graphologyGraph,
139
+ selectedEntity,
140
+ onEntitySelect,
141
+ onExpandEntity,
142
+ onCollapseEntity,
143
+ filters,
144
+ layout: GraphLayout.VERTICAL_TB
145
+ });
146
+ const graphLayoutSelector = component.find(GraphLayoutSelector);
147
+ expect(graphLayoutSelector).toHaveLength(1);
148
+ expect(graphLayoutSelector.prop('value')).toBe(GraphLayout.VERTICAL_TB);
149
+ expect(component.find(SigmaGraphContainer)).toHaveLength(1);
150
+ const circleLayout = component.find(SigmaGraphContainer).find(CircleLayout);
151
+ const hierarchyLayout = component.find(SigmaGraphContainer).find(HierarchyLayout);
152
+ expect(circleLayout).toHaveLength(0);
153
+ expect(hierarchyLayout).toHaveLength(1);
154
+ expect(hierarchyLayout.prop('data')).toBe(data);
155
+ expect(hierarchyLayout.prop('graph')).toBe(graphologyGraph);
156
+ expect(hierarchyLayout.prop('selectedNode')).toBe(selectedEntity.uri);
157
+ expect(hierarchyLayout.prop('onNodeClick')).toBe(onEntitySelect);
158
+ expect(hierarchyLayout.prop('layout')).toEqual(GraphLayout.VERTICAL_TB);
159
+ expect(hierarchyLayout.prop('onNodeExpand')).toBe(onExpandEntity);
160
+ expect(hierarchyLayout.prop('onNodeCollapse')).toBe(onCollapseEntity);
161
+ expect(hierarchyLayout.prop('filters')).toBe(filters);
162
+ expect(component.find(SigmaGraphContainer).find(SigmaGraphResizer)).toHaveLength(1);
163
+ });
164
+
165
+ it('should render TreeLayout if TreeLayout is selected', () => {
166
+ const component = setUp({
167
+ layout: GraphLayout.TREE
168
+ });
169
+ const graphLayoutSelector = component.find(GraphLayoutSelector);
170
+ expect(graphLayoutSelector).toHaveLength(1);
171
+ expect(graphLayoutSelector.prop('value')).toBe(GraphLayout.TREE);
172
+ expect(component.find(SigmaGraphContainer)).toHaveLength(0);
173
+ const treeLayout = component.find(TreeLayout);
174
+ expect(treeLayout).toHaveLength(1);
175
+ });
176
+
177
+ it('should render GraphTypeSelector', () => {
178
+ const component = setUp();
179
+ expect(component.find(GraphTypeSelector)).toHaveLength(1);
180
+ });
181
+
182
+ it('should render GraphLayoutSelector', () => {
183
+ const graphTypeUri = 'graphTypeUri';
184
+ const component = setUp({graphTypeUri});
185
+ expect(component.find(GraphLayoutSelector)).toHaveLength(1);
186
+ expect(component.find(GraphLayoutSelector).prop('graphTypeUri')).toBe(graphTypeUri);
187
+ });
188
+
189
+ it('should render ZoomSlider', () => {
190
+ const graphologyGraph = new MultiGraph();
191
+ const component = setUp({graphologyGraph});
192
+ expect(component.find(ZoomSlider)).toHaveLength(1);
193
+ });
194
+
195
+ it('should render GotoButton', () => {
196
+ const graphologyGraph = new MultiGraph();
197
+ const selectedEntity = {uri: 'uri2'};
198
+ const component = setUp({graphologyGraph, selectedEntity});
199
+ expect(component.find(GotoButton)).toHaveLength(1);
200
+ expect(component.find(GotoButton).prop('node')).toBe(selectedEntity.uri);
201
+ });
202
+ });
@@ -0,0 +1,30 @@
1
+ import {makeStyles} from '@mui/styles';
2
+
3
+ export const useStyles = makeStyles({
4
+ wrapper: {
5
+ height: '100%',
6
+ position: 'relative'
7
+ },
8
+ selectors: {
9
+ display: 'flex',
10
+ position: 'absolute',
11
+ top: '12px',
12
+ right: '16px',
13
+ zIndex: 2
14
+ },
15
+ graph: {
16
+ height: 'calc(100% - 5px)'
17
+ },
18
+ rightBottomControls: {
19
+ position: 'absolute',
20
+ zIndex: 100,
21
+ right: '18px',
22
+ bottom: '16px',
23
+ display: 'flex',
24
+ width: '200px'
25
+ },
26
+ zoomSlider: {
27
+ flexGrow: 1,
28
+ marginRight: '8px'
29
+ }
30
+ });
@@ -0,0 +1,43 @@
1
+ import React, {memo} from 'react';
2
+ import i18n from 'ui-i18n';
3
+ import {propEq} from 'ramda';
4
+ import {DropDownSelector} from '@reltio/components';
5
+ import {GraphLayout} from '@reltio/mdm-sdk';
6
+ import {useStyles} from './styles';
7
+
8
+ type Props = {
9
+ value: GraphLayout;
10
+ onChangeHandler: (value: GraphLayout) => void;
11
+ graphTypeUri?: string;
12
+ };
13
+
14
+ const GraphLayoutSelector = ({value, onChangeHandler, graphTypeUri}: Props) => {
15
+ const styles = useStyles();
16
+ const layouts = [
17
+ {label: i18n.text('Simple network'), value: GraphLayout.SIMPLE_NETWORK},
18
+ {label: i18n.text('Vertical hierarchy'), value: GraphLayout.VERTICAL_TB},
19
+ {label: i18n.text('Horizontal hierarchy'), value: GraphLayout.HORIZONTAL_LR},
20
+ {label: i18n.text('Directed network'), value: GraphLayout.DIRECTED_NETWORK},
21
+ {label: i18n.text('Tree'), value: GraphLayout.TREE}
22
+ ];
23
+ const options = graphTypeUri ? layouts : layouts.filter((layout) => layout.value !== GraphLayout.TREE);
24
+ return (
25
+ <DropDownSelector
26
+ className={styles.graphLayoutSelector}
27
+ label={i18n.text('Graph layout')}
28
+ value={layouts.find(propEq('value', value))}
29
+ options={options}
30
+ onChange={(value) => onChangeHandler(value.value)}
31
+ TextFieldProps={{
32
+ InputProps: {
33
+ disableUnderline: true,
34
+ classes: {
35
+ root: styles.filledInputRoot
36
+ }
37
+ }
38
+ }}
39
+ />
40
+ );
41
+ };
42
+
43
+ export default memo(GraphLayoutSelector);
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import {shallow} from 'enzyme';
3
+ import i18n from 'ui-i18n';
4
+ import {GraphLayout} from '@reltio/mdm-sdk';
5
+ import {DropDownSelector} from '@reltio/components';
6
+ import GraphLayoutSelector from '../GraphLayoutSelector';
7
+
8
+ const props = {
9
+ value: GraphLayout.HORIZONTAL_LR,
10
+ onChangeHandler: jest.fn()
11
+ };
12
+
13
+ describe('GraphLayoutSelector tests', () => {
14
+ const layouts = [
15
+ {label: i18n.text('Simple network'), value: GraphLayout.SIMPLE_NETWORK},
16
+ {label: i18n.text('Vertical hierarchy'), value: GraphLayout.VERTICAL_TB},
17
+ {label: i18n.text('Horizontal hierarchy'), value: GraphLayout.HORIZONTAL_LR},
18
+ {label: i18n.text('Directed network'), value: GraphLayout.DIRECTED_NETWORK},
19
+ {label: i18n.text('Tree'), value: GraphLayout.TREE}
20
+ ];
21
+ it('should render DropDownSelector', () => {
22
+ const optionsWithoutTreeLayout = layouts.filter((layout) => layout.value !== GraphLayout.TREE);
23
+ const graphTypeComponent = shallow(<GraphLayoutSelector {...props} />);
24
+ const dropDownComponent = graphTypeComponent.find(DropDownSelector);
25
+ expect(dropDownComponent).toHaveLength(1);
26
+ expect(dropDownComponent.prop('label')).toBe('Graph layout');
27
+ expect(dropDownComponent.prop('value')).toEqual({value: props.value, label: props.value});
28
+ expect(dropDownComponent.prop('options')).toEqual(optionsWithoutTreeLayout);
29
+ });
30
+
31
+ it('should call onChangeHandler after selecting option', () => {
32
+ const graphTypeComponent = shallow(<GraphLayoutSelector {...props} />);
33
+ const dropDownComponent = graphTypeComponent.find(DropDownSelector);
34
+ dropDownComponent.prop('onChange')({label: GraphLayout.SIMPLE_NETWORK, value: GraphLayout.SIMPLE_NETWORK});
35
+ expect(props.onChangeHandler).toBeCalledWith(GraphLayout.SIMPLE_NETWORK);
36
+ });
37
+
38
+ it('should add tree layout in options if graphTypeUri exist', () => {
39
+ const propsWithGraphType = {...props, graphTypeUri: 'graphTypeUri'};
40
+ const graphTypeComponent = shallow(<GraphLayoutSelector {...propsWithGraphType} />);
41
+ const dropDownComponent = graphTypeComponent.find(DropDownSelector);
42
+ expect(dropDownComponent.prop('options')).toEqual(layouts);
43
+ });
44
+ });
@@ -0,0 +1,15 @@
1
+ import {makeStyles} from '@mui/styles';
2
+
3
+ export const useStyles = makeStyles({
4
+ graphLayoutSelector: {
5
+ minWidth: '202px',
6
+ backgroundColor: '#FAFAFA',
7
+ opacity: 1,
8
+ marginLeft: '10px'
9
+ },
10
+
11
+ filledInputRoot: {
12
+ borderRadius: '4px',
13
+ height: '42px'
14
+ }
15
+ });
@@ -0,0 +1,58 @@
1
+ import React, {memo} from 'react';
2
+ import {useSelector} from 'react-redux';
3
+ import {pluck} from 'ramda';
4
+ import mdm from '@reltio/mdm-module';
5
+ import {Entity, GraphLayout} from '@reltio/mdm-sdk';
6
+ import {LinearLoadIndicator, ProfileResizablePanes, ScreenProfileBand} from '@reltio/components';
7
+
8
+ import {useGraphState} from '../../hooks/useGraphState';
9
+ import {useGraphRightSidePanelElements} from '../../hooks/useGraphRightSidePanelElements';
10
+ import {GraphStateContext} from '../../contexts/GraphStateContext';
11
+ import {GraphRightSidePanel} from '../GraphRightSidePanel/GraphRightSidePanel';
12
+ import GraphArea from '../GraphArea/GraphArea';
13
+
14
+ import {useStyles} from './styles';
15
+
16
+ type Props = {
17
+ graphTypeUri?: string;
18
+ graphLayout?: GraphLayout;
19
+ };
20
+
21
+ const perspectiveId = 'graph';
22
+
23
+ const GraphPerspectiveView = memo(({graphTypeUri, graphLayout}: Props) => {
24
+ const styles = useStyles();
25
+ const entity: Entity = useSelector(mdm.selectors.getEntity);
26
+ const graphState = useGraphState(entity, graphTypeUri, graphLayout);
27
+ const {graphLoading, layout} = graphState;
28
+
29
+ const buttonsDisabled = layout === GraphLayout.TREE;
30
+ const {tabs} = useGraphRightSidePanelElements();
31
+
32
+ return (
33
+ <GraphStateContext.Provider value={graphState}>
34
+ <div className={styles.perspectiveView}>
35
+ {graphLoading && <LinearLoadIndicator />}
36
+ {entity?.uri && (
37
+ <div className={styles.graphContainer}>
38
+ <ProfileResizablePanes
39
+ disabled={buttonsDisabled}
40
+ perspectiveId={perspectiveId}
41
+ buttonsProps={pluck('buttonProps', tabs)}
42
+ >
43
+ <div className={styles.graphWrapper}>
44
+ <ScreenProfileBand entity={entity} />
45
+ <GraphArea />
46
+ </div>
47
+ <GraphRightSidePanel tabs={tabs} />
48
+ </ProfileResizablePanes>
49
+ </div>
50
+ )}
51
+ </div>
52
+ </GraphStateContext.Provider>
53
+ );
54
+ });
55
+
56
+ GraphPerspectiveView.displayName = 'GraphPerspectiveView';
57
+
58
+ export default GraphPerspectiveView;
@@ -0,0 +1,115 @@
1
+ import React from 'react';
2
+ import {shallow, mount} from 'enzyme';
3
+ import * as reactRedux from 'react-redux';
4
+ import {LinearLoadIndicator, ScreenProfileBand} from '@reltio/components';
5
+ import {Entity, Metadata} from '@reltio/mdm-sdk';
6
+
7
+ import GraphPerspectiveView from '../GraphPerspectiveView';
8
+ import {GraphStateContext} from '../../../contexts/GraphStateContext';
9
+ import GraphArea from '../../GraphArea/GraphArea';
10
+ import {GraphRightSidePanel} from '../../GraphRightSidePanel/GraphRightSidePanel';
11
+
12
+ jest.mock('../../GraphArea/GraphArea', () => () => null);
13
+
14
+ jest.mock('../../GraphRightSidePanel/GraphRightSidePanel', () => ({
15
+ ...(jest.requireActual('../../GraphRightSidePanel/GraphRightSidePanel') as Record<string, unknown>),
16
+ default: () => null
17
+ }));
18
+
19
+ jest.mock('../../../contexts/GraphStateContext', () => ({
20
+ GraphStateContext: {
21
+ Provider: jest.fn().mockImplementation(({children}) => <div id="graphStateContextMock">{children}</div>)
22
+ }
23
+ }));
24
+
25
+ jest.mock('@reltio/components', () => ({
26
+ ...jest.requireActual<Record<string, unknown>>('@reltio/components'),
27
+ ScreenProfileBand: jest.fn(() => null)
28
+ }));
29
+
30
+ jest.mock('@reltio/mdm-sdk', () => ({
31
+ ...jest.requireActual<Record<string, unknown>>('@reltio/mdm-sdk'),
32
+ removeRelation: jest.fn().mockReturnValue(Promise.resolve({})),
33
+ createRelation: jest.fn().mockReturnValue(Promise.resolve({})),
34
+ getHops: jest.fn().mockReturnValue(Promise.resolve({})),
35
+ getEntity: jest.fn().mockReturnValue(Promise.resolve({})),
36
+ getRelation: jest.fn().mockReturnValue(Promise.resolve({})),
37
+ updateRelation: jest.fn().mockReturnValue(Promise.resolve())
38
+ }));
39
+
40
+ type CreateStoreProps = {
41
+ entity?: Entity;
42
+ metadata?: Metadata;
43
+ };
44
+ const createStore = ({entity, metadata}: CreateStoreProps = {}) => ({
45
+ profile: {
46
+ entity: entity || {
47
+ uri: 'entities/uri1',
48
+ type: 'configuration/entityTypes/HCO'
49
+ }
50
+ },
51
+ tenant: {
52
+ id: 't1'
53
+ },
54
+ metadata: {
55
+ t1: metadata
56
+ }
57
+ });
58
+
59
+ describe('GraphPerspectiveView tests', () => {
60
+ const dispatch = jest.fn();
61
+ let store;
62
+
63
+ const setUp = (method: typeof shallow | typeof mount = shallow, customStore?) => {
64
+ store = customStore || createStore();
65
+ return (method as typeof shallow)(<GraphPerspectiveView />);
66
+ };
67
+
68
+ beforeAll(() => {
69
+ jest.spyOn(reactRedux, 'useDispatch').mockReturnValue(dispatch);
70
+ jest.spyOn(reactRedux, 'useSelector').mockImplementation((selector) => selector(store));
71
+ });
72
+
73
+ afterEach(() => {
74
+ jest.clearAllMocks();
75
+ });
76
+
77
+ it('should not render main components if entity uri is not defined in store', () => {
78
+ const component = setUp(
79
+ shallow,
80
+ createStore({
81
+ entity: {} as Entity
82
+ })
83
+ );
84
+ expect(component.find(GraphStateContext.Provider)).toHaveLength(1);
85
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
86
+ data: null,
87
+ graphLoading: false,
88
+ selectedEntityLoading: false,
89
+ selectedEntity: null,
90
+ onEntitySelect: expect.any(Function),
91
+ graphTypeUri: null
92
+ });
93
+ expect(component.find(LinearLoadIndicator)).toHaveLength(0);
94
+ expect(component.find(ScreenProfileBand)).toHaveLength(0);
95
+ expect(component.find(GraphArea)).toHaveLength(0);
96
+ expect(component.find(GraphRightSidePanel)).toHaveLength(0);
97
+ });
98
+
99
+ it('should render main components if entity uri is defined in store', () => {
100
+ const component = setUp();
101
+ expect(component.find(GraphStateContext.Provider)).toHaveLength(1);
102
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
103
+ data: null,
104
+ graphTypeUri: null,
105
+ graphLoading: false,
106
+ selectedEntityLoading: false,
107
+ selectedEntity: null,
108
+ onEntitySelect: expect.any(Function)
109
+ });
110
+ expect(component.find(LinearLoadIndicator)).toHaveLength(0);
111
+ expect(component.find(ScreenProfileBand)).toHaveLength(1);
112
+ expect(component.find(GraphArea)).toHaveLength(1);
113
+ expect(component.find(GraphRightSidePanel)).toHaveLength(1);
114
+ });
115
+ });