@truedat/dd 4.33.0 → 4.33.4
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/CHANGELOG.md +12 -0
- package/package.json +6 -6
- package/src/api.js +6 -0
- package/src/components/DictionaryRoutes.js +21 -3
- package/src/components/GraphLoader.js +22 -6
- package/src/components/LineageEvents.js +23 -0
- package/src/components/LineageEventsTable.js +91 -0
- package/src/components/LineageForm.js +2 -1
- package/src/components/LineageGraph.js +59 -11
- package/src/components/LineageRoutes.js +9 -7
- package/src/components/StructureTypesLoader.js +4 -2
- package/src/components/__tests__/LineageEventsTable.spec.js +40 -0
- package/src/components/__tests__/__snapshots__/LineageEventsTable.spec.js.snap +88 -0
- package/src/components/__tests__/__snapshots__/LineageRoutes.spec.js.snap +4 -0
- package/src/messages/en.js +15 -0
- package/src/messages/es.js +15 -0
- package/src/reducers/__tests__/graphLoading.spec.js +2 -2
- package/src/reducers/__tests__/lineageEventsLoading.spec.js +24 -0
- package/src/reducers/graph.js +4 -1
- package/src/reducers/graphLoading.js +8 -4
- package/src/reducers/graphRedirect.js +1 -2
- package/src/reducers/index.js +4 -0
- package/src/reducers/lineageEvents.js +13 -0
- package/src/reducers/lineageEventsLoading.js +14 -0
- package/src/routines.js +3 -0
- package/src/sagas/__tests__/createGraph.spec.js +164 -12
- package/src/sagas/createGraph.js +97 -6
- package/src/sagas/fetchGraph.js +1 -0
- package/src/sagas/fetchLineageEvents.js +26 -0
- package/src/sagas/fetchStructureTypes.js +5 -3
- package/src/sagas/index.js +6 -0
- package/src/selectors/__tests__/getTabVisibility.spec.js +3 -6
- package/src/selectors/getLineageEventColumns.js +52 -0
- package/src/selectors/getTabVisibility.js +3 -12
- package/src/styles/lineageGraph.less +3 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dd",
|
|
3
|
-
"version": "4.33.
|
|
3
|
+
"version": "4.33.4",
|
|
4
4
|
"description": "Truedat Web Data Dictionary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@testing-library/jest-dom": "^5.14.1",
|
|
35
35
|
"@testing-library/react": "^12.0.0",
|
|
36
36
|
"@testing-library/user-event": "^13.2.1",
|
|
37
|
-
"@truedat/test": "4.33.
|
|
37
|
+
"@truedat/test": "4.33.4",
|
|
38
38
|
"babel-jest": "^27.0.6",
|
|
39
39
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
40
40
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
]
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@truedat/auth": "4.33.
|
|
88
|
-
"@truedat/core": "4.33.
|
|
89
|
-
"@truedat/df": "4.33.
|
|
87
|
+
"@truedat/auth": "4.33.4",
|
|
88
|
+
"@truedat/core": "4.33.4",
|
|
89
|
+
"@truedat/df": "4.33.4",
|
|
90
90
|
"lodash": "^4.17.21",
|
|
91
91
|
"path-to-regexp": "^1.7.0",
|
|
92
92
|
"prop-types": "^15.7.2",
|
|
@@ -107,5 +107,5 @@
|
|
|
107
107
|
"react-dom": ">= 16.8.6 < 17",
|
|
108
108
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
109
109
|
},
|
|
110
|
-
"gitHead": "
|
|
110
|
+
"gitHead": "08160df210692628d37599956bc78c587c019afc"
|
|
111
111
|
}
|
package/src/api.js
CHANGED
|
@@ -14,8 +14,10 @@ const API_GRANT_REQUESTS = "/api/grant_requests";
|
|
|
14
14
|
const API_GRANTS_CSV = "/api/grants/csv";
|
|
15
15
|
const API_GRANTS_SEARCH = "/api/grants/search";
|
|
16
16
|
const API_GRAPH = "/api/graphs/:id";
|
|
17
|
+
const API_GRAPH_HASH = "/api/graphs/hash/:hash";
|
|
17
18
|
const API_GRAPHS = "/api/graphs";
|
|
18
19
|
const API_GRAPH_CSV = "/api/graphs/csv";
|
|
20
|
+
const API_LINEAGE_EVENTS = "/api/lineage_events";
|
|
19
21
|
const API_MY_GRANT_FILTERS_SEARCH = "/api/grant_filters/search/mine";
|
|
20
22
|
const API_MY_GRANTS_SEARCH = "/api/grants/search/mine";
|
|
21
23
|
const API_NODE = "/api/nodes/:id";
|
|
@@ -29,6 +31,7 @@ const API_STRUCTURE_TAG = "/api/data_structure_tags/:id";
|
|
|
29
31
|
const API_STRUCTURE_TAGS = "/api/data_structure_tags";
|
|
30
32
|
const API_STRUCTURE_TYPE = "/api/data_structure_types/:id";
|
|
31
33
|
const API_STRUCTURE_TYPES = "/api/data_structure_types";
|
|
34
|
+
const API_STRUCTURE_TYPES_LITE = "/api/data_structure_types/lite";
|
|
32
35
|
const API_STRUCTURES_TAG = "/api/data_structures/:data_structure_id/tags/:id";
|
|
33
36
|
const API_STRUCTURES_TAGS = "/api/data_structures/:data_structure_id/tags";
|
|
34
37
|
const API_STRUCTURE_USER_FILTERS = "/api/data_structure_user_filters";
|
|
@@ -57,9 +60,11 @@ export {
|
|
|
57
60
|
API_GRANT_REQUESTS,
|
|
58
61
|
API_GRANTS_SEARCH,
|
|
59
62
|
API_GRAPH,
|
|
63
|
+
API_GRAPH_HASH,
|
|
60
64
|
API_GRAPHS,
|
|
61
65
|
API_GRAPH_CSV,
|
|
62
66
|
API_GRANTS_CSV,
|
|
67
|
+
API_LINEAGE_EVENTS,
|
|
63
68
|
API_MY_GRANTS_SEARCH,
|
|
64
69
|
API_MY_GRANT_FILTERS_SEARCH,
|
|
65
70
|
API_NODE,
|
|
@@ -73,6 +78,7 @@ export {
|
|
|
73
78
|
API_STRUCTURE_TAGS,
|
|
74
79
|
API_STRUCTURE_TYPE,
|
|
75
80
|
API_STRUCTURE_TYPES,
|
|
81
|
+
API_STRUCTURE_TYPES_LITE,
|
|
76
82
|
API_STRUCTURE_USER_FILTERS,
|
|
77
83
|
API_STRUCTURE_USER_FILTER,
|
|
78
84
|
API_STRUCTURES_TAG,
|
|
@@ -30,7 +30,6 @@ const TemplatesLoader = React.lazy(() =>
|
|
|
30
30
|
const Loaders = () => (
|
|
31
31
|
<>
|
|
32
32
|
<StructuresLoader />
|
|
33
|
-
<StructureTypesLoader />
|
|
34
33
|
<StructureFiltersLoader />
|
|
35
34
|
<TemplatesLoader scope="dd" />
|
|
36
35
|
</>
|
|
@@ -49,6 +48,7 @@ export const DictionaryRoutes = () => {
|
|
|
49
48
|
path={STRUCTURES}
|
|
50
49
|
render={() => (
|
|
51
50
|
<>
|
|
51
|
+
<StructureTypesLoader liteRequest={true} />
|
|
52
52
|
<SystemsLoader />
|
|
53
53
|
<StructuresRoutes />
|
|
54
54
|
</>
|
|
@@ -58,17 +58,35 @@ export const DictionaryRoutes = () => {
|
|
|
58
58
|
path={SYSTEMS}
|
|
59
59
|
render={() => (
|
|
60
60
|
<>
|
|
61
|
+
<StructureTypesLoader liteRequest={true} />
|
|
61
62
|
<SystemsLoader />
|
|
62
63
|
<SystemsRoutes />
|
|
63
64
|
</>
|
|
64
65
|
)}
|
|
65
66
|
/>
|
|
66
|
-
<Route
|
|
67
|
-
|
|
67
|
+
<Route
|
|
68
|
+
path={STRUCTURE_TAGS}
|
|
69
|
+
render={() => (
|
|
70
|
+
<>
|
|
71
|
+
<StructureTypesLoader liteRequest={true} />
|
|
72
|
+
<StructureTagsRoutes />
|
|
73
|
+
</>
|
|
74
|
+
)}
|
|
75
|
+
/>
|
|
76
|
+
<Route
|
|
77
|
+
path={STRUCTURE_TYPES}
|
|
78
|
+
render={() => (
|
|
79
|
+
<>
|
|
80
|
+
<StructureTypesLoader />
|
|
81
|
+
<StructureTypesRoutes />
|
|
82
|
+
</>
|
|
83
|
+
)}
|
|
84
|
+
/>
|
|
68
85
|
<Route
|
|
69
86
|
path={PROFILE_GROUP}
|
|
70
87
|
render={() => (
|
|
71
88
|
<>
|
|
89
|
+
<StructureTypesLoader liteRequest={true} />
|
|
72
90
|
<Route render={() => <ProfileGroupLoader />} />
|
|
73
91
|
<Switch>
|
|
74
92
|
<Route
|
|
@@ -2,27 +2,41 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import { useEffect } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
|
-
import { useRouteMatch } from "react-router-dom";
|
|
5
|
+
import { useRouteMatch, useHistory } from "react-router-dom";
|
|
6
6
|
import { GRAPH } from "@truedat/core/routes";
|
|
7
|
-
import { fetchGraph, clearGraph } from "../routines";
|
|
7
|
+
import { fetchGraph, clearGraph, cancelPoll } from "../routines";
|
|
8
8
|
|
|
9
|
-
export const GraphLoader = ({ clearGraph, fetchGraph, graph }) => {
|
|
9
|
+
export const GraphLoader = ({ clearGraph, fetchGraph, graph, cancelPoll }) => {
|
|
10
10
|
const match = useRouteMatch(GRAPH);
|
|
11
11
|
const id = _.path("params.id")(match);
|
|
12
|
+
|
|
13
|
+
const history = useHistory();
|
|
14
|
+
|
|
12
15
|
useEffect(() => {
|
|
13
16
|
return () => {
|
|
14
17
|
clearGraph();
|
|
15
18
|
};
|
|
16
19
|
}, [clearGraph]);
|
|
20
|
+
|
|
17
21
|
useEffect(() => {
|
|
18
22
|
if (id) {
|
|
19
23
|
if (_.isEmpty(graph)) {
|
|
20
24
|
fetchGraph({ id });
|
|
21
|
-
} else if (
|
|
25
|
+
} else if (id != graph.id) {
|
|
22
26
|
fetchGraph({ id });
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
|
-
}, [graph, fetchGraph
|
|
29
|
+
}, [/*graph, *//*fetchGraph,*/ id]);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
return () => {
|
|
33
|
+
// && history.location.pathname === "any specific path")
|
|
34
|
+
if (history.action === "POP") {
|
|
35
|
+
cancelPoll();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}, [history]);
|
|
39
|
+
|
|
26
40
|
return null;
|
|
27
41
|
};
|
|
28
42
|
|
|
@@ -30,10 +44,12 @@ GraphLoader.propTypes = {
|
|
|
30
44
|
clearGraph: PropTypes.func.isRequired,
|
|
31
45
|
fetchGraph: PropTypes.func.isRequired,
|
|
32
46
|
graph: PropTypes.object,
|
|
47
|
+
cancelPoll: PropTypes.func,
|
|
33
48
|
};
|
|
34
49
|
|
|
35
50
|
const mapStateToProps = ({ graph }) => ({ graph });
|
|
36
51
|
|
|
37
|
-
export default connect(mapStateToProps, { clearGraph, fetchGraph })(
|
|
52
|
+
export default connect(mapStateToProps, { clearGraph, fetchGraph, cancelPoll })(
|
|
38
53
|
GraphLoader
|
|
39
54
|
);
|
|
55
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Header, Icon, Segment, Dimmer, Loader } from "semantic-ui-react";
|
|
3
|
+
import { FormattedMessage } from "react-intl";
|
|
4
|
+
import LineageEventsTable from "./LineageEventsTable"
|
|
5
|
+
|
|
6
|
+
export const LineageEvents = () => (
|
|
7
|
+
<Segment>
|
|
8
|
+
<Header as="h2">
|
|
9
|
+
<Icon circular name="cogs" />
|
|
10
|
+
<Header.Content>
|
|
11
|
+
<FormattedMessage id="lineage.events.header" />
|
|
12
|
+
<Header.Subheader>
|
|
13
|
+
<FormattedMessage id="lineage.events.subheader" />
|
|
14
|
+
</Header.Subheader>
|
|
15
|
+
</Header.Content>
|
|
16
|
+
</Header>
|
|
17
|
+
<Segment attached="bottom">
|
|
18
|
+
<LineageEventsTable />
|
|
19
|
+
</Segment>
|
|
20
|
+
</Segment>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export default LineageEvents;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { useEffect } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { FormattedMessage } from "react-intl";
|
|
5
|
+
import { Header, Icon, Table } from "semantic-ui-react";
|
|
6
|
+
import { useHistory, } from "react-router-dom";
|
|
7
|
+
import { connect } from "react-redux";
|
|
8
|
+
import { useIntl } from "react-intl";
|
|
9
|
+
import { columnDecorator } from "@truedat/core/services";
|
|
10
|
+
import { linkTo } from "@truedat/core/routes";
|
|
11
|
+
import { lineageEventColumns as columns } from "../selectors/getLineageEventColumns";
|
|
12
|
+
import { fetchLineageEvents } from "../routines";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export const LineageEventsTable = ({ fetchLineageEvents, lineageEvents, lineageEventsLoading }) => {
|
|
16
|
+
const { formatMessage } = useIntl();
|
|
17
|
+
const history = useHistory();
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
fetchLineageEvents();
|
|
21
|
+
}, [fetchLineageEvents]);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
{!_.isEmpty(lineageEvents) && (
|
|
26
|
+
<Table sortable selectable>
|
|
27
|
+
<Table.Header>
|
|
28
|
+
<Table.Row>
|
|
29
|
+
{columns.map((column, i) => {
|
|
30
|
+
return (
|
|
31
|
+
<Table.HeaderCell
|
|
32
|
+
key={i}
|
|
33
|
+
width={column.width}
|
|
34
|
+
content={formatMessage({
|
|
35
|
+
id: `lineage.events.props.${column.name}`,
|
|
36
|
+
defaultMessage: column.name,
|
|
37
|
+
})}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
})}
|
|
41
|
+
</Table.Row>
|
|
42
|
+
</Table.Header>
|
|
43
|
+
<Table.Body>
|
|
44
|
+
{lineageEvents.map((event, i) => (
|
|
45
|
+
<Table.Row
|
|
46
|
+
key={i}
|
|
47
|
+
onClick={
|
|
48
|
+
event.graph_id
|
|
49
|
+
? () => history.push(linkTo.GRAPH({ id: event?.graph_id }))
|
|
50
|
+
: null
|
|
51
|
+
}
|
|
52
|
+
>
|
|
53
|
+
{columns &&
|
|
54
|
+
columns.map((column, key) => (
|
|
55
|
+
<Table.Cell
|
|
56
|
+
key={key}
|
|
57
|
+
textAlign={column.textAlign}
|
|
58
|
+
content={columnDecorator(column)(event)}
|
|
59
|
+
/>
|
|
60
|
+
))}
|
|
61
|
+
</Table.Row>
|
|
62
|
+
))}
|
|
63
|
+
</Table.Body>
|
|
64
|
+
</Table>
|
|
65
|
+
)}
|
|
66
|
+
{_.isEmpty(lineageEvents) && !lineageEventsLoading && (
|
|
67
|
+
<Header as="h4">
|
|
68
|
+
<Icon name="search" />
|
|
69
|
+
<Header.Content>
|
|
70
|
+
<FormattedMessage id="lineage.events.search.results.empty" />
|
|
71
|
+
</Header.Content>
|
|
72
|
+
</Header>
|
|
73
|
+
)}
|
|
74
|
+
</>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
LineageEventsTable.propTypes = {
|
|
79
|
+
lineageEvents: PropTypes.array,
|
|
80
|
+
fetchLineageEvents: PropTypes.func,
|
|
81
|
+
lineageEventsLoading: PropTypes.bool,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const mapStateToProps = (state) => ({
|
|
85
|
+
lineageEvents: state.lineageEvents,
|
|
86
|
+
lineageEventsLoading: state.lineageEventsLoading,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export default connect(mapStateToProps, { fetchLineageEvents })(
|
|
90
|
+
LineageEventsTable
|
|
91
|
+
);
|
|
@@ -54,10 +54,11 @@ export const LineageForm = ({
|
|
|
54
54
|
const [open, setOpen] = useState(true);
|
|
55
55
|
const [selectLevels, setSelectLevels] = useState(levelsSelection);
|
|
56
56
|
const [levels, setLevels] = useState(lineageLevels);
|
|
57
|
-
const handleSubmit = (type) => () =>
|
|
57
|
+
const handleSubmit = (type) => () => {
|
|
58
58
|
_.isNil(levels)
|
|
59
59
|
? createGraph({ ids: selectedResources, type })
|
|
60
60
|
: createGraph({ ids: selectedResources, type, levels });
|
|
61
|
+
}
|
|
61
62
|
const disabled = _.isEmpty(selectedResources);
|
|
62
63
|
useEffect(() => {
|
|
63
64
|
setOpen(!graphLoading && _.isEmpty(graph));
|
|
@@ -4,12 +4,19 @@ import PropTypes from "prop-types";
|
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
5
|
import { Dimmer, Loader } from "semantic-ui-react";
|
|
6
6
|
import svgPanZoom from "svg-pan-zoom";
|
|
7
|
-
import { FormattedMessage } from "react-intl";
|
|
8
|
-
import {
|
|
7
|
+
import { FormattedMessage, useIntl } from "react-intl";
|
|
8
|
+
import {
|
|
9
|
+
clearNode,
|
|
10
|
+
selectNode,
|
|
11
|
+
hoverNode,
|
|
12
|
+
initSvg,
|
|
13
|
+
cancelPoll,
|
|
14
|
+
} from "../routines";
|
|
9
15
|
import LineageLink from "./LineageLink";
|
|
10
16
|
import LineageDefs from "./LineageDefs";
|
|
11
17
|
import LineageGroup from "./LineageGroup";
|
|
12
18
|
import LineageResource from "./LineageResource";
|
|
19
|
+
import "../styles/lineageGraph.less";
|
|
13
20
|
|
|
14
21
|
const svgOptions = { minZoom: 0.2, maxZoom: 2.0, fit: false, center: false };
|
|
15
22
|
const disablePanZoom = (svg) => {
|
|
@@ -50,11 +57,18 @@ export const LineageGraph = ({
|
|
|
50
57
|
groups = [],
|
|
51
58
|
resources = [],
|
|
52
59
|
loading,
|
|
60
|
+
loadingInfo,
|
|
61
|
+
cancelPoll,
|
|
53
62
|
}) => {
|
|
54
63
|
const ref = useRef(null);
|
|
55
64
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
56
65
|
const { selectedNode, hover, svg } = state;
|
|
57
66
|
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
// Anything in here is fired on component mount.
|
|
69
|
+
return () => cancelPoll();
|
|
70
|
+
}, []);
|
|
71
|
+
|
|
58
72
|
useEffect(() => {
|
|
59
73
|
if (!_.isEmpty(resources)) {
|
|
60
74
|
const svg = svgPanZoom(ref.current, svgOptions);
|
|
@@ -67,6 +81,8 @@ export const LineageGraph = ({
|
|
|
67
81
|
const onSelect = (g) => () => dispatch(selectNode.trigger(g));
|
|
68
82
|
const onHover = (g) =>
|
|
69
83
|
selectedNode ? undefined : () => dispatch(hoverNode.trigger(g));
|
|
84
|
+
const { formatMessage } = useIntl();
|
|
85
|
+
|
|
70
86
|
return (
|
|
71
87
|
<>
|
|
72
88
|
<Dimmer.Dimmable dimmed={loading} className="dl">
|
|
@@ -74,8 +90,34 @@ export const LineageGraph = ({
|
|
|
74
90
|
<Loader size="large">
|
|
75
91
|
<FormattedMessage
|
|
76
92
|
id="lineage.graph.loading"
|
|
77
|
-
defaultMessage="Analyzing..."
|
|
93
|
+
defaultMessage={"Analyzing..."}
|
|
78
94
|
/>
|
|
95
|
+
{loadingInfo?.data?.graph_hash && loadingInfo?.data?.status && (
|
|
96
|
+
<p>
|
|
97
|
+
{formatMessage({
|
|
98
|
+
id:
|
|
99
|
+
loadingInfo?.data?.status === "already_started"
|
|
100
|
+
? "lineage.graph.loading.background.existing"
|
|
101
|
+
: loadingInfo?.data?.status === "just_started" &&
|
|
102
|
+
"lineage.graph.loading.background.launched",
|
|
103
|
+
})}
|
|
104
|
+
</p>
|
|
105
|
+
)}
|
|
106
|
+
{loadingInfo?.data?.graph_hash && (
|
|
107
|
+
<p>
|
|
108
|
+
Graph hash:{" "}
|
|
109
|
+
<span className="graph-hash">
|
|
110
|
+
{loadingInfo?.data?.graph_hash}
|
|
111
|
+
</span>
|
|
112
|
+
</p>
|
|
113
|
+
)}
|
|
114
|
+
<p>
|
|
115
|
+
{loadingInfo?.data?.retry &&
|
|
116
|
+
formatMessage(
|
|
117
|
+
{ id: "lineage.graph.loading.polling" },
|
|
118
|
+
{ retry: loadingInfo?.data?.retry }
|
|
119
|
+
)}
|
|
120
|
+
</p>
|
|
79
121
|
</Loader>
|
|
80
122
|
</Dimmer>
|
|
81
123
|
<svg
|
|
@@ -121,17 +163,23 @@ LineageGraph.propTypes = {
|
|
|
121
163
|
paths: PropTypes.array,
|
|
122
164
|
resources: PropTypes.array,
|
|
123
165
|
height: PropTypes.string,
|
|
166
|
+
loading: PropTypes.bool,
|
|
167
|
+
loadingInfo: PropTypes.object,
|
|
168
|
+
cancelPoll: PropTypes.func,
|
|
124
169
|
};
|
|
125
170
|
|
|
126
171
|
const mapStateToProps = (
|
|
127
172
|
{ graph = {}, graphLoading, selectedNode },
|
|
128
173
|
ownProps
|
|
129
|
-
) =>
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
174
|
+
) => {
|
|
175
|
+
return {
|
|
176
|
+
paths: _.prop("paths")(_.propOr(graph, "graph")(ownProps)),
|
|
177
|
+
groups: _.prop("groups")(_.propOr(graph, "graph")(ownProps)),
|
|
178
|
+
resources: _.prop("resources")(_.propOr(graph, "graph")(ownProps)),
|
|
179
|
+
loading: graphLoading !== false,
|
|
180
|
+
loadingInfo: graphLoading,
|
|
181
|
+
selectedNode,
|
|
182
|
+
};
|
|
183
|
+
};
|
|
136
184
|
|
|
137
|
-
export default connect(mapStateToProps, { clearNode })(LineageGraph);
|
|
185
|
+
export default connect(mapStateToProps, { clearNode, cancelPoll })(LineageGraph);
|
|
@@ -2,7 +2,8 @@ import React from "react";
|
|
|
2
2
|
import { Route } from "react-router-dom";
|
|
3
3
|
import { Unauthorized } from "@truedat/core/components";
|
|
4
4
|
import { useAuthorized } from "@truedat/core/hooks";
|
|
5
|
-
import { GRAPH, GRAPHS, SAMPLE } from "@truedat/core/routes";
|
|
5
|
+
import { GRAPH, GRAPHS, LINEAGE_EVENTS, SAMPLE } from "@truedat/core/routes";
|
|
6
|
+
import LineageEvents from "./LineageEvents"
|
|
6
7
|
import LineageGraph from "./LineageGraph";
|
|
7
8
|
import LineageSample from "./LineageSample";
|
|
8
9
|
import LineageForm from "./LineageForm";
|
|
@@ -13,16 +14,13 @@ const Graphs = () => (
|
|
|
13
14
|
<>
|
|
14
15
|
<LineageForm />
|
|
15
16
|
<GraphRedirector />
|
|
16
|
-
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
const Graph = () => (
|
|
20
|
-
<>
|
|
21
|
-
<GraphLoader />
|
|
17
|
+
{/* Load LineageGraph here so that its <Loader> is already available when clicking the LinageForm */}
|
|
22
18
|
<LineageGraph />
|
|
23
19
|
</>
|
|
24
20
|
);
|
|
25
21
|
|
|
22
|
+
const Graph = () => <GraphLoader />;
|
|
23
|
+
|
|
26
24
|
export const LineageRoutes = () => {
|
|
27
25
|
const authorized = useAuthorized("lineage");
|
|
28
26
|
return (
|
|
@@ -35,6 +33,10 @@ export const LineageRoutes = () => {
|
|
|
35
33
|
path={GRAPH}
|
|
36
34
|
render={() => (authorized ? <Graph /> : <Unauthorized />)}
|
|
37
35
|
/>
|
|
36
|
+
<Route
|
|
37
|
+
path={LINEAGE_EVENTS}
|
|
38
|
+
render={() => (authorized ? <LineageEvents /> : <Unauthorized />)}
|
|
39
|
+
/>
|
|
38
40
|
<Route
|
|
39
41
|
path={SAMPLE}
|
|
40
42
|
render={() => (authorized ? <LineageSample /> : <Unauthorized />)}
|
|
@@ -6,19 +6,21 @@ import { clearStructureTypes, fetchStructureTypes } from "../routines";
|
|
|
6
6
|
export const StructureTypesLoader = ({
|
|
7
7
|
clearStructureTypes,
|
|
8
8
|
fetchStructureTypes,
|
|
9
|
+
liteRequest = false,
|
|
9
10
|
}) => {
|
|
10
11
|
useEffect(() => {
|
|
11
|
-
fetchStructureTypes();
|
|
12
|
+
fetchStructureTypes({ liteRequest });
|
|
12
13
|
return () => {
|
|
13
14
|
clearStructureTypes();
|
|
14
15
|
};
|
|
15
|
-
}, [clearStructureTypes, fetchStructureTypes]);
|
|
16
|
+
}, [clearStructureTypes, fetchStructureTypes, liteRequest]);
|
|
16
17
|
return null;
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
StructureTypesLoader.propTypes = {
|
|
20
21
|
clearStructureTypes: PropTypes.func,
|
|
21
22
|
fetchStructureTypes: PropTypes.func,
|
|
23
|
+
liteRequest: PropTypes.bool,
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export default connect(null, { clearStructureTypes, fetchStructureTypes })(
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
|
+
import { LineageEventsTable } from "../LineageEventsTable";
|
|
4
|
+
import en from "../../messages/en";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
describe("<LineageEventsTable />", () => {
|
|
8
|
+
const lineageEvents = [
|
|
9
|
+
{
|
|
10
|
+
graph_id: 1234,
|
|
11
|
+
graph_data: "graph_data",
|
|
12
|
+
status: "COMPLETED",
|
|
13
|
+
message: "message",
|
|
14
|
+
inserted_at: "2021-11-26T10:09:27.168999Z",
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const lineageEventsLoading = false;
|
|
19
|
+
const fetchLineageEvents = jest.fn();
|
|
20
|
+
|
|
21
|
+
it("matches the latest snapshot", () => {
|
|
22
|
+
const props = { fetchLineageEvents, lineageEvents, lineageEventsLoading };
|
|
23
|
+
const { container } = render(<LineageEventsTable {...props} />, {
|
|
24
|
+
messages: { en },
|
|
25
|
+
});
|
|
26
|
+
expect(container).toMatchSnapshot();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("matches the latest snapshot (no jobs)", () => {
|
|
30
|
+
const props = {
|
|
31
|
+
fetchLineageEvents,
|
|
32
|
+
lineageEvents: [],
|
|
33
|
+
lineageEventsLoading,
|
|
34
|
+
};
|
|
35
|
+
const { container } = render(<LineageEventsTable {...props} />, {
|
|
36
|
+
messages: { en },
|
|
37
|
+
});
|
|
38
|
+
expect(container).toMatchSnapshot();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`<LineageEventsTable /> matches the latest snapshot (no jobs) 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<h4
|
|
6
|
+
class="ui header"
|
|
7
|
+
>
|
|
8
|
+
<i
|
|
9
|
+
aria-hidden="true"
|
|
10
|
+
class="search icon"
|
|
11
|
+
/>
|
|
12
|
+
<div
|
|
13
|
+
class="content"
|
|
14
|
+
>
|
|
15
|
+
No graphs found
|
|
16
|
+
</div>
|
|
17
|
+
</h4>
|
|
18
|
+
</div>
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
exports[`<LineageEventsTable /> matches the latest snapshot 1`] = `
|
|
22
|
+
<div>
|
|
23
|
+
<table
|
|
24
|
+
class="ui selectable sortable table"
|
|
25
|
+
>
|
|
26
|
+
<thead
|
|
27
|
+
class=""
|
|
28
|
+
>
|
|
29
|
+
<tr
|
|
30
|
+
class=""
|
|
31
|
+
>
|
|
32
|
+
<th
|
|
33
|
+
class="two wide"
|
|
34
|
+
>
|
|
35
|
+
Graph
|
|
36
|
+
</th>
|
|
37
|
+
<th
|
|
38
|
+
class="two wide"
|
|
39
|
+
>
|
|
40
|
+
Status
|
|
41
|
+
</th>
|
|
42
|
+
<th
|
|
43
|
+
class="two wide"
|
|
44
|
+
>
|
|
45
|
+
Message
|
|
46
|
+
</th>
|
|
47
|
+
<th
|
|
48
|
+
class="two wide"
|
|
49
|
+
>
|
|
50
|
+
Date
|
|
51
|
+
</th>
|
|
52
|
+
</tr>
|
|
53
|
+
</thead>
|
|
54
|
+
<tbody
|
|
55
|
+
class=""
|
|
56
|
+
>
|
|
57
|
+
<tr
|
|
58
|
+
class=""
|
|
59
|
+
>
|
|
60
|
+
<td
|
|
61
|
+
class=""
|
|
62
|
+
>
|
|
63
|
+
graph_data
|
|
64
|
+
</td>
|
|
65
|
+
<td
|
|
66
|
+
class=""
|
|
67
|
+
>
|
|
68
|
+
Completed
|
|
69
|
+
</td>
|
|
70
|
+
<td
|
|
71
|
+
class=""
|
|
72
|
+
>
|
|
73
|
+
message
|
|
74
|
+
</td>
|
|
75
|
+
<td
|
|
76
|
+
class="center aligned"
|
|
77
|
+
>
|
|
78
|
+
<time
|
|
79
|
+
datetime="1637921367168"
|
|
80
|
+
>
|
|
81
|
+
2021-11-26 10:09
|
|
82
|
+
</time>
|
|
83
|
+
</td>
|
|
84
|
+
</tr>
|
|
85
|
+
</tbody>
|
|
86
|
+
</table>
|
|
87
|
+
</div>
|
|
88
|
+
`;
|