@reltio/sources 1.4.1585 → 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 +38 -21
- package/public/bundle.js +205 -0
- package/public/bundle.js.LICENSE.txt +79 -0
- package/public/package.json +22 -0
- package/scripts/build/index.js +20 -0
- package/src/components/CrosswalkTreeView/CrosswalkTreeView.tsx +47 -0
- package/src/components/CrosswalkTreeView/__tests__/CrosswalkTreeView.spec.tsx +72 -0
- package/src/components/CrosswalkTreeView/__tests__/helpers.spec.ts +961 -0
- package/src/components/CrosswalkTreeView/helpers.ts +91 -0
- package/src/components/CrosswalkTreeView/styles.ts +10 -0
- package/src/components/EmptyState/EmptyState.tsx +20 -0
- package/src/components/EmptyState/__tests__/EmptyState.test.tsx +13 -0
- package/src/components/EmptyState/icons/EmptySources.svg +43 -0
- package/src/components/EmptyState/styles.ts +19 -0
- package/src/components/LegendTable/LegendTable.tsx +124 -0
- package/src/components/LegendTable/LegendTableRow/ContributorRow/ContributorRow.tsx +46 -0
- package/src/components/LegendTable/LegendTableRow/ContributorRow/__tests__/ContributorRow.test.tsx +103 -0
- package/src/components/LegendTable/LegendTableRow/ContributorRow/styles.ts +31 -0
- package/src/components/LegendTable/LegendTableRow/LegendTableRow.tsx +179 -0
- package/src/components/LegendTable/LegendTableRow/__tests__/LegendTableRow.test.tsx +371 -0
- package/src/components/LegendTable/LegendTableRow/styles.ts +31 -0
- package/src/components/LegendTable/__tests__/LegendTable.test.tsx +273 -0
- package/src/components/LegendTable/__tests__/helpers.test.ts +541 -0
- package/src/components/LegendTable/helpers.ts +64 -0
- package/src/components/LegendTable/styles.ts +17 -0
- package/src/components/LegendView/LegendView.tsx +201 -0
- package/src/components/LegendView/__tests__/LegendView.test.tsx +307 -0
- package/src/components/LegendView/styles.ts +51 -0
- package/src/components/RightSidePanel/RightSidePanel.tsx +25 -0
- package/src/components/RightSidePanel/__tests__/RightSidePanel.test.tsx +28 -0
- package/src/components/RightSidePanel/styles.ts +14 -0
- package/src/components/RulesestsSelector/RulesestsSelector.tsx +31 -0
- package/src/components/RulesestsSelector/RulesetOption/RulesetOption.tsx +25 -0
- package/src/components/RulesestsSelector/RulesetOption/__tests__/RulesetOption.test.tsx +25 -0
- package/src/components/RulesestsSelector/RulesetOption/styles.ts +27 -0
- package/src/components/RulesestsSelector/RulesetsMenuList/RulesetsMenuList.tsx +14 -0
- package/src/components/RulesestsSelector/__tests__/RulesetsSelector.test.tsx +91 -0
- package/src/components/RulesestsSelector/styles.ts +7 -0
- package/src/components/SankeyChart/Link.tsx +31 -0
- package/src/components/SankeyChart/MergeTooltip.tsx +37 -0
- package/src/components/SankeyChart/Node.tsx +137 -0
- package/src/components/SankeyChart/SankeyChart.tsx +103 -0
- package/src/components/SankeyChart/__tests__/Link.spec.tsx +127 -0
- package/src/components/SankeyChart/__tests__/MergeTooltip.spec.tsx +22 -0
- package/src/components/SankeyChart/__tests__/Node.spec.tsx +248 -0
- package/src/components/SankeyChart/__tests__/SankeyChart.spec.tsx +161 -0
- package/src/components/SankeyChart/__tests__/__snapshots__/SankeyChart.spec.tsx.snap +183 -0
- package/src/components/SankeyChart/sankey.ts +322 -0
- package/src/components/SankeyChart/styles.ts +41 -0
- package/src/components/SankeyChart/useSankey.tsx +44 -0
- package/src/components/SelectableTree/SelectableTree.tsx +46 -0
- package/src/components/SelectableTree/__tests__/SelectableTree.test.tsx +28 -0
- package/src/components/SelectableTree/__tests__/__snapshots__/SelectableTree.test.tsx.snap +59 -0
- package/src/components/SelectableTree/styles.ts +42 -0
- package/src/components/SourcesView/SourcesView.tsx +318 -0
- package/src/components/SourcesView/__tests__/IntegrationSourcesView.spec.tsx +199 -0
- package/src/components/SourcesView/__tests__/SourcesView.spec.tsx +903 -0
- package/src/components/SourcesView/__tests__/data/metadata.data.ts +27 -0
- package/src/components/SourcesView/__tests__/data/store.data.ts +65 -0
- package/src/components/SourcesView/icons/LegendIcon.svg +8 -0
- package/src/components/SourcesView/index.tsx +57 -0
- package/src/components/SourcesView/styles.ts +44 -0
- package/src/components/TreeActionSnackbar/TreeActionSnackbar.tsx +38 -0
- package/src/components/TreeActionSnackbar/__tests__/TreeActionSnackbar.test.tsx +38 -0
- package/src/components/TreeActionSnackbar/styles.ts +11 -0
- package/src/components/UnmergeDialog/UnmergeDialog.tsx +78 -0
- package/src/components/UnmergeDialog/__tests__/UnmergeDialog.test.tsx +124 -0
- package/src/components/UnmergeDialog/__tests__/testData.data.ts +271 -0
- package/src/components/UnmergeDialog/styles.ts +34 -0
- package/src/components/UnsubscribeDialog/UnsubscribeDialog.tsx +64 -0
- package/src/components/UnsubscribeDialog/__tests__/UnsubscribeDialog.test.tsx +59 -0
- package/src/components/UnsubscribeDialog/styles.ts +31 -0
- package/src/hooks/__tests__/useCrosswalkTree.specs.tsx +68 -0
- package/src/hooks/__tests__/useCrosswalkTreeActions.specs.ts +110 -0
- package/src/hooks/__tests__/useCrosswalksDisplay.specs.tsx +213 -0
- package/src/hooks/__tests__/useEntityWithSurvivorshipGroups.specs.ts +160 -0
- package/src/hooks/useCrosswalkTree.ts +38 -0
- package/src/hooks/useCrosswalkTreeActions.ts +83 -0
- package/src/hooks/useCrosswalksDisplay.ts +110 -0
- package/src/hooks/useEntityWithSurvivorshipGroups.tsx +51 -0
- package/src/icons/notMatch.svg +14 -0
- package/src/index.ts +1 -0
- package/src/services/errors.ts +11 -0
- package/src/types/LegendMode.ts +5 -0
- package/src/types/SankeyChartData.ts +31 -0
- package/src/types/SourcesSavedState.ts +3 -0
- package/src/types/UnmergeContributorEvent.ts +7 -0
- package/src/types/UnsubscribeContributorEvent.ts +6 -0
- package/src/types/index.ts +4 -0
- package/tsconfig.json +4 -0
- package/webpack.config.js +10 -0
- package/bundle.js +0 -2
- package/bundle.js.LICENSE.txt +0 -42
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import * as mdmSdk from '@reltio/mdm-sdk';
|
|
2
|
+
import {LegendMode} from '../../types';
|
|
3
|
+
import {useCrosswalksDisplay} from '../useCrosswalksDisplay';
|
|
4
|
+
import {renderHook, act} from '@testing-library/react-hooks';
|
|
5
|
+
|
|
6
|
+
jest.mock('@reltio/mdm-sdk', () => ({
|
|
7
|
+
...jest.requireActual<Record<string, unknown>>('@reltio/mdm-sdk'),
|
|
8
|
+
getSourceColor: jest.fn(),
|
|
9
|
+
getContributorColor: jest.fn(),
|
|
10
|
+
getCrosswalkColor: jest.fn(),
|
|
11
|
+
getCrosswalkId: jest.fn(),
|
|
12
|
+
findContributorForCrosswalk: jest.fn(),
|
|
13
|
+
debounce: (x) => x
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
describe('useCrosswalksDisplay behaviour', () => {
|
|
17
|
+
const getCrosswalksDisplay = (initialProps) => {
|
|
18
|
+
return renderHook(useCrosswalksDisplay, {initialProps}).result.current;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const contrCrosswalks = [{uri: 'testContrCrosswalk', type: 'test', value: 'test'}];
|
|
22
|
+
|
|
23
|
+
const getSourceColorMock = jest.spyOn(mdmSdk, 'getSourceColor').mockReturnValue('#111111');
|
|
24
|
+
const getCrosswalkColorMock = jest.spyOn(mdmSdk, 'getCrosswalkColor').mockReturnValue('#000000');
|
|
25
|
+
const getCrosswalkIdMock = jest.spyOn(mdmSdk, 'getCrosswalkId').mockReturnValue('testId');
|
|
26
|
+
const getContributorColorMock = jest.spyOn(mdmSdk, 'getContributorColor').mockReturnValue('#FFFFFF');
|
|
27
|
+
const findContributorForCrosswalkMock = jest
|
|
28
|
+
.spyOn(mdmSdk, 'findContributorForCrosswalk')
|
|
29
|
+
.mockReturnValue({uri: 'testContrId', crosswalks: contrCrosswalks});
|
|
30
|
+
|
|
31
|
+
const contributors = [{uri: 'test'}];
|
|
32
|
+
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
jest.clearAllMocks();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should return correct getCrosswalkColor function for LegendMode.Crosswalk', () => {
|
|
38
|
+
const {getCrosswalkColor} = getCrosswalksDisplay({
|
|
39
|
+
activeMode: LegendMode.Crosswalk,
|
|
40
|
+
contributors: contributors
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const crosswalk = {uri: 'testCrosswalk', type: 'testType', value: 'testValue'};
|
|
44
|
+
|
|
45
|
+
const color = getCrosswalkColor(crosswalk);
|
|
46
|
+
expect(getCrosswalkIdMock).toBeCalledWith(crosswalk);
|
|
47
|
+
expect(getCrosswalkColorMock).toBeCalledWith('testId');
|
|
48
|
+
expect(color).toBe('#000000');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should return correct getCrosswalkColor function for LegendMode.Source', () => {
|
|
52
|
+
const {getCrosswalkColor} = getCrosswalksDisplay({
|
|
53
|
+
activeMode: LegendMode.Source,
|
|
54
|
+
contributors: contributors
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const crosswalk = {uri: 'testCrosswalk', type: 'testType', value: 'testValue'};
|
|
58
|
+
|
|
59
|
+
const color = getCrosswalkColor(crosswalk);
|
|
60
|
+
expect(getSourceColorMock).toBeCalledWith(crosswalk.type);
|
|
61
|
+
expect(color).toBe('#111111');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should return correct getCrosswalkColor function for LegendMode.Contributor', () => {
|
|
65
|
+
const {getCrosswalkColor} = getCrosswalksDisplay({
|
|
66
|
+
activeMode: LegendMode.Contributor,
|
|
67
|
+
contributors: contributors
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const crosswalk = {uri: 'testCrosswalk', type: 'testType', value: 'testValue'};
|
|
71
|
+
|
|
72
|
+
const color = getCrosswalkColor(crosswalk);
|
|
73
|
+
expect(findContributorForCrosswalkMock).toBeCalledWith(contributors, crosswalk);
|
|
74
|
+
expect(getContributorColorMock).toBeCalledWith('testContrId');
|
|
75
|
+
expect(color).toBe('#FFFFFF');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should return empty array of highlighted crosswalks by default', () => {
|
|
79
|
+
const {highlightedCrosswalks} = getCrosswalksDisplay({
|
|
80
|
+
activeMode: LegendMode.Contributor,
|
|
81
|
+
contributors: contributors
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
expect(highlightedCrosswalks).toEqual([]);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should return empty array of focused crosswalks by default', () => {
|
|
88
|
+
const {focusedCrosswalks} = getCrosswalksDisplay({
|
|
89
|
+
activeMode: LegendMode.Contributor,
|
|
90
|
+
contributors: contributors
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(focusedCrosswalks).toEqual([]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should return correct setCrosswalkHighlighted function', () => {
|
|
97
|
+
const initialProps = {
|
|
98
|
+
activeMode: LegendMode.Crosswalk,
|
|
99
|
+
contributors: contributors
|
|
100
|
+
};
|
|
101
|
+
const {result, rerender} = renderHook(useCrosswalksDisplay, {initialProps});
|
|
102
|
+
|
|
103
|
+
const crosswalk = {uri: 'testCrosswalk', type: 'testType', value: 'testValue'};
|
|
104
|
+
|
|
105
|
+
result.current.setCrosswalkHighlighted(undefined, true);
|
|
106
|
+
expect(result.current.highlightedCrosswalks).toEqual([]);
|
|
107
|
+
|
|
108
|
+
act(() => {
|
|
109
|
+
result.current.setCrosswalkHighlighted(crosswalk, true);
|
|
110
|
+
});
|
|
111
|
+
expect(result.current.highlightedCrosswalks).toEqual([crosswalk]);
|
|
112
|
+
|
|
113
|
+
act(() => {
|
|
114
|
+
result.current.setCrosswalkHighlighted(crosswalk, false);
|
|
115
|
+
});
|
|
116
|
+
expect(result.current.highlightedCrosswalks).toEqual([]);
|
|
117
|
+
|
|
118
|
+
initialProps.activeMode = LegendMode.Contributor;
|
|
119
|
+
rerender();
|
|
120
|
+
act(() => {
|
|
121
|
+
result.current.setCrosswalkHighlighted(crosswalk, true);
|
|
122
|
+
});
|
|
123
|
+
expect(findContributorForCrosswalkMock).toBeCalledWith(contributors, crosswalk);
|
|
124
|
+
expect(result.current.highlightedCrosswalks).toEqual([crosswalk, ...contrCrosswalks]);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should return correct toggleCrosswalkFocus function', () => {
|
|
128
|
+
const initialProps = {
|
|
129
|
+
activeMode: LegendMode.Crosswalk,
|
|
130
|
+
contributors: contributors
|
|
131
|
+
};
|
|
132
|
+
const {result, rerender} = renderHook(useCrosswalksDisplay, {initialProps});
|
|
133
|
+
|
|
134
|
+
const crosswalk = {uri: 'testCrosswalk', type: 'testType', value: 'testValue'};
|
|
135
|
+
|
|
136
|
+
result.current.toggleCrosswalkFocus(undefined);
|
|
137
|
+
expect(result.current.highlightedCrosswalks).toEqual([]);
|
|
138
|
+
expect(result.current.focusedCrosswalks).toEqual([]);
|
|
139
|
+
|
|
140
|
+
act(() => {
|
|
141
|
+
result.current.toggleCrosswalkFocus(crosswalk);
|
|
142
|
+
});
|
|
143
|
+
expect(result.current.highlightedCrosswalks).toEqual([crosswalk]);
|
|
144
|
+
expect(result.current.focusedCrosswalks).toEqual([crosswalk]);
|
|
145
|
+
|
|
146
|
+
act(() => {
|
|
147
|
+
result.current.toggleCrosswalkFocus(crosswalk);
|
|
148
|
+
});
|
|
149
|
+
expect(result.current.highlightedCrosswalks).toEqual([]);
|
|
150
|
+
expect(result.current.focusedCrosswalks).toEqual([]);
|
|
151
|
+
|
|
152
|
+
initialProps.activeMode = LegendMode.Contributor;
|
|
153
|
+
rerender();
|
|
154
|
+
act(() => {
|
|
155
|
+
result.current.toggleCrosswalkFocus(crosswalk);
|
|
156
|
+
});
|
|
157
|
+
expect(findContributorForCrosswalkMock).toBeCalledWith(contributors, crosswalk);
|
|
158
|
+
expect(result.current.highlightedCrosswalks).toEqual([crosswalk, ...contrCrosswalks]);
|
|
159
|
+
expect(result.current.focusedCrosswalks).toEqual([crosswalk, ...contrCrosswalks]);
|
|
160
|
+
|
|
161
|
+
act(() => {
|
|
162
|
+
result.current.toggleCrosswalkFocus(crosswalk);
|
|
163
|
+
});
|
|
164
|
+
expect(result.current.highlightedCrosswalks).toEqual([]);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should return correct highlightedCrosswalks when crosswalks focused and highlighted', () => {
|
|
168
|
+
const initialProps = {
|
|
169
|
+
activeMode: LegendMode.Crosswalk,
|
|
170
|
+
contributors: contributors
|
|
171
|
+
};
|
|
172
|
+
const {result} = renderHook(useCrosswalksDisplay, {initialProps});
|
|
173
|
+
|
|
174
|
+
const crosswalk = {uri: 'testCrosswalk', type: 'testType', value: 'testValue'};
|
|
175
|
+
const crosswalkHighlighted = {uri: 'testCrosswalk1', type: 'testType1', value: 'testValue1'};
|
|
176
|
+
|
|
177
|
+
act(() => {
|
|
178
|
+
result.current.toggleCrosswalkFocus(crosswalk);
|
|
179
|
+
result.current.setCrosswalkHighlighted(crosswalkHighlighted, true);
|
|
180
|
+
});
|
|
181
|
+
expect(result.current.highlightedCrosswalks).toEqual([crosswalkHighlighted, crosswalk]);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should reset focusedCrosswalks on entity change if focusedCrosswalks not empty', () => {
|
|
185
|
+
const initialProps = {
|
|
186
|
+
activeMode: LegendMode.Crosswalk,
|
|
187
|
+
contributors: contributors,
|
|
188
|
+
entity: {
|
|
189
|
+
uri: 'entities/uri1',
|
|
190
|
+
type: 'configuration/entityTypes/HCO'
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
const {result, rerender} = renderHook(useCrosswalksDisplay, {initialProps});
|
|
194
|
+
const crosswalk = {uri: 'testCrosswalk', type: 'testType', value: 'testValue'};
|
|
195
|
+
|
|
196
|
+
act(() => {
|
|
197
|
+
result.current.toggleCrosswalkFocus(crosswalk);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
expect(result.current.focusedCrosswalks).toEqual([crosswalk]);
|
|
201
|
+
|
|
202
|
+
rerender(initialProps);
|
|
203
|
+
expect(result.current.focusedCrosswalks).toEqual([crosswalk]);
|
|
204
|
+
|
|
205
|
+
initialProps.entity = {
|
|
206
|
+
uri: 'entities/uri2',
|
|
207
|
+
type: 'configuration/entityTypes/HCO2'
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
rerender(initialProps);
|
|
211
|
+
expect(result.current.focusedCrosswalks).toEqual([]);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import {act, renderHook} from '@testing-library/react-hooks';
|
|
2
|
+
import * as reactRedux from 'react-redux';
|
|
3
|
+
import * as mdmSdk from '@reltio/mdm-sdk';
|
|
4
|
+
import {useEntityWithSurvivorshipGroups} from '../useEntityWithSurvivorshipGroups';
|
|
5
|
+
|
|
6
|
+
jest.mock('@reltio/mdm-sdk', () => ({
|
|
7
|
+
...jest.requireActual<Record<string, unknown>>('@reltio/mdm-sdk'),
|
|
8
|
+
getEntityBySurvivorshipGroupUri: jest.fn()
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
const survivorshipGroups = [
|
|
12
|
+
{
|
|
13
|
+
uri: 'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups2cwLEgWAo',
|
|
14
|
+
label: 'tests45',
|
|
15
|
+
description: 'rerere',
|
|
16
|
+
default: true,
|
|
17
|
+
mapping: []
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
uri: 'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups3aGSPnPlj',
|
|
21
|
+
label: 'l1',
|
|
22
|
+
description: 'd1',
|
|
23
|
+
default: false,
|
|
24
|
+
mapping: []
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const store = {
|
|
29
|
+
tenant: {
|
|
30
|
+
id: 'sokol'
|
|
31
|
+
},
|
|
32
|
+
metadata: {
|
|
33
|
+
sokol: {
|
|
34
|
+
entityTypes: [{uri: 'configuration/entityTypes/HCP', survivorshipGroups}]
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const defaultEntity = {
|
|
40
|
+
uri: 'entities/1',
|
|
41
|
+
type: 'configuration/entityTypes/HCP',
|
|
42
|
+
attributes: {
|
|
43
|
+
CountryCode: [
|
|
44
|
+
{
|
|
45
|
+
lookupCode: 'IT',
|
|
46
|
+
lookupRawValue: 'IT',
|
|
47
|
+
ov: true,
|
|
48
|
+
type: 'configuration/entityTypes/HCP/attributes/CountryCode',
|
|
49
|
+
uri: 'entities/1864oxoO/attributes/CountryCode/3TFgmPUK5',
|
|
50
|
+
value: 'Italy'
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const loadedEntity = {
|
|
57
|
+
uri: 'entities/1',
|
|
58
|
+
type: 'configuration/entityTypes/HCP',
|
|
59
|
+
attributes: {
|
|
60
|
+
CountryCode: [
|
|
61
|
+
{
|
|
62
|
+
lookupCode: 'IT',
|
|
63
|
+
lookupRawValue: 'IT',
|
|
64
|
+
ov: false,
|
|
65
|
+
type: 'configuration/entityTypes/HCP/attributes/CountryCode',
|
|
66
|
+
uri: 'entities/1864oxoO/attributes/CountryCode/3TFgmPUK5',
|
|
67
|
+
value: 'Italy'
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
describe('useEntityWithSurvivorshipGroups behaviour', () => {
|
|
74
|
+
const getEntityBySurvivorshipGroupUriSpy = jest.spyOn(mdmSdk, 'getEntityBySurvivorshipGroupUri');
|
|
75
|
+
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
jest.spyOn(reactRedux, 'useSelector').mockImplementation((selector) => selector(store));
|
|
78
|
+
getEntityBySurvivorshipGroupUriSpy.mockResolvedValue(loadedEntity);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
afterEach(() => {
|
|
82
|
+
jest.clearAllMocks();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should return survivorshipGroups correctly', () => {
|
|
86
|
+
const {result} = renderHook(useEntityWithSurvivorshipGroups, {initialProps: defaultEntity});
|
|
87
|
+
expect(result.current.survivorshipGroups).toEqual(survivorshipGroups);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should return survivorshipGroups as empty array by default if entity is null', () => {
|
|
91
|
+
const {result} = renderHook(useEntityWithSurvivorshipGroups, {initialProps: null});
|
|
92
|
+
expect(result.current.survivorshipGroups).toEqual([]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should set default entity and default currentSurvivorshipGroupUri correctly', () => {
|
|
96
|
+
const {result} = renderHook(useEntityWithSurvivorshipGroups, {initialProps: defaultEntity});
|
|
97
|
+
expect(result.current.currentSurvivorshipGroupUri).toBe(
|
|
98
|
+
'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups2cwLEgWAo'
|
|
99
|
+
);
|
|
100
|
+
expect(result.current.entity).toEqual(defaultEntity);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('onChangeSurvivorshipGroup handler should work correctly with not default uri param ', async () => {
|
|
104
|
+
const {result} = renderHook(useEntityWithSurvivorshipGroups, {initialProps: defaultEntity});
|
|
105
|
+
expect(result.current.currentSurvivorshipGroupUri).toBe(
|
|
106
|
+
'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups2cwLEgWAo'
|
|
107
|
+
);
|
|
108
|
+
expect(result.current.entity).toEqual(defaultEntity);
|
|
109
|
+
expect(result.current.isLoading).toBe(false);
|
|
110
|
+
act(() => {
|
|
111
|
+
result.current.onChangeSurvivorshipGroup(
|
|
112
|
+
'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups3aGSPnPlj'
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
expect(result.current.currentSurvivorshipGroupUri).toBe(
|
|
116
|
+
'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups3aGSPnPlj'
|
|
117
|
+
);
|
|
118
|
+
expect(result.current.isLoading).toBe(true);
|
|
119
|
+
expect(getEntityBySurvivorshipGroupUriSpy).toHaveBeenCalledWith(
|
|
120
|
+
'entities/1',
|
|
121
|
+
'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups3aGSPnPlj'
|
|
122
|
+
);
|
|
123
|
+
await act(async () => {
|
|
124
|
+
return Promise.resolve();
|
|
125
|
+
});
|
|
126
|
+
expect(result.current.isLoading).toBe(false);
|
|
127
|
+
expect(result.current.entity).toEqual(loadedEntity);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('onChangeSurvivorshipGroup handler should work correctly with default uri param ', async () => {
|
|
131
|
+
const {result} = renderHook(useEntityWithSurvivorshipGroups, {initialProps: defaultEntity});
|
|
132
|
+
await act(async () => {
|
|
133
|
+
result.current.onChangeSurvivorshipGroup(
|
|
134
|
+
'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups3aGSPnPlj'
|
|
135
|
+
);
|
|
136
|
+
return Promise.resolve();
|
|
137
|
+
});
|
|
138
|
+
expect(getEntityBySurvivorshipGroupUriSpy).toHaveBeenCalledTimes(1);
|
|
139
|
+
expect(result.current.entity).toEqual(loadedEntity);
|
|
140
|
+
act(() => {
|
|
141
|
+
result.current.onChangeSurvivorshipGroup(
|
|
142
|
+
'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups2cwLEgWAo'
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
expect(getEntityBySurvivorshipGroupUriSpy).toHaveBeenCalledTimes(1);
|
|
146
|
+
expect(result.current.entity).toEqual(defaultEntity);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should return isDefaultSurvivorshipGroupUri correctly', async () => {
|
|
150
|
+
const {result} = renderHook(useEntityWithSurvivorshipGroups, {initialProps: defaultEntity});
|
|
151
|
+
expect(result.current.isDefaultSurvivorshipGroupUri).toBe(true);
|
|
152
|
+
await act(async () => {
|
|
153
|
+
result.current.onChangeSurvivorshipGroup(
|
|
154
|
+
'configuration/entityTypes/HCP/survivorshipGroups/survivorshipGroups3aGSPnPlj'
|
|
155
|
+
);
|
|
156
|
+
return Promise.resolve();
|
|
157
|
+
});
|
|
158
|
+
expect(result.current.isDefaultSurvivorshipGroupUri).toBe(false);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {useCallback, useEffect, useState} from 'react';
|
|
2
|
+
import {getCrosswalkTree, CrosswalkTree} from '@reltio/mdm-sdk';
|
|
3
|
+
import {noop, useSafePromise} from '@reltio/components';
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
entityUri?: string;
|
|
7
|
+
onSuccess?: () => void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const useCrosswalkTree = ({entityUri, onSuccess = noop}: Props) => {
|
|
11
|
+
const [crosswalkTree, setCrosswalkTree] = useState<CrosswalkTree>(null);
|
|
12
|
+
const safePromise = useSafePromise();
|
|
13
|
+
|
|
14
|
+
const onError = (e) => {
|
|
15
|
+
console.warn('Failed to load crosswalk tree', e);
|
|
16
|
+
setCrosswalkTree(null);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const loadData = useCallback(() => {
|
|
20
|
+
if (entityUri) {
|
|
21
|
+
safePromise(getCrosswalkTree({entityUri}))
|
|
22
|
+
.then((results) => {
|
|
23
|
+
setCrosswalkTree(results);
|
|
24
|
+
})
|
|
25
|
+
.catch(onError)
|
|
26
|
+
.finally(onSuccess);
|
|
27
|
+
} else {
|
|
28
|
+
setCrosswalkTree(null);
|
|
29
|
+
onSuccess();
|
|
30
|
+
}
|
|
31
|
+
}, [entityUri, onSuccess]);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
loadData();
|
|
35
|
+
}, [loadData]);
|
|
36
|
+
|
|
37
|
+
return {crosswalkTree, reload: loadData};
|
|
38
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {useCallback} from 'react';
|
|
2
|
+
import {useSelector} from 'react-redux';
|
|
3
|
+
import {andThen, pipe} from 'ramda';
|
|
4
|
+
import i18n from 'ui-i18n';
|
|
5
|
+
import mdm from '@reltio/mdm-module';
|
|
6
|
+
import {
|
|
7
|
+
Entity,
|
|
8
|
+
unmergeContributor as unmergeContributorRequest,
|
|
9
|
+
unsubscribeEntityFromDataTenantEntity
|
|
10
|
+
} from '@reltio/mdm-sdk';
|
|
11
|
+
import {useCrosswalkActions, noop} from '@reltio/components';
|
|
12
|
+
import {UnmergeContributorEvent, UnsubscribeContributorEvent} from '../types';
|
|
13
|
+
|
|
14
|
+
type Props = {
|
|
15
|
+
onLoad?: () => void;
|
|
16
|
+
onSuccess?: () => void;
|
|
17
|
+
onError?: (error: unknown) => void;
|
|
18
|
+
onShowMessage?: (message: string, entity?: Entity) => void;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const useCrosswalkTreeActions = ({
|
|
22
|
+
onLoad = noop,
|
|
23
|
+
onSuccess = noop,
|
|
24
|
+
onError = noop,
|
|
25
|
+
onShowMessage = noop
|
|
26
|
+
}: Props) => {
|
|
27
|
+
const {addCrosswalk, editCrosswalk, deleteCrosswalk} = useCrosswalkActions({onLoad, onSuccess, onError});
|
|
28
|
+
const dtssPath = useSelector(mdm.selectors.getDtssPath);
|
|
29
|
+
const tenant = useSelector(mdm.selectors.getTenant);
|
|
30
|
+
|
|
31
|
+
const handleAction = useCallback(
|
|
32
|
+
(request: Promise<unknown>) => {
|
|
33
|
+
onLoad();
|
|
34
|
+
request
|
|
35
|
+
.then(() => {
|
|
36
|
+
onSuccess();
|
|
37
|
+
})
|
|
38
|
+
.catch(onError);
|
|
39
|
+
},
|
|
40
|
+
[onLoad, onError, onSuccess]
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const unmergeContributor = useCallback(
|
|
44
|
+
(event: UnmergeContributorEvent) =>
|
|
45
|
+
pipe(
|
|
46
|
+
unmergeContributorRequest,
|
|
47
|
+
andThen((response) => {
|
|
48
|
+
onShowMessage(i18n.text('has been unmerged'), response.b);
|
|
49
|
+
return response;
|
|
50
|
+
}),
|
|
51
|
+
handleAction
|
|
52
|
+
)(event),
|
|
53
|
+
[handleAction, onShowMessage]
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const unsubscribeContributor = useCallback(
|
|
57
|
+
({crosswalk, dataTenant}: UnsubscribeContributorEvent) =>
|
|
58
|
+
pipe(
|
|
59
|
+
unsubscribeEntityFromDataTenantEntity,
|
|
60
|
+
andThen((response) => {
|
|
61
|
+
if (!response.successful) throw new Error(i18n.text('Failed to unsubscribe contributor'));
|
|
62
|
+
return response;
|
|
63
|
+
}),
|
|
64
|
+
handleAction
|
|
65
|
+
)({
|
|
66
|
+
dtssPath,
|
|
67
|
+
value: crosswalk.value,
|
|
68
|
+
type: crosswalk.type,
|
|
69
|
+
sourceTable: crosswalk.sourceTable,
|
|
70
|
+
dataTenant: dataTenant.id,
|
|
71
|
+
customerTenant: tenant
|
|
72
|
+
}),
|
|
73
|
+
[handleAction, dtssPath, tenant]
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
addCrosswalk,
|
|
78
|
+
editCrosswalk,
|
|
79
|
+
deleteCrosswalk,
|
|
80
|
+
unmergeContributor,
|
|
81
|
+
unsubscribeContributor
|
|
82
|
+
};
|
|
83
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {useCallback, useEffect, useMemo, useState, useRef} from 'react';
|
|
2
|
+
import {any, concat} from 'ramda';
|
|
3
|
+
import {LegendMode} from '../types';
|
|
4
|
+
import {
|
|
5
|
+
Contributor,
|
|
6
|
+
CrosswalkBase,
|
|
7
|
+
debounce,
|
|
8
|
+
Entity,
|
|
9
|
+
eqCrosswalks,
|
|
10
|
+
findContributorForCrosswalk,
|
|
11
|
+
getContributorColor,
|
|
12
|
+
getCrosswalkColor,
|
|
13
|
+
getCrosswalkId,
|
|
14
|
+
getSourceColor
|
|
15
|
+
} from '@reltio/mdm-sdk';
|
|
16
|
+
|
|
17
|
+
type Props = {
|
|
18
|
+
activeMode: LegendMode;
|
|
19
|
+
contributors: Contributor[];
|
|
20
|
+
entity: Entity;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const useCrosswalksDisplay = ({activeMode, contributors, entity}: Props) => {
|
|
24
|
+
const getCrosswalkColorForActiveMode = useCallback(
|
|
25
|
+
(crosswalk: CrosswalkBase) => {
|
|
26
|
+
switch (activeMode) {
|
|
27
|
+
case LegendMode.Source:
|
|
28
|
+
return getSourceColor(crosswalk.type);
|
|
29
|
+
case LegendMode.Contributor:
|
|
30
|
+
return getContributorColor(findContributorForCrosswalk(contributors, crosswalk)?.uri || '');
|
|
31
|
+
case LegendMode.Crosswalk:
|
|
32
|
+
return getCrosswalkColor(getCrosswalkId(crosswalk));
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
[activeMode, contributors]
|
|
36
|
+
);
|
|
37
|
+
const [highlightedCrosswalks, setHighlightedCrosswalks] = useState<CrosswalkBase[]>([]);
|
|
38
|
+
const highlightedCrosswalksCache = useRef([]);
|
|
39
|
+
const applyHighlightedCrosswalks = useCallback(
|
|
40
|
+
debounce(() => {
|
|
41
|
+
setHighlightedCrosswalks([...highlightedCrosswalksCache.current]);
|
|
42
|
+
}, 50),
|
|
43
|
+
[]
|
|
44
|
+
);
|
|
45
|
+
const cacheHighlightedCrosswalks = useCallback(
|
|
46
|
+
(arr) => {
|
|
47
|
+
highlightedCrosswalksCache.current = arr;
|
|
48
|
+
applyHighlightedCrosswalks(arr);
|
|
49
|
+
},
|
|
50
|
+
[applyHighlightedCrosswalks]
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const setCrosswalkHighlighted = useCallback(
|
|
54
|
+
(crosswalk: CrosswalkBase, highlighted: boolean) => {
|
|
55
|
+
if (!crosswalk) return;
|
|
56
|
+
if (highlighted) {
|
|
57
|
+
if (activeMode === LegendMode.Contributor) {
|
|
58
|
+
const contributor = findContributorForCrosswalk(contributors, crosswalk);
|
|
59
|
+
cacheHighlightedCrosswalks([crosswalk, ...(contributor?.crosswalks || [])]);
|
|
60
|
+
} else {
|
|
61
|
+
cacheHighlightedCrosswalks([crosswalk]);
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
cacheHighlightedCrosswalks([]);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
[activeMode, cacheHighlightedCrosswalks, contributors]
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const [focusedCrosswalks, setFocusedCrosswalks] = useState<CrosswalkBase[]>([]);
|
|
71
|
+
const calculateFocusedCrosswalks = useCallback(
|
|
72
|
+
(prev: CrosswalkBase[], next: CrosswalkBase[]) =>
|
|
73
|
+
concat(
|
|
74
|
+
prev.filter((prevCrosswalk) => !any(eqCrosswalks(prevCrosswalk), next)),
|
|
75
|
+
next.filter((nextCrosswalk) => !any(eqCrosswalks(nextCrosswalk), prev))
|
|
76
|
+
),
|
|
77
|
+
[]
|
|
78
|
+
);
|
|
79
|
+
const toggleCrosswalkFocus = useCallback(
|
|
80
|
+
(crosswalk: CrosswalkBase) => {
|
|
81
|
+
if (!crosswalk) return;
|
|
82
|
+
if (activeMode === LegendMode.Contributor) {
|
|
83
|
+
const contributor = findContributorForCrosswalk(contributors, crosswalk);
|
|
84
|
+
setFocusedCrosswalks((prevValue) =>
|
|
85
|
+
calculateFocusedCrosswalks([crosswalk, ...(contributor?.crosswalks || [])], prevValue)
|
|
86
|
+
);
|
|
87
|
+
} else {
|
|
88
|
+
setFocusedCrosswalks((prevValue) => calculateFocusedCrosswalks([crosswalk], prevValue));
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
[activeMode, calculateFocusedCrosswalks, contributors]
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (focusedCrosswalks.length) {
|
|
96
|
+
setFocusedCrosswalks([]);
|
|
97
|
+
}
|
|
98
|
+
}, [activeMode, entity]);
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
getCrosswalkColor: getCrosswalkColorForActiveMode,
|
|
102
|
+
highlightedCrosswalks: useMemo(
|
|
103
|
+
() => [...highlightedCrosswalks, ...focusedCrosswalks],
|
|
104
|
+
[highlightedCrosswalks, focusedCrosswalks]
|
|
105
|
+
),
|
|
106
|
+
focusedCrosswalks,
|
|
107
|
+
toggleCrosswalkFocus,
|
|
108
|
+
setCrosswalkHighlighted
|
|
109
|
+
};
|
|
110
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {useCallback, useEffect, useState} from 'react';
|
|
2
|
+
import {useSelector} from 'react-redux';
|
|
3
|
+
import {pipe, propOr, find, propEq, prop} from 'ramda';
|
|
4
|
+
import {getEntityType, getEntityBySurvivorshipGroupUri, Entity} from '@reltio/mdm-sdk';
|
|
5
|
+
import mdmModule from '@reltio/mdm-module';
|
|
6
|
+
import {useSafePromise} from '@reltio/components';
|
|
7
|
+
|
|
8
|
+
export const useEntityWithSurvivorshipGroups = (defaultEntity: Entity) => {
|
|
9
|
+
const entityTypeUri = defaultEntity?.type;
|
|
10
|
+
const metadata = useSelector(mdmModule.selectors.getMetadata);
|
|
11
|
+
const survivorshipGroups = pipe(getEntityType(metadata), propOr([], 'survivorshipGroups'))(entityTypeUri);
|
|
12
|
+
const defaultSurvivorshipGroupUri = pipe(find(propEq('default', true)), prop('uri'))(survivorshipGroups);
|
|
13
|
+
const [currentSurvivorshipGroupUri, setCurrentSurvivorshipGroupUri] = useState(null);
|
|
14
|
+
const [entity, setEntity] = useState(null);
|
|
15
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
16
|
+
const safePromise = useSafePromise();
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (defaultEntity) {
|
|
20
|
+
setEntity(defaultEntity);
|
|
21
|
+
setCurrentSurvivorshipGroupUri(defaultSurvivorshipGroupUri);
|
|
22
|
+
}
|
|
23
|
+
}, [defaultEntity, defaultSurvivorshipGroupUri]);
|
|
24
|
+
|
|
25
|
+
const onChangeSurvivorshipGroup = useCallback(
|
|
26
|
+
(survivorshipGroupUri: string) => {
|
|
27
|
+
setCurrentSurvivorshipGroupUri(survivorshipGroupUri);
|
|
28
|
+
const isDefaultSurvivorshipGroupUri = defaultSurvivorshipGroupUri === survivorshipGroupUri;
|
|
29
|
+
if (!isDefaultSurvivorshipGroupUri) {
|
|
30
|
+
setIsLoading(true);
|
|
31
|
+
safePromise(getEntityBySurvivorshipGroupUri(entity.uri, survivorshipGroupUri))
|
|
32
|
+
.then(setEntity)
|
|
33
|
+
.finally(() => setIsLoading(false));
|
|
34
|
+
} else {
|
|
35
|
+
setEntity(defaultEntity);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
[defaultEntity, defaultSurvivorshipGroupUri, entity, safePromise]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const isDefaultSurvivorshipGroupUri = defaultSurvivorshipGroupUri === currentSurvivorshipGroupUri;
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
survivorshipGroups,
|
|
45
|
+
currentSurvivorshipGroupUri,
|
|
46
|
+
onChangeSurvivorshipGroup,
|
|
47
|
+
entity,
|
|
48
|
+
isLoading,
|
|
49
|
+
isDefaultSurvivorshipGroupUri
|
|
50
|
+
};
|
|
51
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
3
|
+
<title>Icon / Not a match</title>
|
|
4
|
+
<defs>
|
|
5
|
+
<path d="M17,13.1383198 L21.5,17.6383198 L17,22.1383198 L17,18.5003198 L15.753258,18.5 L12.265,15.021 L13.678,13.607 L16.579,16.5003198 L17,16.5003198 L17,13.1383198 Z M17,1.5 L21.5,6 L17,10.5 L17,7.138 L16.579,7.138 L5.5497951,18.1383198 L2,18.1383198 L2,16.1383198 L4.723,16.138 L15.753258,5.13831978 L17,5.138 L17,1.5 Z M5.5497951,5.5 L8.844,8.786 L7.43,10.199 L4.723,7.50031978 L2,7.5 L2,5.5 L5.5497951,5.5 Z" id="path-1"></path>
|
|
6
|
+
</defs>
|
|
7
|
+
<g id="Icon-/-Not-a-match" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
8
|
+
<mask id="mask-2" fill="white">
|
|
9
|
+
<use xlink:href="#path-1"></use>
|
|
10
|
+
</mask>
|
|
11
|
+
<g id="Combined-Shape" fill-rule="nonzero"></g>
|
|
12
|
+
<rect id="Icon-Color" fill-opacity="0.54" fill="#000000" mask="url(#mask-2)" x="0" y="0" width="24" height="24"></rect>
|
|
13
|
+
</g>
|
|
14
|
+
</svg>
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default as SourcesView} from './components/SourcesView';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {ErrorPopup} from '@reltio/components';
|
|
2
|
+
import i18n from 'ui-i18n';
|
|
3
|
+
import {getRequestErrorMessage} from '@reltio/mdm-sdk';
|
|
4
|
+
|
|
5
|
+
export const showErrorMessage = (error: unknown) => {
|
|
6
|
+
console.error(error); // eslint-disable-line
|
|
7
|
+
ErrorPopup.addError({
|
|
8
|
+
title: i18n.text('Error'),
|
|
9
|
+
message: getRequestErrorMessage(error, i18n.text('Something went wrong'))
|
|
10
|
+
});
|
|
11
|
+
};
|