@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,27 @@
|
|
|
1
|
+
export const getMetadata = ({tenant, access}) => ({
|
|
2
|
+
[tenant]: {
|
|
3
|
+
entityTypes: [
|
|
4
|
+
{
|
|
5
|
+
uri: 'configuration/entityTypes/HCP',
|
|
6
|
+
label: 'HCP',
|
|
7
|
+
attributes: [
|
|
8
|
+
{
|
|
9
|
+
label: 'Country Code',
|
|
10
|
+
name: 'CountryCode',
|
|
11
|
+
type: 'String',
|
|
12
|
+
uri: 'configuration/entityTypes/HCP/attributes/CountryCode'
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
...(access ? {access} : {})
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
sources: [
|
|
19
|
+
{
|
|
20
|
+
uri: 'configuration/sources/Reltio',
|
|
21
|
+
label: 'Reltio',
|
|
22
|
+
icon: 'images/source/reltio.png',
|
|
23
|
+
abbreviation: 'Reltio'
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {getMetadata} from './metadata.data';
|
|
2
|
+
|
|
3
|
+
export const createInitialState = ({access = null} = {}) => {
|
|
4
|
+
const tenant = 'alenat';
|
|
5
|
+
return {
|
|
6
|
+
profile: {
|
|
7
|
+
entity: {
|
|
8
|
+
uri: 'entities/1mGpgPSC',
|
|
9
|
+
type: 'configuration/entityTypes/HCP',
|
|
10
|
+
attributes: {
|
|
11
|
+
CountryCode: [
|
|
12
|
+
{
|
|
13
|
+
uri: 'entities/1mGpgPSC/attributes/CountryCode/1',
|
|
14
|
+
type: 'configuration/entityTypes/HCP/attributes/CountryCode',
|
|
15
|
+
value: 'Italy',
|
|
16
|
+
lookupCode: 'IT'
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
crosswalks: [
|
|
21
|
+
{
|
|
22
|
+
uri: 'entities/1mGpgPSC/crosswalks/4eQNj0MiJ',
|
|
23
|
+
type: 'configuration/sources/Reltio',
|
|
24
|
+
value: '1OCFJIn5',
|
|
25
|
+
reltioLoadDate: '2021-06-11T08:24:31.726Z',
|
|
26
|
+
createDate: '2018-11-19T12:14:00.735Z',
|
|
27
|
+
updateDate: '2018-11-19T12:14:00.735Z',
|
|
28
|
+
attributes: [
|
|
29
|
+
'entities/1mGpgPSC/attributes/CountryCode/12jf9nc37',
|
|
30
|
+
'entities/1mGpgPSC/attributes/Name/1dl1LhLwS'
|
|
31
|
+
],
|
|
32
|
+
singleAttributeUpdateDates: {}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
uri: 'entities/1mGpgPSC/crosswalks/5JS297jHk',
|
|
36
|
+
type: 'configuration/sources/Reltio',
|
|
37
|
+
value: '1mGpgPSC',
|
|
38
|
+
reltioLoadDate: '2021-06-09T11:32:16.434Z',
|
|
39
|
+
sourcePublishDate: '1970-01-01T00:00:00.000Z',
|
|
40
|
+
createDate: '2018-11-28T13:16:18.540Z',
|
|
41
|
+
updateDate: '2018-11-28T13:16:18.540Z',
|
|
42
|
+
attributes: [
|
|
43
|
+
'entities/1mGpgPSC/attributes/Address/ZxOfYYo',
|
|
44
|
+
'entities/1mGpgPSC/attributes/Name/1CwTindWI'
|
|
45
|
+
],
|
|
46
|
+
singleAttributeUpdateDates: {
|
|
47
|
+
'entities/1mGpgPSC/attributes/Name/1CwTindWI': '2021-06-09T11:32:16.434Z'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
history: {
|
|
53
|
+
mode: 'Current'
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
metadata: getMetadata({tenant, access}),
|
|
57
|
+
ui: {
|
|
58
|
+
config: {}
|
|
59
|
+
},
|
|
60
|
+
tenant: {
|
|
61
|
+
id: tenant
|
|
62
|
+
},
|
|
63
|
+
dataTenants: []
|
|
64
|
+
};
|
|
65
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<mask id="mask0" masktype="alpha" maskUnits="userSpaceOnUse" x="2" y="3" width="19" height="17">
|
|
3
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.5 5C2.5 4.17 3.17 3.5 4 3.5C4.83 3.5 5.5 4.17 5.5 5C5.5 5.83 4.83 6.5 4 6.5C3.17 6.5 2.5 5.83 2.5 5ZM21 20H8V18H21V20ZM8 10H21V8H8V10ZM8 6V4H21V6H8ZM8 16H21V14H8V16ZM5.5 16.5V13.5H2.5V16.5H5.5Z" fill="white"/>
|
|
4
|
+
</mask>
|
|
5
|
+
<g mask="url(#mask0)">
|
|
6
|
+
<rect width="24" height="24" fill-opacity="0.54" fill="#000000"/>
|
|
7
|
+
</g>
|
|
8
|
+
</svg>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React, {useCallback} from 'react';
|
|
2
|
+
import {Provider} from 'react-redux';
|
|
3
|
+
import {Store} from 'redux';
|
|
4
|
+
|
|
5
|
+
import {AdapterMoment} from '@mui/x-date-pickers/AdapterMoment';
|
|
6
|
+
import createGenerateClassName from '@mui/styles/createGenerateClassName';
|
|
7
|
+
import StylesProvider from '@mui/styles/StylesProvider';
|
|
8
|
+
import ReactResizeDetector from 'react-resize-detector';
|
|
9
|
+
import {LocalizationProvider} from '@mui/x-date-pickers/LocalizationProvider';
|
|
10
|
+
import {ErrorPopup, ViewIdContext} from '@reltio/components';
|
|
11
|
+
import {SourcesSavedState} from '../../types';
|
|
12
|
+
import SourcesView from './SourcesView';
|
|
13
|
+
import {promisifyCallback, SourcesPerspectiveConfig} from '@reltio/mdm-sdk';
|
|
14
|
+
|
|
15
|
+
const generateClassName = createGenerateClassName({
|
|
16
|
+
productionPrefix: 'sourcesPerspective',
|
|
17
|
+
disableGlobal: true,
|
|
18
|
+
seed: 'srcs'
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
type Props = {
|
|
22
|
+
config: SourcesPerspectiveConfig;
|
|
23
|
+
store: Store<unknown>;
|
|
24
|
+
onResize?: (width: number, height: number) => void;
|
|
25
|
+
saveState: (state: SourcesSavedState) => void;
|
|
26
|
+
getSavedState: (clb: (state: SourcesSavedState) => void) => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const SourcesPerspective = ({config, store, onResize, saveState, getSavedState}: Props) => {
|
|
30
|
+
const getSavedStatePromisified: () => Promise<SourcesSavedState> = useCallback(promisifyCallback(getSavedState), [
|
|
31
|
+
getSavedState
|
|
32
|
+
]);
|
|
33
|
+
return (
|
|
34
|
+
<Provider store={store}>
|
|
35
|
+
<ViewIdContext.Provider value={config.id}>
|
|
36
|
+
<StylesProvider generateClassName={generateClassName}>
|
|
37
|
+
<LocalizationProvider dateAdapter={AdapterMoment}>
|
|
38
|
+
<ReactResizeDetector
|
|
39
|
+
handleHeight
|
|
40
|
+
onResize={(width, height) => onResize?.(Math.floor(width), Math.floor(height))}
|
|
41
|
+
/>
|
|
42
|
+
{config && (
|
|
43
|
+
<SourcesView
|
|
44
|
+
config={config}
|
|
45
|
+
saveState={saveState}
|
|
46
|
+
getSavedState={getSavedStatePromisified}
|
|
47
|
+
/>
|
|
48
|
+
)}
|
|
49
|
+
<ErrorPopup />
|
|
50
|
+
</LocalizationProvider>
|
|
51
|
+
</StylesProvider>
|
|
52
|
+
</ViewIdContext.Provider>
|
|
53
|
+
</Provider>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export default SourcesPerspective;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {makeStyles} from '@mui/styles';
|
|
2
|
+
|
|
3
|
+
export const useStyles = makeStyles({
|
|
4
|
+
sourcesView: {
|
|
5
|
+
position: 'absolute',
|
|
6
|
+
top: 0,
|
|
7
|
+
left: 0,
|
|
8
|
+
right: 0,
|
|
9
|
+
bottom: 0,
|
|
10
|
+
overflowX: 'hidden',
|
|
11
|
+
overflowY: 'auto',
|
|
12
|
+
fontFamily: 'Roboto, Helvetica, Arial, sans-serif',
|
|
13
|
+
display: 'flex'
|
|
14
|
+
},
|
|
15
|
+
'@global div[role=tooltip]': {
|
|
16
|
+
fontFamily: 'Roboto, Helvetica, Arial, sans-serif'
|
|
17
|
+
},
|
|
18
|
+
'@global div[role=presentation]': {
|
|
19
|
+
fontFamily: 'Roboto, Helvetica, Arial, sans-serif'
|
|
20
|
+
},
|
|
21
|
+
resizablePanesWrapper: {
|
|
22
|
+
flexGrow: 1,
|
|
23
|
+
height: '100%'
|
|
24
|
+
},
|
|
25
|
+
pane: {
|
|
26
|
+
position: 'absolute',
|
|
27
|
+
top: 0,
|
|
28
|
+
left: 0,
|
|
29
|
+
right: 0,
|
|
30
|
+
bottom: 0,
|
|
31
|
+
display: 'flex',
|
|
32
|
+
flexDirection: 'column',
|
|
33
|
+
overflow: 'hidden'
|
|
34
|
+
},
|
|
35
|
+
headerDivider: {
|
|
36
|
+
marginLeft: '16px',
|
|
37
|
+
marginRight: '8px',
|
|
38
|
+
height: '32px',
|
|
39
|
+
borderColor: 'rgba(0, 0, 0, 0.12)'
|
|
40
|
+
},
|
|
41
|
+
attributesTable: {
|
|
42
|
+
backgroundColor: '#fff'
|
|
43
|
+
}
|
|
44
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, {useContext} from 'react';
|
|
2
|
+
import i18n from 'ui-i18n';
|
|
3
|
+
import {useSelector} from 'react-redux';
|
|
4
|
+
import mdmModule from '@reltio/mdm-module';
|
|
5
|
+
import {Entity, getLabel} from '@reltio/mdm-sdk';
|
|
6
|
+
import {UrlGeneratorsContext} from '@reltio/components';
|
|
7
|
+
import Typography from '@mui/material/Typography';
|
|
8
|
+
import Link from '@mui/material/Link';
|
|
9
|
+
import InfoIcon from '@mui/icons-material/Info';
|
|
10
|
+
|
|
11
|
+
import {useStyles} from './styles';
|
|
12
|
+
|
|
13
|
+
type Props = {
|
|
14
|
+
entity: Entity;
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const TreeActionSnackbar = ({entity, message}: Props) => {
|
|
19
|
+
const styles = useStyles();
|
|
20
|
+
const uiPath = useSelector(mdmModule.selectors.getUIPath);
|
|
21
|
+
const {generateEntityUrl} = useContext(UrlGeneratorsContext);
|
|
22
|
+
const entityLink = generateEntityUrl({uiPath, uri: entity.uri});
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div className={styles.snackbarMessage}>
|
|
26
|
+
<InfoIcon className={styles.snackbarIcon} />
|
|
27
|
+
<Typography>
|
|
28
|
+
{getLabel(entity.label)}{' '}
|
|
29
|
+
<Link href={entityLink} target="_blank" underline="hover">
|
|
30
|
+
{i18n.text('lookup profile')}
|
|
31
|
+
</Link>{' '}
|
|
32
|
+
{message}
|
|
33
|
+
</Typography>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default TreeActionSnackbar;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {shallow} from 'enzyme';
|
|
3
|
+
import * as reactRedux from 'react-redux';
|
|
4
|
+
import Link from '@mui/material/Link';
|
|
5
|
+
import Typography from '@mui/material/Typography';
|
|
6
|
+
import TreeActionSnackbar from '../TreeActionSnackbar';
|
|
7
|
+
|
|
8
|
+
describe('TreeActionSnackbar tests', () => {
|
|
9
|
+
const store = {
|
|
10
|
+
ui: {
|
|
11
|
+
paths: {
|
|
12
|
+
uiPath: 'https://tst-01.reltio.com/reltio/api/uitest1'
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
beforeAll(() => {
|
|
17
|
+
jest.spyOn(reactRedux, 'useSelector').mockImplementation((selector) => selector(store));
|
|
18
|
+
});
|
|
19
|
+
it('should render correctly', () => {
|
|
20
|
+
const entity = {
|
|
21
|
+
uri: 'entities/123',
|
|
22
|
+
type: 'configuration/entityTypes/HCP',
|
|
23
|
+
label: 'Entity label'
|
|
24
|
+
};
|
|
25
|
+
const message = 'has been unmerged';
|
|
26
|
+
const wrapper = shallow(<TreeActionSnackbar entity={entity} message={message} />);
|
|
27
|
+
expect(wrapper.find('.snackbarMessage')).toHaveLength(1);
|
|
28
|
+
expect(wrapper.find('.snackbarIcon')).toHaveLength(1);
|
|
29
|
+
|
|
30
|
+
const typography = wrapper.find(Typography);
|
|
31
|
+
expect(typography).toHaveLength(1);
|
|
32
|
+
expect(typography.find(Link).props()).toMatchObject({
|
|
33
|
+
href: `${store.ui.paths.uiPath}#p~com.reltio.plugins.entity.default.DefaultPerspective_e~${entity.uri}`,
|
|
34
|
+
target: '_blank'
|
|
35
|
+
});
|
|
36
|
+
expect(typography.text()).toBe(`${entity.label} lookup profile ${message}`);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React, {useCallback, useState} from 'react';
|
|
2
|
+
import i18n from 'ui-i18n';
|
|
3
|
+
import Button from '@mui/material/Button';
|
|
4
|
+
import Dialog from '@mui/material/Dialog';
|
|
5
|
+
import DialogActions from '@mui/material/DialogActions';
|
|
6
|
+
import DialogContent from '@mui/material/DialogContent';
|
|
7
|
+
import DialogTitle from '@mui/material/DialogTitle';
|
|
8
|
+
import Typography from '@mui/material/Typography';
|
|
9
|
+
import {SelectableTree} from '../SelectableTree/SelectableTree';
|
|
10
|
+
import {
|
|
11
|
+
collectCrosswalksFromContributor,
|
|
12
|
+
Contributor,
|
|
13
|
+
CrosswalkTree,
|
|
14
|
+
getLastUriPart,
|
|
15
|
+
UnmergeOperation
|
|
16
|
+
} from '@reltio/mdm-sdk';
|
|
17
|
+
|
|
18
|
+
import {useStyles} from './styles';
|
|
19
|
+
|
|
20
|
+
type Props = {
|
|
21
|
+
contributor: Contributor;
|
|
22
|
+
crosswalkTree: CrosswalkTree;
|
|
23
|
+
canUnmerge?: boolean;
|
|
24
|
+
onClose: () => void;
|
|
25
|
+
onUnmergeContributor: (operationType: UnmergeOperation) => void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const UnmergeDialog = ({canUnmerge, contributor, crosswalkTree, onClose, onUnmergeContributor}: Props) => {
|
|
29
|
+
const styles = useStyles();
|
|
30
|
+
|
|
31
|
+
const [unmergeOperation, setUnmergeOperation] = useState(UnmergeOperation.Unmerge);
|
|
32
|
+
|
|
33
|
+
const getColoredCrosswalks = useCallback(
|
|
34
|
+
(includeMerges: boolean) => collectCrosswalksFromContributor(contributor, includeMerges).map(({uri}) => uri),
|
|
35
|
+
[contributor]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const unmergeContributor = () => {
|
|
39
|
+
onUnmergeContributor(unmergeOperation);
|
|
40
|
+
onClose();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Dialog open={true} onClose={onClose} classes={{paper: styles.dialogContainer}}>
|
|
45
|
+
<DialogTitle classes={{root: styles.dialogTitle}}>{i18n.text('Unmerge')}</DialogTitle>
|
|
46
|
+
<DialogContent classes={{root: styles.dialogContent}}>
|
|
47
|
+
<Typography variant={'body2'} className={styles.uri}>
|
|
48
|
+
<span className={styles.title}>{i18n.text('Entity URI:')}</span>
|
|
49
|
+
{getLastUriPart(contributor.uri).toUpperCase()}
|
|
50
|
+
</Typography>
|
|
51
|
+
<div className={styles.trees}>
|
|
52
|
+
<SelectableTree
|
|
53
|
+
onSelect={() => setUnmergeOperation(UnmergeOperation.Unmerge)}
|
|
54
|
+
selected={unmergeOperation === UnmergeOperation.Unmerge}
|
|
55
|
+
title={i18n.text('Unmerge')}
|
|
56
|
+
crosswalkTree={crosswalkTree}
|
|
57
|
+
coloredCrosswalks={getColoredCrosswalks(true)}
|
|
58
|
+
/>
|
|
59
|
+
{contributor.merges && contributor.uri !== crosswalkTree.uri && (
|
|
60
|
+
<SelectableTree
|
|
61
|
+
onSelect={() => setUnmergeOperation(UnmergeOperation.TreeUnmerge)}
|
|
62
|
+
selected={unmergeOperation === UnmergeOperation.TreeUnmerge}
|
|
63
|
+
title={i18n.text('Tree unmerge')}
|
|
64
|
+
crosswalkTree={crosswalkTree}
|
|
65
|
+
coloredCrosswalks={getColoredCrosswalks(false)}
|
|
66
|
+
/>
|
|
67
|
+
)}
|
|
68
|
+
</div>
|
|
69
|
+
</DialogContent>
|
|
70
|
+
<DialogActions>
|
|
71
|
+
<Button onClick={onClose}>{i18n.text('Cancel')}</Button>
|
|
72
|
+
<Button disabled={!canUnmerge} onClick={unmergeContributor} color="primary">
|
|
73
|
+
{i18n.text('Unmerge')}
|
|
74
|
+
</Button>
|
|
75
|
+
</DialogActions>
|
|
76
|
+
</Dialog>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Button from '@mui/material/Button';
|
|
3
|
+
import {UnmergeOperation} from '@reltio/mdm-sdk';
|
|
4
|
+
import {shallow} from 'enzyme';
|
|
5
|
+
import {act} from 'react-dom/test-utils';
|
|
6
|
+
import Typography from '@mui/material/Typography';
|
|
7
|
+
import {UnmergeDialog} from '../UnmergeDialog';
|
|
8
|
+
import {SelectableTree} from '../../SelectableTree/SelectableTree';
|
|
9
|
+
import {contributors, crosswalkTree} from './testData.data';
|
|
10
|
+
|
|
11
|
+
describe('UnmergeDialog tests', () => {
|
|
12
|
+
const contributorUri = 'entities/p6u3cIz';
|
|
13
|
+
const props = {
|
|
14
|
+
contributor: contributors.find(({uri}) => uri === contributorUri),
|
|
15
|
+
crosswalkTree,
|
|
16
|
+
canUnmerge: true,
|
|
17
|
+
onClose: jest.fn(),
|
|
18
|
+
onUnmergeContributor: jest.fn()
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
it('should render unmerge and Tree unmerge', () => {
|
|
22
|
+
const component = shallow(<UnmergeDialog {...props} />);
|
|
23
|
+
const selectableTrees = component.find(SelectableTree);
|
|
24
|
+
const expectedValues = [
|
|
25
|
+
{
|
|
26
|
+
selected: true,
|
|
27
|
+
crosswalkTree: props.crosswalkTree,
|
|
28
|
+
coloredCrosswalks: [],
|
|
29
|
+
title: 'Unmerge'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
selected: false,
|
|
33
|
+
crosswalkTree: props.crosswalkTree,
|
|
34
|
+
coloredCrosswalks: ['entities/j8K1vc9/crosswalks/1CwTipUbG'],
|
|
35
|
+
title: 'Tree unmerge'
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
expect(component.find(Typography).text()).toBe('Entity URI:P6U3CIZ');
|
|
39
|
+
expect(selectableTrees).toHaveLength(2);
|
|
40
|
+
selectableTrees.forEach((tree, i) => {
|
|
41
|
+
expect(tree.prop('selected')).toBe(expectedValues[i].selected);
|
|
42
|
+
expect(tree.prop('crosswalkTree')).toEqual(expectedValues[i].crosswalkTree);
|
|
43
|
+
expect(tree.prop('coloredCrosswalks')).toEqual(expectedValues[i].coloredCrosswalks);
|
|
44
|
+
expect(tree.prop('title')).toBe(expectedValues[i].title);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const unmergeButton = component.find(Button).filterWhere((button) => button.text() === 'Unmerge');
|
|
48
|
+
expect(unmergeButton.prop('disabled')).toBeFalsy();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should render only unmerge if contributor.uri === crosswalkTree.uri', () => {
|
|
52
|
+
const modifiedProps = {
|
|
53
|
+
...props,
|
|
54
|
+
contributor: contributors.find(({uri}) => uri === crosswalkTree.uri)
|
|
55
|
+
};
|
|
56
|
+
const component = shallow(<UnmergeDialog {...modifiedProps} />);
|
|
57
|
+
const selectableTree = component.find(SelectableTree);
|
|
58
|
+
expect(selectableTree.prop('selected')).toBe(true);
|
|
59
|
+
expect(selectableTree.prop('title')).toBe('Unmerge');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should render only unmerge if contributor has not got any merges', () => {
|
|
63
|
+
const modifiedProps = {
|
|
64
|
+
...props,
|
|
65
|
+
contributor: contributors.find(({uri}) => uri === 'entities/1N1mfYja')
|
|
66
|
+
};
|
|
67
|
+
const component = shallow(<UnmergeDialog {...modifiedProps} />);
|
|
68
|
+
const selectableTree = component.find(SelectableTree);
|
|
69
|
+
expect(selectableTree.prop('selected')).toBe(true);
|
|
70
|
+
expect(selectableTree.prop('title')).toBe('Unmerge');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should change unmergeOperation', () => {
|
|
74
|
+
const component = shallow(<UnmergeDialog {...props} />);
|
|
75
|
+
const selectableTrees = component.find(SelectableTree);
|
|
76
|
+
const expectedValues = [
|
|
77
|
+
{selected: true, title: 'Unmerge'},
|
|
78
|
+
{selected: false, title: 'Tree unmerge'}
|
|
79
|
+
];
|
|
80
|
+
expect(selectableTrees).toHaveLength(2);
|
|
81
|
+
selectableTrees.forEach((tree, i) => {
|
|
82
|
+
expect(tree.prop('selected')).toBe(expectedValues[i].selected);
|
|
83
|
+
expect(tree.prop('title')).toBe(expectedValues[i].title);
|
|
84
|
+
});
|
|
85
|
+
const treeUnmerge = selectableTrees.filterWhere((tree) => tree.prop('title') === 'Tree unmerge');
|
|
86
|
+
act(() => {
|
|
87
|
+
treeUnmerge.prop('onSelect')();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const newSelectableTrees = component.find(SelectableTree);
|
|
91
|
+
newSelectableTrees.forEach((tree, i) => {
|
|
92
|
+
expect(tree.prop('selected')).toBe(!expectedValues[i].selected);
|
|
93
|
+
expect(tree.prop('title')).toBe(expectedValues[i].title);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should call onUnmergeContributor and onClose on Unmerge Button click', () => {
|
|
98
|
+
const component = shallow(<UnmergeDialog {...props} />);
|
|
99
|
+
const unmergeContributor = component
|
|
100
|
+
.find(Button)
|
|
101
|
+
.filterWhere((button) => button.text() === 'Unmerge')
|
|
102
|
+
.prop('onClick') as () => void;
|
|
103
|
+
unmergeContributor();
|
|
104
|
+
expect(props.onUnmergeContributor).toHaveBeenCalledWith(UnmergeOperation.Unmerge);
|
|
105
|
+
expect(props.onClose).toHaveBeenCalled();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should call onClose on Cancel Button click', () => {
|
|
109
|
+
const component = shallow(<UnmergeDialog {...props} />);
|
|
110
|
+
const closeDialog = component
|
|
111
|
+
.find(Button)
|
|
112
|
+
.filterWhere((button) => button.text() === 'Cancel')
|
|
113
|
+
.prop('onClick') as () => void;
|
|
114
|
+
closeDialog();
|
|
115
|
+
expect(props.onClose).toHaveBeenCalled();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should disable unmerge button if canUnmerge === false', () => {
|
|
119
|
+
const component = shallow(<UnmergeDialog {...props} canUnmerge={false} />);
|
|
120
|
+
|
|
121
|
+
const unmergeButton = component.find(Button).filterWhere((button) => button.text() === 'Unmerge');
|
|
122
|
+
expect(unmergeButton.prop('disabled')).toBeTruthy();
|
|
123
|
+
});
|
|
124
|
+
});
|