@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,373 @@
1
+ import React from 'react';
2
+ import {mount, shallow} from 'enzyme';
3
+ import {act} from 'react-dom/test-utils';
4
+ import * as reactRedux from 'react-redux';
5
+ import {Entity, getEntity, getHops, Metadata} from '@reltio/mdm-sdk';
6
+ import {ui} from '@reltio/mdm-module';
7
+ import {GraphStateContext} from '../../../contexts/GraphStateContext';
8
+ import GraphPerspectiveView from '../GraphPerspectiveView';
9
+
10
+ jest.mock('../../GraphArea/GraphArea', () => () => null);
11
+ jest.mock('../../GraphRightSidePanel/GraphRightSidePanel', () => ({
12
+ ...(jest.requireActual('../../GraphRightSidePanel/GraphRightSidePanel') as Record<string, unknown>),
13
+ default: () => null
14
+ }));
15
+ jest.mock('../../../contexts/GraphStateContext', () => ({
16
+ GraphStateContext: {
17
+ Provider: jest.fn().mockImplementation(({children}) => <div id="graphStateContextMock">{children}</div>)
18
+ }
19
+ }));
20
+
21
+ jest.mock('@reltio/components', () => ({
22
+ ...jest.requireActual<Record<string, unknown>>('@reltio/components'),
23
+ ScreenProfileBand: () => null
24
+ }));
25
+
26
+ jest.mock('@reltio/mdm-sdk', () => ({
27
+ ...jest.requireActual<Record<string, unknown>>('@reltio/mdm-sdk'),
28
+ removeRelation: jest.fn().mockReturnValue(Promise.resolve({})),
29
+ createRelation: jest.fn().mockReturnValue(Promise.resolve({})),
30
+ getHops: jest.fn().mockReturnValue(Promise.resolve({})),
31
+ getEntity: jest.fn().mockReturnValue(Promise.resolve({})),
32
+ getRelation: jest.fn().mockReturnValue(Promise.resolve({})),
33
+ updateRelation: jest.fn().mockReturnValue(Promise.resolve())
34
+ }));
35
+
36
+ type CreateStoreProps = {
37
+ entity?: Entity;
38
+ metadata?: Metadata;
39
+ };
40
+ const createStore = ({entity, metadata = {} as Metadata}: CreateStoreProps = {}) => ({
41
+ profile: {
42
+ entity: entity || {
43
+ uri: 'entities/uri1',
44
+ type: 'configuration/entityTypes/HCO'
45
+ }
46
+ },
47
+ tenant: {
48
+ id: 't1'
49
+ },
50
+ metadata: {
51
+ t1: metadata
52
+ }
53
+ });
54
+
55
+ describe('useSelectedEntity behavior', () => {
56
+ const dispatch = jest.fn();
57
+ let store;
58
+
59
+ const setUp = (method: typeof shallow | typeof mount = shallow, customStore?) => {
60
+ store = customStore || createStore();
61
+ return (method as typeof shallow)(<GraphPerspectiveView />);
62
+ };
63
+
64
+ beforeAll(() => {
65
+ jest.spyOn(reactRedux, 'useDispatch').mockReturnValue(dispatch);
66
+ jest.spyOn(reactRedux, 'useSelector').mockImplementation((selector) => selector(store));
67
+ });
68
+
69
+ afterEach(() => {
70
+ jest.clearAllMocks();
71
+ });
72
+
73
+ it('should request entity on onEntitySelect and set value to GraphStateContext.Provider', async () => {
74
+ const mainEntity = {
75
+ uri: 'entities/uri1',
76
+ type: 'configuration/entityTypes/HCO'
77
+ };
78
+ const entity = {
79
+ uri: 'entities/1',
80
+ type: '123'
81
+ };
82
+ const data = {entities: [{uri: '1'}], relations: []};
83
+ (getHops as jest.Mock).mockReturnValue(Promise.resolve(data));
84
+ (getEntity as jest.Mock).mockReturnValue(Promise.resolve(entity));
85
+ const component = setUp(mount, createStore({entity: mainEntity}));
86
+ expect(component.find(GraphStateContext.Provider)).toHaveLength(1);
87
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
88
+ selectedEntity: null,
89
+ selectedEntityLoading: true
90
+ });
91
+ await act(async () => {
92
+ await Promise.resolve();
93
+ });
94
+ component.update();
95
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
96
+ selectedEntity: mainEntity, // main entity is selected by default
97
+ selectedEntityLoading: false
98
+ });
99
+ expect(getHops).toHaveBeenCalled();
100
+ expect(getEntity).not.toHaveBeenCalled();
101
+ await act(async () => {
102
+ await Promise.resolve();
103
+ });
104
+ component.update();
105
+ component.find(GraphStateContext.Provider).prop('value').onEntitySelect(entity.uri);
106
+ component.update();
107
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
108
+ selectedEntity: mainEntity,
109
+ selectedEntityLoading: true
110
+ });
111
+ expect(getEntity).toHaveBeenCalledWith(entity.uri);
112
+ await act(async () => {
113
+ await Promise.resolve();
114
+ });
115
+ component.update();
116
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
117
+ selectedEntity: entity,
118
+ selectedEntityLoading: false
119
+ });
120
+ });
121
+
122
+ it('should dispatch an error in case of failed entity request', async () => {
123
+ const error = {errorMessage: 'Error!!'};
124
+ const mainEntity = {
125
+ uri: 'entities/uri1',
126
+ type: 'configuration/entityTypes/HCO'
127
+ };
128
+ (getEntity as jest.Mock).mockReturnValue(Promise.reject(error));
129
+ const component = setUp(mount, createStore({entity: mainEntity}));
130
+ expect(component.find(GraphStateContext.Provider)).toHaveLength(1);
131
+ expect(getEntity).not.toHaveBeenCalled();
132
+ component.find(GraphStateContext.Provider).prop('value').onEntitySelect('entities/some');
133
+ component.update();
134
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
135
+ selectedEntity: null,
136
+ selectedEntityLoading: true
137
+ });
138
+ expect(getEntity).toHaveBeenCalledWith('entities/some');
139
+ await act(async () => {
140
+ await Promise.resolve();
141
+ });
142
+ component.update();
143
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
144
+ selectedEntity: mainEntity,
145
+ selectedEntityLoading: false
146
+ });
147
+ expect(dispatch).toHaveBeenCalledWith(ui.actions.errorSet(error.errorMessage));
148
+ });
149
+
150
+ it('should use brief entity info from "data" and set it as selectedEntity before entity request', async () => {
151
+ const mainEntity = {
152
+ uri: 'entities/uri1',
153
+ type: 'configuration/entityTypes/HCO'
154
+ };
155
+ const briefEntityInfo = {
156
+ uri: 'entities/1',
157
+ type: '123'
158
+ };
159
+ const entity = {
160
+ uri: 'entities/1',
161
+ type: '123',
162
+ attributes: {}
163
+ };
164
+ const data = {entities: [{uri: '1'}, briefEntityInfo], relations: []};
165
+ (getHops as jest.Mock).mockReturnValue(Promise.resolve(data));
166
+ (getEntity as jest.Mock).mockReturnValue(Promise.resolve(entity));
167
+ const component = setUp(mount, createStore({entity: mainEntity}));
168
+ expect(component.find(GraphStateContext.Provider)).toHaveLength(1);
169
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
170
+ selectedEntity: null,
171
+ selectedEntityLoading: true
172
+ });
173
+ await act(async () => {
174
+ await Promise.resolve();
175
+ });
176
+ component.update();
177
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
178
+ selectedEntity: mainEntity,
179
+ selectedEntityLoading: false
180
+ });
181
+ expect(getHops).toHaveBeenCalled();
182
+ expect(getEntity).not.toHaveBeenCalled();
183
+ await act(async () => {
184
+ await Promise.resolve();
185
+ });
186
+ component.update();
187
+ component.find(GraphStateContext.Provider).prop('value').onEntitySelect(entity.uri);
188
+ component.update();
189
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
190
+ selectedEntity: briefEntityInfo,
191
+ selectedEntityLoading: true
192
+ });
193
+ expect(getEntity).toHaveBeenCalledWith(entity.uri);
194
+ await act(async () => {
195
+ await Promise.resolve();
196
+ });
197
+ component.update();
198
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
199
+ selectedEntity: entity,
200
+ selectedEntityLoading: false
201
+ });
202
+ });
203
+
204
+ it('should make request for each uniq entity only once', async () => {
205
+ const mainEntity = {
206
+ uri: 'entities/uri1',
207
+ type: 'configuration/entityTypes/HCO'
208
+ };
209
+ const briefEntityInfo = {
210
+ uri: 'entities/1',
211
+ type: '123'
212
+ };
213
+ const briefEntityInfo2 = {
214
+ uri: 'entities/2',
215
+ type: '123'
216
+ };
217
+ const entity = {
218
+ uri: 'entities/1',
219
+ type: '123',
220
+ attributes: {}
221
+ };
222
+ const entity2 = {
223
+ uri: 'entities/2',
224
+ type: '123',
225
+ attributes: {}
226
+ };
227
+ const data = {entities: [{uri: '1'}, briefEntityInfo, briefEntityInfo2], relations: []};
228
+ (getHops as jest.Mock).mockReturnValue(Promise.resolve(data));
229
+ (getEntity as jest.Mock).mockReturnValue(Promise.resolve(entity));
230
+ const component = setUp(mount, createStore({entity: mainEntity}));
231
+ expect(component.find(GraphStateContext.Provider)).toHaveLength(1);
232
+ expect(getHops).toHaveBeenCalled();
233
+ expect(getEntity).not.toHaveBeenCalled();
234
+ await act(async () => {
235
+ await Promise.resolve();
236
+ });
237
+ component.update();
238
+ // first entity selection
239
+ component.find(GraphStateContext.Provider).prop('value').onEntitySelect(entity.uri);
240
+ component.update();
241
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
242
+ selectedEntity: briefEntityInfo,
243
+ selectedEntityLoading: true
244
+ });
245
+ expect(getEntity).toHaveBeenCalledWith(entity.uri);
246
+ await act(async () => {
247
+ await Promise.resolve();
248
+ });
249
+ component.update();
250
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
251
+ selectedEntity: entity,
252
+ selectedEntityLoading: false
253
+ });
254
+
255
+ // first entity2 selection
256
+ (getEntity as jest.Mock).mockReturnValue(Promise.resolve(entity2));
257
+ component.find(GraphStateContext.Provider).prop('value').onEntitySelect(entity2.uri);
258
+ component.update();
259
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
260
+ selectedEntity: briefEntityInfo2,
261
+ selectedEntityLoading: true
262
+ });
263
+ expect(getEntity).toHaveBeenCalledWith(entity2.uri);
264
+ await act(async () => {
265
+ await Promise.resolve();
266
+ });
267
+ component.update();
268
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
269
+ selectedEntity: entity2,
270
+ selectedEntityLoading: false
271
+ });
272
+
273
+ //second entity selection
274
+ component.find(GraphStateContext.Provider).prop('value').onEntitySelect(entity.uri);
275
+ component.update();
276
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
277
+ selectedEntity: briefEntityInfo,
278
+ selectedEntityLoading: true
279
+ });
280
+ await act(async () => {
281
+ await Promise.resolve();
282
+ });
283
+ component.update();
284
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
285
+ selectedEntity: entity,
286
+ selectedEntityLoading: false
287
+ });
288
+
289
+ //second entity2 selection
290
+ component.find(GraphStateContext.Provider).prop('value').onEntitySelect(entity2.uri);
291
+ component.update();
292
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
293
+ selectedEntity: briefEntityInfo2,
294
+ selectedEntityLoading: true
295
+ });
296
+ await act(async () => {
297
+ await Promise.resolve();
298
+ });
299
+ component.update();
300
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
301
+ selectedEntity: entity2,
302
+ selectedEntityLoading: false
303
+ });
304
+
305
+ expect(getEntity).toHaveBeenCalledTimes(2);
306
+ });
307
+
308
+ it('should set current entity if no selected entity in the new data', async () => {
309
+ const mainEntity = {
310
+ uri: 'entities/uri1',
311
+ type: 'configuration/entityTypes/HCO'
312
+ };
313
+ const entityInfo = {
314
+ uri: 'entities/1',
315
+ type: '123'
316
+ };
317
+ const entityInfo2 = {
318
+ uri: 'entities/2',
319
+ type: '123'
320
+ };
321
+ const entity = {
322
+ uri: 'entities/1',
323
+ type: '123',
324
+ attributes: {}
325
+ };
326
+ const data = {entities: [{uri: '1'}, entityInfo, entityInfo2], relations: []};
327
+ (getHops as jest.Mock).mockReturnValue(Promise.resolve(data));
328
+ (getEntity as jest.Mock).mockReturnValue(Promise.resolve(entity));
329
+
330
+ const component = setUp(mount, createStore({entity: mainEntity}));
331
+ expect(component.find(GraphStateContext.Provider)).toHaveLength(1);
332
+ expect(getHops).toHaveBeenCalled();
333
+ expect(getEntity).not.toHaveBeenCalled();
334
+ await act(async () => {
335
+ await Promise.resolve();
336
+ });
337
+ component.update();
338
+
339
+ // entity selection
340
+ component.find(GraphStateContext.Provider).prop('value').onEntitySelect(entity.uri);
341
+ component.update();
342
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
343
+ selectedEntity: entityInfo,
344
+ selectedEntityLoading: true
345
+ });
346
+ expect(getEntity).toHaveBeenCalledWith(entity.uri);
347
+ await act(async () => {
348
+ await Promise.resolve();
349
+ });
350
+ component.update();
351
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
352
+ selectedEntity: entity,
353
+ selectedEntityLoading: false
354
+ });
355
+
356
+ // new data
357
+ const newData = {entities: [{uri: '1'}], relations: []};
358
+ (getHops as jest.Mock).mockReturnValue(Promise.resolve(newData));
359
+ // reload data
360
+ component
361
+ .find(GraphStateContext.Provider)
362
+ .prop('value')
363
+ .setGraphTypeUri('configuration/graphTypes/FamilyGraph');
364
+ await act(async () => {
365
+ await Promise.resolve();
366
+ });
367
+ component.update();
368
+ expect(component.find(GraphStateContext.Provider).prop('value')).toMatchObject({
369
+ selectedEntity: mainEntity,
370
+ selectedEntityLoading: false
371
+ });
372
+ });
373
+ });
@@ -0,0 +1,34 @@
1
+ import {makeStyles} from '@mui/styles';
2
+
3
+ export const useStyles = makeStyles((theme) => ({
4
+ perspectiveView: {
5
+ position: 'absolute',
6
+ top: 0,
7
+ left: 0,
8
+ right: 0,
9
+ bottom: 0,
10
+ fontFamily: 'Roboto, Helvetica, Arial, sans-serif',
11
+ overflowX: 'hidden',
12
+ overflowY: 'auto',
13
+ display: 'flex',
14
+ flexDirection: 'column',
15
+ backgroundColor: theme.palette.background.default
16
+ },
17
+ graphWrapper: {
18
+ display: 'flex',
19
+ flexDirection: 'column',
20
+ overflow: 'hidden',
21
+ flexGrow: 1
22
+ },
23
+ graphContainer: {
24
+ display: 'flex',
25
+ overflow: 'hidden',
26
+ flexGrow: 1
27
+ },
28
+ '@global div[role=tooltip]': {
29
+ fontFamily: 'Roboto, Helvetica, Arial, sans-serif'
30
+ },
31
+ '@global div[role=presentation]': {
32
+ fontFamily: 'Roboto, Helvetica, Arial, sans-serif'
33
+ }
34
+ }));
@@ -0,0 +1,27 @@
1
+ import React, {memo} from 'react';
2
+ import {isNil} from 'ramda';
3
+ import {RightPanelTab, SidePanel} from '@reltio/components';
4
+ import RightPanelProfileBand from '../RightPanelProfileBand/RightPanelProfileBand';
5
+
6
+ export enum ActivePanel {
7
+ Relationship,
8
+ EntityDetails
9
+ }
10
+
11
+ type Props = {
12
+ active?: number;
13
+ tabs: RightPanelTab[];
14
+ };
15
+
16
+ export const GraphRightSidePanel = memo(({active, tabs}: Props) => {
17
+ const isOpen = !isNil(active);
18
+
19
+ return (
20
+ <SidePanel open={isOpen}>
21
+ <RightPanelProfileBand />
22
+ {tabs[active]?.content}
23
+ </SidePanel>
24
+ );
25
+ });
26
+
27
+ GraphRightSidePanel.displayName = 'GraphRightSidePanel';
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import {shallow} from 'enzyme';
3
+
4
+ import {GraphRightSidePanel} from '../GraphRightSidePanel';
5
+ import {SidePanel} from '@reltio/components';
6
+ import RightPanelProfileBand from '../../RightPanelProfileBand/RightPanelProfileBand';
7
+
8
+ const setUp = (props = {tabs: []}) => shallow(<GraphRightSidePanel {...props} />);
9
+
10
+ describe('GraphRightSidePanel tests', () => {
11
+ it('should render main components', () => {
12
+ const component = setUp();
13
+ expect(component.find(SidePanel)).toHaveLength(1);
14
+ expect(component.find(SidePanel).prop('open')).toBe(false);
15
+ expect(component.find(SidePanel).find(RightPanelProfileBand)).toHaveLength(1);
16
+ expect(component.find(SidePanel).children()).toHaveLength(1);
17
+ });
18
+ });
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M6 7V9H8V7H6ZM6 11V13H8V11H6ZM6 15V17H8V15H6ZM10 7V9H16.5H18V7H10ZM20 5V10.0193C20.8055 10.5342 21.4895 11.2219 22 12.0304V5V3.5V3H2V3.5V5V19V20V21H13.0276C12.2202 20.4894 11.5333 19.8054 11.019 19H4V5H20ZM10.4967 13C10.8078 12.2522 11.2545 11.5753 11.8061 11H10V13H10.4967ZM10 15.5C10 15.3317 10.0064 15.165 10.0189 15H10V15.5ZM10 15.5C10 16.0163 10.06 16.5185 10.1734 17H10V15.5ZM20.3 17.89L23.42 21L22 22.42L18.88 19.3C18.19 19.74 17.37 20 16.49 20C14.01 20 12 17.99 12 15.5C12 13.01 14.01 11 16.5 11C18.99 11 21 13.01 21 15.5C21 16.38 20.74 17.19 20.3 17.89ZM16.5 18C17.88 18 19 16.88 19 15.5C19 14.12 17.88 13 16.5 13C15.12 13 14 14.12 14 15.5C14 16.88 15.12 18 16.5 18Z" fill="currentColor"/>
3
+ </svg>
@@ -0,0 +1,8 @@
1
+ import {makeStyles} from '@mui/styles';
2
+
3
+ export const useStyles = makeStyles({
4
+ wrapper: {
5
+ display: 'flex',
6
+ overflow: 'hidden'
7
+ }
8
+ });
@@ -0,0 +1,56 @@
1
+ import {DropDownSelector, withContext} from '@reltio/components';
2
+ import i18n from 'ui-i18n';
3
+ import React, {useMemo} from 'react';
4
+ import {useStyles} from './styles';
5
+ import {GraphStateContext} from '../../contexts/GraphStateContext';
6
+ import {GraphState} from '../../types/graphDataTypes';
7
+ import {Entity, getGraphTypesForEntityType} from '@reltio/mdm-sdk';
8
+ import {useSelector} from 'react-redux';
9
+ import mdmModule from '@reltio/mdm-module';
10
+
11
+ type Props = Partial<Pick<GraphState, 'graphTypeUri' | 'setGraphTypeUri'>>;
12
+
13
+ const GraphTypeSelector = ({graphTypeUri, setGraphTypeUri}: Props) => {
14
+ const styles = useStyles();
15
+ const metadata = useSelector(mdmModule.selectors.getMetadata);
16
+ const entity: Entity = useSelector(mdmModule.selectors.getEntity);
17
+ const graphTypeOptions = useMemo(
18
+ () => [
19
+ {label: i18n.text('All'), value: null},
20
+ ...getGraphTypesForEntityType(metadata, entity.type).map(({uri, label}) => ({value: uri, label}))
21
+ ],
22
+ [entity, metadata]
23
+ );
24
+ const value = useMemo(
25
+ () => graphTypeOptions.find((opt) => opt.value === graphTypeUri),
26
+ [graphTypeOptions, graphTypeUri]
27
+ );
28
+ return (
29
+ <DropDownSelector
30
+ classes={{valueContainer: styles.valueContainer}}
31
+ className={styles.graphTypeSelector}
32
+ height={42}
33
+ label={i18n.text('Graph type')}
34
+ value={value}
35
+ options={graphTypeOptions}
36
+ onChange={(opt) => setGraphTypeUri(opt.value)}
37
+ TextFieldProps={{
38
+ InputProps: {
39
+ disableUnderline: true,
40
+ classes: {
41
+ root: styles.filledInputRoot
42
+ }
43
+ }
44
+ }}
45
+ />
46
+ );
47
+ };
48
+
49
+ export default withContext(
50
+ GraphStateContext,
51
+ ({graphTypeUri, setGraphTypeUri}) => ({
52
+ setGraphTypeUri,
53
+ graphTypeUri
54
+ }),
55
+ GraphTypeSelector
56
+ );
@@ -0,0 +1,109 @@
1
+ import React from 'react';
2
+ import {mount} from 'enzyme';
3
+ import GraphTypeSelector from '../GraphTypeSelector';
4
+ import {GraphStateContext} from '../../../contexts/GraphStateContext';
5
+ import {DropDownSelector} from '@reltio/components';
6
+ import * as reactRedux from 'react-redux';
7
+ import {GraphState} from '../../../types/graphDataTypes';
8
+
9
+ const onChangeGraphType = jest.fn();
10
+
11
+ const setUp = ({graphTypeUri = null} = {}) =>
12
+ mount(
13
+ <GraphStateContext.Provider
14
+ value={
15
+ {
16
+ graphTypeUri,
17
+ setGraphTypeUri: onChangeGraphType as (graphType: string) => void
18
+ } as GraphState
19
+ }
20
+ >
21
+ <GraphTypeSelector />
22
+ </GraphStateContext.Provider>
23
+ );
24
+
25
+ const tenant = 'uitest1';
26
+
27
+ const store = () => ({
28
+ tenant: {id: tenant},
29
+ metadata: {
30
+ [tenant]: {
31
+ entityTypes: [
32
+ {
33
+ uri: 'configuration/entityTypes/HCP',
34
+ extendsTypeURI: 'configuration/entityTypes/Individual'
35
+ },
36
+ {
37
+ uri: 'configuration/entityTypes/Individual',
38
+ extendsTypeURI: 'configuration/entityTypes/Party'
39
+ },
40
+ {
41
+ uri: 'configuration/entityTypes/Party'
42
+ }
43
+ ],
44
+ graphTypes: [
45
+ {
46
+ uri: 'configuration/graphTypes/FamilyGraph',
47
+ label: 'FamilyGraph',
48
+ relationshipTypeURIs: ['configuration/relationTypes/Family']
49
+ },
50
+ {
51
+ uri: 'configuration/graphTypes/CompanyHierarchy',
52
+ relationshipTypeURIs: [
53
+ 'configuration/relationTypes/Leased',
54
+ 'configuration/relationTypes/Subsidiary',
55
+ 'configuration/relationTypes/Owned'
56
+ ]
57
+ }
58
+ ],
59
+ relationTypes: [
60
+ {
61
+ uri: 'configuration/relationTypes/Family',
62
+ startObject: {
63
+ uri: 'configuration/relationTypes/Affiliation/startObject',
64
+ objectTypeURI: 'configuration/entityTypes/Party'
65
+ }
66
+ },
67
+ {
68
+ uri: 'configuration/relationTypes/Assistant',
69
+ startObject: {
70
+ objectTypeURI: 'configuration/entityTypes/Individual',
71
+ uri: 'configuration/relationTypes/Assistant/startObject'
72
+ }
73
+ }
74
+ ]
75
+ }
76
+ },
77
+ profile: {
78
+ entity: {
79
+ uri: 'entities/1IPdCSY1',
80
+ type: 'configuration/entityTypes/HCP'
81
+ }
82
+ }
83
+ });
84
+
85
+ describe('Graph tests', () => {
86
+ beforeAll(() => {
87
+ jest.spyOn(reactRedux, 'useSelector').mockImplementation((selector) => selector(store()));
88
+ });
89
+
90
+ it('should render DropDownSelector with options for graphType', () => {
91
+ const component = setUp();
92
+ expect(component.find(DropDownSelector)).toHaveLength(1);
93
+ expect(component.find(DropDownSelector).prop('label')).toEqual('Graph type');
94
+ expect(component.find(DropDownSelector).prop('value')).toEqual({value: null, label: 'All'});
95
+ expect(component.find(DropDownSelector).prop('options')).toEqual([
96
+ {value: null, label: 'All'},
97
+ {
98
+ value: 'configuration/graphTypes/FamilyGraph',
99
+ label: 'FamilyGraph'
100
+ }
101
+ ]);
102
+ expect(onChangeGraphType).not.toHaveBeenCalled();
103
+ component.find(DropDownSelector).prop('onChange')({
104
+ value: 'configuration/graphTypes/FamilyGraph',
105
+ label: 'FamilyGraph'
106
+ });
107
+ expect(onChangeGraphType).toHaveBeenCalledWith('configuration/graphTypes/FamilyGraph');
108
+ });
109
+ });
@@ -0,0 +1,17 @@
1
+ import {makeStyles} from '@mui/styles';
2
+
3
+ export const useStyles = makeStyles({
4
+ graphTypeSelector: {
5
+ minWidth: '200px',
6
+ backgroundColor: '#FAFAFA',
7
+ opacity: 1,
8
+ height: '40px'
9
+ },
10
+ filledInputRoot: {
11
+ borderRadius: '4px'
12
+ },
13
+ valueContainer: {
14
+ width: 'auto',
15
+ marginLeft: '16px'
16
+ }
17
+ });