@truedat/dd 4.35.4 → 4.35.8
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 +15 -1
- package/package.json +5 -5
- package/src/components/GraphLoader.js +1 -1
- package/src/components/GraphRedirector.js +12 -4
- package/src/components/LineageContextMenu.js +15 -3
- package/src/components/LineageSample.js +1 -1
- package/src/components/StructureFieldsDropdown.js +19 -5
- package/src/components/StructureGraph.js +9 -3
- package/src/components/StructureLineage.js +4 -1
- package/src/components/StructureSelectorInputField.js +30 -0
- package/src/components/StructureSelectorInputFieldJoin.js +48 -29
- package/src/components/__tests__/__snapshots__/GrantRequest.spec.js.snap +4 -4
- package/src/components/__tests__/__snapshots__/StructureSelectorInputFieldJoin.spec.js.snap +17 -15
- package/src/reducers/__tests__/graph.spec.js +0 -6
- package/src/reducers/__tests__/lineageQuery.spec.js +29 -1
- package/src/reducers/__tests__/structureImpactGraph.spec.js +24 -1
- package/src/reducers/__tests__/structureLineageGraph.spec.js +35 -1
- package/src/reducers/graph.js +0 -2
- package/src/reducers/lineageQuery.js +22 -6
- package/src/reducers/structureImpactGraph.js +5 -2
- package/src/reducers/structureLineageGraph.js +5 -2
- package/src/sagas/__tests__/createGraph.spec.js +10 -5
- package/src/sagas/createGraph.js +21 -4
- package/src/selectors/getStructuresFields.js +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.35.8] 2022-01-07
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- [TD-4390] Support for alias on Implementation
|
|
8
|
+
|
|
9
|
+
## [4.35.7] 2021-01-07
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- [TD-4413]:
|
|
14
|
+
- Fix impact tab not displaying data, affecting lineage tab
|
|
15
|
+
- Fix LineageContextMenu inside impact and lineage tabs not redirecting to /graphs
|
|
16
|
+
|
|
3
17
|
## [4.35.4] 2021-12-20
|
|
4
18
|
|
|
5
19
|
### Fixed
|
|
6
20
|
|
|
7
|
-
-
|
|
21
|
+
- [TD-4356] Improve structure types view performance by doing optional the metadata fields column
|
|
8
22
|
|
|
9
23
|
## [4.35.3] 2021-12-20
|
|
10
24
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dd",
|
|
3
|
-
"version": "4.35.
|
|
3
|
+
"version": "4.35.8",
|
|
4
4
|
"description": "Truedat Web Data Dictionary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
]
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@truedat/auth": "4.35.
|
|
88
|
-
"@truedat/core": "4.35.
|
|
89
|
-
"@truedat/df": "4.35.
|
|
87
|
+
"@truedat/auth": "4.35.8",
|
|
88
|
+
"@truedat/core": "4.35.8",
|
|
89
|
+
"@truedat/df": "4.35.8",
|
|
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": "35a51ffb36f357fe814258d51420d5ace5b3cd63"
|
|
111
111
|
}
|
|
@@ -5,23 +5,31 @@ import { connect } from "react-redux";
|
|
|
5
5
|
import { useHistory, useLocation } from "react-router-dom";
|
|
6
6
|
import { clearRedirect } from "@truedat/core/routines";
|
|
7
7
|
|
|
8
|
-
export const GraphRedirector = ({ graphRedirect, clearRedirect }) => {
|
|
8
|
+
export const GraphRedirector = ({ graph, graphRedirect, clearRedirect }) => {
|
|
9
9
|
const { pathname } = useLocation();
|
|
10
10
|
const history = useHistory();
|
|
11
11
|
useEffect(() => {
|
|
12
|
-
if (
|
|
12
|
+
if (
|
|
13
|
+
graphRedirect &&
|
|
14
|
+
graph?.fromLineageContextMenu &&
|
|
15
|
+
!_.isEqual(pathname, graphRedirect)
|
|
16
|
+
) {
|
|
13
17
|
history.push(graphRedirect);
|
|
14
18
|
clearRedirect();
|
|
15
19
|
}
|
|
16
|
-
}, [pathname, graphRedirect]);
|
|
20
|
+
}, [history, pathname, graphRedirect, graph, clearRedirect]);
|
|
17
21
|
return null;
|
|
18
22
|
};
|
|
19
23
|
|
|
20
24
|
GraphRedirector.propTypes = {
|
|
25
|
+
graph: PropTypes.object,
|
|
21
26
|
clearRedirect: PropTypes.func.isRequired,
|
|
22
27
|
graphRedirect: PropTypes.string,
|
|
23
28
|
};
|
|
24
29
|
|
|
25
|
-
const mapStateToProps = ({ graphRedirect }) => ({
|
|
30
|
+
const mapStateToProps = ({ graph, graphRedirect }) => ({
|
|
31
|
+
graph,
|
|
32
|
+
graphRedirect,
|
|
33
|
+
});
|
|
26
34
|
|
|
27
35
|
export default connect(mapStateToProps, { clearRedirect })(GraphRedirector);
|
|
@@ -23,7 +23,12 @@ export const LineageContextMenu = ({
|
|
|
23
23
|
<>
|
|
24
24
|
<Menu.Item
|
|
25
25
|
onClick={() =>
|
|
26
|
-
createGraph({
|
|
26
|
+
createGraph({
|
|
27
|
+
ids: [id],
|
|
28
|
+
levels: levels,
|
|
29
|
+
type: "lineage",
|
|
30
|
+
fromLineageContextMenu: true,
|
|
31
|
+
})
|
|
27
32
|
}
|
|
28
33
|
>
|
|
29
34
|
<Icon name="random" flipped="horizontally" />
|
|
@@ -34,7 +39,12 @@ export const LineageContextMenu = ({
|
|
|
34
39
|
</Menu.Item>
|
|
35
40
|
<Menu.Item
|
|
36
41
|
onClick={() =>
|
|
37
|
-
createGraph({
|
|
42
|
+
createGraph({
|
|
43
|
+
ids: [id],
|
|
44
|
+
levels: levels,
|
|
45
|
+
type: "impact",
|
|
46
|
+
fromLineageContextMenu: true,
|
|
47
|
+
})
|
|
38
48
|
}
|
|
39
49
|
>
|
|
40
50
|
<Icon name="random" />
|
|
@@ -43,7 +53,9 @@ export const LineageContextMenu = ({
|
|
|
43
53
|
defaultMessage="Impact"
|
|
44
54
|
/>
|
|
45
55
|
</Menu.Item>
|
|
46
|
-
<Menu.Item
|
|
56
|
+
<Menu.Item
|
|
57
|
+
onClick={() => excludeNode({ id, fromLineageContextMenu: true })}
|
|
58
|
+
>
|
|
47
59
|
<Icon name="eye slash outline" />
|
|
48
60
|
<FormattedMessage
|
|
49
61
|
id="navigation.lineage.exclude"
|
|
@@ -8,6 +8,7 @@ import { getStructuresFields } from "../selectors/getStructuresFields";
|
|
|
8
8
|
|
|
9
9
|
export const StructureFieldsDropdown = ({
|
|
10
10
|
label,
|
|
11
|
+
fluid,
|
|
11
12
|
inline,
|
|
12
13
|
onSelectField,
|
|
13
14
|
structureFields,
|
|
@@ -17,22 +18,33 @@ export const StructureFieldsDropdown = ({
|
|
|
17
18
|
}) => {
|
|
18
19
|
const { formatMessage } = useIntl();
|
|
19
20
|
const onClick = ({ value, modifier }) => {
|
|
20
|
-
const
|
|
21
|
+
const [data_structure_id, parent_index] = _.isString(value)
|
|
22
|
+
? value.split("/").map(Number)
|
|
23
|
+
: [value, undefined];
|
|
24
|
+
const field = _.isNil(parent_index)
|
|
25
|
+
? _.find({ data_structure_id: data_structure_id })(structureFields)
|
|
26
|
+
: _.find({
|
|
27
|
+
data_structure_id: data_structure_id,
|
|
28
|
+
parent_index: parent_index,
|
|
29
|
+
})(structureFields);
|
|
21
30
|
onSelectField(field, modifier);
|
|
22
31
|
};
|
|
23
32
|
|
|
24
33
|
const formatOption = (field) => {
|
|
34
|
+
const value = _.isNil(field?.parent_index)
|
|
35
|
+
? field.data_structure_id
|
|
36
|
+
: `${field.data_structure_id}/${field.parent_index}`;
|
|
25
37
|
const modifier = _.find({ sourceType: field.field_type })(
|
|
26
38
|
typeCastModifiers
|
|
27
39
|
);
|
|
28
40
|
if (modifier) {
|
|
29
41
|
return {
|
|
30
|
-
key:
|
|
42
|
+
key: value,
|
|
31
43
|
text: `${field.name} (${formatMessage({
|
|
32
44
|
id: `filtersGrid.field.modifier.${modifier.name}`,
|
|
33
45
|
})})`,
|
|
34
46
|
modifier,
|
|
35
|
-
value:
|
|
47
|
+
value: value,
|
|
36
48
|
icon: formatMessage({
|
|
37
49
|
id: `field_type.icon.${field.field_type}`,
|
|
38
50
|
defaultMessage: "hashtag",
|
|
@@ -41,9 +53,9 @@ export const StructureFieldsDropdown = ({
|
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
return {
|
|
44
|
-
key:
|
|
56
|
+
key: value,
|
|
45
57
|
text: field.name,
|
|
46
|
-
value:
|
|
58
|
+
value: value,
|
|
47
59
|
icon: formatMessage({
|
|
48
60
|
id: `field_type.icon.${field.field_type}`,
|
|
49
61
|
defaultMessage: "hashtag",
|
|
@@ -88,6 +100,7 @@ export const StructureFieldsDropdown = ({
|
|
|
88
100
|
|
|
89
101
|
return (
|
|
90
102
|
<OptionGroup
|
|
103
|
+
fluid={fluid}
|
|
91
104
|
inline={inline}
|
|
92
105
|
label={label}
|
|
93
106
|
value={value}
|
|
@@ -102,6 +115,7 @@ export const StructureFieldsDropdown = ({
|
|
|
102
115
|
|
|
103
116
|
StructureFieldsDropdown.propTypes = {
|
|
104
117
|
label: PropTypes.string,
|
|
118
|
+
fluid: PropTypes.bool,
|
|
105
119
|
inline: PropTypes.bool,
|
|
106
120
|
value: PropTypes.number,
|
|
107
121
|
structureFields: PropTypes.array,
|
|
@@ -3,6 +3,7 @@ import React, { useEffect } from "react";
|
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
5
|
import { createGraph, fetchStructureGraph } from "../routines";
|
|
6
|
+
import GraphRedirector from "./GraphRedirector";
|
|
6
7
|
import LineageGraph from "./LineageGraph";
|
|
7
8
|
|
|
8
9
|
export const StructureGraph = ({
|
|
@@ -16,11 +17,16 @@ export const StructureGraph = ({
|
|
|
16
17
|
}) => {
|
|
17
18
|
useEffect(() => {
|
|
18
19
|
degree && _.isEmpty(graph) && createGraph({ ids: [id], type: type });
|
|
19
|
-
}, [type]);
|
|
20
|
+
}, [degree, graph, id, type, createGraph]);
|
|
20
21
|
useEffect(() => {
|
|
21
22
|
graphId && _.isEmpty(graph) && fetchStructureGraph({ id: graphId });
|
|
22
|
-
}, [graphId]);
|
|
23
|
-
return degree ?
|
|
23
|
+
}, [graph, graphId, fetchStructureGraph]);
|
|
24
|
+
return degree ? (
|
|
25
|
+
<>
|
|
26
|
+
<GraphRedirector />
|
|
27
|
+
<LineageGraph height="50vh" graph={graph} />
|
|
28
|
+
</>
|
|
29
|
+
) : null;
|
|
24
30
|
};
|
|
25
31
|
|
|
26
32
|
StructureGraph.propTypes = {
|
|
@@ -18,7 +18,10 @@ export const StructureLineage = (props) => (
|
|
|
18
18
|
</>
|
|
19
19
|
);
|
|
20
20
|
|
|
21
|
-
const mapStateToProps = ({
|
|
21
|
+
const mapStateToProps = ({
|
|
22
|
+
structureLineageId: graphId,
|
|
23
|
+
structureLineageGraph: graph,
|
|
24
|
+
}) => ({
|
|
22
25
|
graph,
|
|
23
26
|
graphId,
|
|
24
27
|
type: "lineage",
|
|
@@ -34,6 +34,12 @@ export const StructureSelectorInputField = ({
|
|
|
34
34
|
onChangeField({ ...selectedStructure, clauses });
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
const aliasIsNeeded =
|
|
38
|
+
_.flow(
|
|
39
|
+
_.map(_.path("structure.id")),
|
|
40
|
+
_.filter((s) => s === selectedStructure?.structure?.id)
|
|
41
|
+
)(structures).length > 1;
|
|
42
|
+
|
|
37
43
|
return (
|
|
38
44
|
<>
|
|
39
45
|
<Form.Field>
|
|
@@ -74,6 +80,30 @@ export const StructureSelectorInputField = ({
|
|
|
74
80
|
/>
|
|
75
81
|
)}
|
|
76
82
|
</Form.Field>
|
|
83
|
+
{aliasIsNeeded && (
|
|
84
|
+
<Container style={{ paddingLeft: "8em" }}>
|
|
85
|
+
<Form.Field>
|
|
86
|
+
<label>
|
|
87
|
+
{formatMessage({
|
|
88
|
+
id: `ruleImplementation.props.structure.alias`,
|
|
89
|
+
})}
|
|
90
|
+
</label>
|
|
91
|
+
<Form.Input
|
|
92
|
+
width={fieldWidth ? fieldWidth : 7}
|
|
93
|
+
value={selectedStructure?.alias?.text || ""}
|
|
94
|
+
onChange={(e) =>
|
|
95
|
+
onChangeField({
|
|
96
|
+
...selectedStructure,
|
|
97
|
+
alias: {
|
|
98
|
+
...(selectedStructure?.alias || {}),
|
|
99
|
+
text: e.target.value,
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
/>
|
|
104
|
+
</Form.Field>
|
|
105
|
+
</Container>
|
|
106
|
+
)}
|
|
77
107
|
{joined && _.prop("structure")(selectedStructure) && (
|
|
78
108
|
<Container style={{ paddingLeft: "8em" }}>
|
|
79
109
|
<Form.Field>
|
|
@@ -2,10 +2,10 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { useIntl } from "react-intl";
|
|
5
|
-
import {
|
|
5
|
+
import { Grid, Icon, Popup } from "semantic-ui-react";
|
|
6
6
|
import StructureFieldsDropdown from "./StructureFieldsDropdown";
|
|
7
7
|
|
|
8
|
-
const getClauses = selectedStructure => {
|
|
8
|
+
const getClauses = (selectedStructure) => {
|
|
9
9
|
const clauses = _.getOr([], "clauses")(selectedStructure);
|
|
10
10
|
return _.isEmpty(clauses) ? [{}] : clauses;
|
|
11
11
|
};
|
|
@@ -14,15 +14,21 @@ const getParentStructures = (structures, selectedStructure) => {
|
|
|
14
14
|
return structures && selectedStructure
|
|
15
15
|
? _.flow(
|
|
16
16
|
_.filter(
|
|
17
|
-
s =>
|
|
18
|
-
_.path("
|
|
19
|
-
_.path("
|
|
17
|
+
(s) =>
|
|
18
|
+
_.path("alias.index")(s) !==
|
|
19
|
+
_.path("alias.index")(selectedStructure)
|
|
20
20
|
),
|
|
21
21
|
_.defaultTo([])
|
|
22
22
|
)(structures)
|
|
23
23
|
: [];
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
const structureToFieldDropdown = (structures) =>
|
|
27
|
+
_.map((s) => ({
|
|
28
|
+
..._.prop("structure")(s),
|
|
29
|
+
alias: _.prop("alias")(s),
|
|
30
|
+
}))(structures);
|
|
31
|
+
|
|
26
32
|
const JoinClause = ({
|
|
27
33
|
createClause,
|
|
28
34
|
deleteClause,
|
|
@@ -31,33 +37,43 @@ const JoinClause = ({
|
|
|
31
37
|
left,
|
|
32
38
|
parentStructures,
|
|
33
39
|
right,
|
|
34
|
-
selectedStructure
|
|
40
|
+
selectedStructure,
|
|
35
41
|
}) => {
|
|
36
42
|
const addActionDisabled = _.isEmpty(left) || _.isEmpty(right);
|
|
37
43
|
const { formatMessage } = useIntl();
|
|
38
44
|
return (
|
|
39
|
-
<
|
|
40
|
-
<
|
|
45
|
+
<Grid>
|
|
46
|
+
<Grid.Column width={4}>
|
|
41
47
|
<StructureFieldsDropdown
|
|
42
|
-
|
|
48
|
+
fluid
|
|
49
|
+
parentStructures={structureToFieldDropdown([selectedStructure])}
|
|
43
50
|
onSelectField={handleChange("left", idx)}
|
|
44
|
-
value={
|
|
51
|
+
value={
|
|
52
|
+
_.isNil(_.prop("parent_index")(left))
|
|
53
|
+
? _.prop("id")(left)
|
|
54
|
+
: `${_.prop("id")(left)}/${_.prop("parent_index")(left)}`
|
|
55
|
+
}
|
|
45
56
|
/>
|
|
46
|
-
</
|
|
47
|
-
<
|
|
48
|
-
<
|
|
57
|
+
</Grid.Column>
|
|
58
|
+
<Grid.Column width={1}>{"="}</Grid.Column>
|
|
59
|
+
<Grid.Column width={4}>
|
|
49
60
|
<StructureFieldsDropdown
|
|
50
|
-
|
|
61
|
+
fluid
|
|
62
|
+
parentStructures={structureToFieldDropdown(parentStructures)}
|
|
51
63
|
onSelectField={handleChange("right", idx)}
|
|
52
|
-
value={
|
|
64
|
+
value={
|
|
65
|
+
_.isNil(_.prop("parent_index")(right))
|
|
66
|
+
? _.prop("id")(right)
|
|
67
|
+
: `${_.prop("id")(right)}/${_.prop("parent_index")(right)}`
|
|
68
|
+
}
|
|
53
69
|
/>
|
|
54
|
-
</
|
|
55
|
-
<
|
|
70
|
+
</Grid.Column>
|
|
71
|
+
<Grid.Column width={1}>
|
|
56
72
|
{
|
|
57
73
|
<Popup
|
|
58
74
|
disabled={!addActionDisabled}
|
|
59
75
|
content={formatMessage({
|
|
60
|
-
id: "dataset.form.button.add_join.popup"
|
|
76
|
+
id: "dataset.form.button.add_join.popup",
|
|
61
77
|
})}
|
|
62
78
|
trigger={
|
|
63
79
|
<Icon
|
|
@@ -69,8 +85,8 @@ const JoinClause = ({
|
|
|
69
85
|
}
|
|
70
86
|
/>
|
|
71
87
|
}
|
|
72
|
-
</
|
|
73
|
-
<
|
|
88
|
+
</Grid.Column>
|
|
89
|
+
<Grid.Column width={1}>
|
|
74
90
|
{idx > 0 && (
|
|
75
91
|
<Icon
|
|
76
92
|
name="trash"
|
|
@@ -78,8 +94,8 @@ const JoinClause = ({
|
|
|
78
94
|
onClick={() => deleteClause(idx)}
|
|
79
95
|
/>
|
|
80
96
|
)}
|
|
81
|
-
</
|
|
82
|
-
</
|
|
97
|
+
</Grid.Column>
|
|
98
|
+
</Grid>
|
|
83
99
|
);
|
|
84
100
|
};
|
|
85
101
|
|
|
@@ -91,24 +107,27 @@ JoinClause.propTypes = {
|
|
|
91
107
|
selectedStructure: PropTypes.object,
|
|
92
108
|
createClause: PropTypes.func,
|
|
93
109
|
deleteClause: PropTypes.func,
|
|
94
|
-
handleChange: PropTypes.func
|
|
110
|
+
handleChange: PropTypes.func,
|
|
95
111
|
};
|
|
96
112
|
|
|
97
113
|
export const StructureSelectorInputFieldJoin = ({
|
|
98
114
|
structures,
|
|
99
115
|
selectedStructure,
|
|
100
|
-
handleSelectField
|
|
116
|
+
handleSelectField,
|
|
101
117
|
}) => {
|
|
102
118
|
const clauses = getClauses(selectedStructure);
|
|
103
119
|
const parentStructures = getParentStructures(structures, selectedStructure);
|
|
104
120
|
const createClause = () => handleSelectField([...clauses, {}]);
|
|
105
121
|
const removeAt = (arr, idx) => [
|
|
106
122
|
..._.slice(0, idx)(arr),
|
|
107
|
-
..._.slice(idx + 1, arr.length)(arr)
|
|
123
|
+
..._.slice(idx + 1, arr.length)(arr),
|
|
108
124
|
];
|
|
109
|
-
const deleteClause = idx => handleSelectField(removeAt(clauses, idx));
|
|
110
|
-
const handleChange = (prop, idx) => (
|
|
111
|
-
const
|
|
125
|
+
const deleteClause = (idx) => handleSelectField(removeAt(clauses, idx));
|
|
126
|
+
const handleChange = (prop, idx) => (data) => {
|
|
127
|
+
const { data_structure_id: id, parent_index: parent_index } = data;
|
|
128
|
+
const newClause = _.isNil(parent_index)
|
|
129
|
+
? { ...clauses[idx], [prop]: { id } }
|
|
130
|
+
: { ...clauses[idx], [prop]: { id, parent_index } };
|
|
112
131
|
const newClauses = _.set(`[${idx}]`, newClause)(clauses);
|
|
113
132
|
handleSelectField(newClauses);
|
|
114
133
|
};
|
|
@@ -134,7 +153,7 @@ export const StructureSelectorInputFieldJoin = ({
|
|
|
134
153
|
StructureSelectorInputFieldJoin.propTypes = {
|
|
135
154
|
structures: PropTypes.array,
|
|
136
155
|
selectedStructure: PropTypes.object,
|
|
137
|
-
handleSelectField: PropTypes.func
|
|
156
|
+
handleSelectField: PropTypes.func,
|
|
138
157
|
};
|
|
139
158
|
|
|
140
159
|
export default StructureSelectorInputFieldJoin;
|
|
@@ -378,7 +378,7 @@ exports[`<GrantRequest /> matches the latest snapshot with approve actions 1`] =
|
|
|
378
378
|
role="listitem"
|
|
379
379
|
>
|
|
380
380
|
<div
|
|
381
|
-
class="header"
|
|
381
|
+
class="header dynamic-field-header"
|
|
382
382
|
>
|
|
383
383
|
bar
|
|
384
384
|
</div>
|
|
@@ -386,7 +386,7 @@ exports[`<GrantRequest /> matches the latest snapshot with approve actions 1`] =
|
|
|
386
386
|
class="description"
|
|
387
387
|
>
|
|
388
388
|
<div
|
|
389
|
-
|
|
389
|
+
class="default-value"
|
|
390
390
|
>
|
|
391
391
|
baz
|
|
392
392
|
</div>
|
|
@@ -644,7 +644,7 @@ exports[`<GrantRequest /> matches the latest snapshot with failed status 1`] = `
|
|
|
644
644
|
role="listitem"
|
|
645
645
|
>
|
|
646
646
|
<div
|
|
647
|
-
class="header"
|
|
647
|
+
class="header dynamic-field-header"
|
|
648
648
|
>
|
|
649
649
|
bar
|
|
650
650
|
</div>
|
|
@@ -652,7 +652,7 @@ exports[`<GrantRequest /> matches the latest snapshot with failed status 1`] = `
|
|
|
652
652
|
class="description"
|
|
653
653
|
>
|
|
654
654
|
<div
|
|
655
|
-
|
|
655
|
+
class="default-value"
|
|
656
656
|
>
|
|
657
657
|
baz
|
|
658
658
|
</div>
|
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`<StructureSelectorInputFieldJoin /> matches the latest JoinClause snapshot 1`] = `
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
>
|
|
7
|
-
<FormField
|
|
4
|
+
<Grid>
|
|
5
|
+
<GridColumn
|
|
8
6
|
width={4}
|
|
9
7
|
>
|
|
10
8
|
<Connect(StructureFieldsDropdown)
|
|
9
|
+
fluid={true}
|
|
11
10
|
onSelectField={[Function]}
|
|
12
11
|
parentStructures={
|
|
13
12
|
Array [
|
|
14
|
-
|
|
13
|
+
Object {
|
|
14
|
+
"alias": undefined,
|
|
15
|
+
},
|
|
15
16
|
]
|
|
16
17
|
}
|
|
17
18
|
value="7"
|
|
18
19
|
/>
|
|
19
|
-
</
|
|
20
|
-
<
|
|
20
|
+
</GridColumn>
|
|
21
|
+
<GridColumn
|
|
21
22
|
width={1}
|
|
22
23
|
>
|
|
23
24
|
=
|
|
24
|
-
</
|
|
25
|
-
<
|
|
25
|
+
</GridColumn>
|
|
26
|
+
<GridColumn
|
|
26
27
|
width={4}
|
|
27
28
|
>
|
|
28
29
|
<Connect(StructureFieldsDropdown)
|
|
30
|
+
fluid={true}
|
|
29
31
|
onSelectField={[Function]}
|
|
30
32
|
parentStructures={Array []}
|
|
31
33
|
value="8"
|
|
32
34
|
/>
|
|
33
|
-
</
|
|
34
|
-
<
|
|
35
|
+
</GridColumn>
|
|
36
|
+
<GridColumn
|
|
35
37
|
width={1}
|
|
36
38
|
>
|
|
37
39
|
<Popup
|
|
@@ -57,8 +59,8 @@ exports[`<StructureSelectorInputFieldJoin /> matches the latest JoinClause snaps
|
|
|
57
59
|
/>
|
|
58
60
|
}
|
|
59
61
|
/>
|
|
60
|
-
</
|
|
61
|
-
<
|
|
62
|
+
</GridColumn>
|
|
63
|
+
<GridColumn
|
|
62
64
|
width={1}
|
|
63
65
|
>
|
|
64
66
|
<Icon
|
|
@@ -67,8 +69,8 @@ exports[`<StructureSelectorInputFieldJoin /> matches the latest JoinClause snaps
|
|
|
67
69
|
name="trash"
|
|
68
70
|
onClick={[Function]}
|
|
69
71
|
/>
|
|
70
|
-
</
|
|
71
|
-
</
|
|
72
|
+
</GridColumn>
|
|
73
|
+
</Grid>
|
|
72
74
|
`;
|
|
73
75
|
|
|
74
76
|
exports[`<StructureSelectorInputFieldJoin /> matches the latest snapshot 1`] = `
|
|
@@ -17,12 +17,6 @@ describe("reducers: graph", () => {
|
|
|
17
17
|
expect(graph(fooState, { type: clearGraph.TRIGGER })).toEqual(initialState);
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
it("should be the initial state after receiving the clearStructure.TRIGGER action", () => {
|
|
21
|
-
expect(graph(fooState, { type: clearStructure.TRIGGER })).toEqual(
|
|
22
|
-
initialState
|
|
23
|
-
);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
20
|
it("should be the initial state after receiving the fetchStructure.TRIGGER action", () => {
|
|
27
21
|
expect(graph(fooState, { type: fetchStructure.TRIGGER })).toEqual(
|
|
28
22
|
initialState
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createGraph,
|
|
4
4
|
excludeNode,
|
|
5
5
|
fetchGraph,
|
|
6
|
-
selectGroup
|
|
6
|
+
selectGroup,
|
|
7
7
|
} from "../../routines";
|
|
8
8
|
|
|
9
9
|
const fooState = { foo: "bar" };
|
|
@@ -21,6 +21,17 @@ describe("reducers: lineageQuery", () => {
|
|
|
21
21
|
).toMatchObject({ excludes: ["bar", "foo"] });
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
it("should append a default {fromLineageContextMenu: false} it it was not specified in the excludeNode.TRIGGER action payload", () => {
|
|
25
|
+
const state = { excludes: ["foo"] };
|
|
26
|
+
const payload = { id: "bar" };
|
|
27
|
+
expect(
|
|
28
|
+
lineageQuery(state, { type: excludeNode.TRIGGER, payload })
|
|
29
|
+
).toMatchObject({
|
|
30
|
+
excludes: ["bar", "foo"],
|
|
31
|
+
fromLineageContextMenu: false,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
24
35
|
it("should reset the exclusions after receiving the selectGroup.TRIGGER action", () => {
|
|
25
36
|
const payload = {};
|
|
26
37
|
expect(
|
|
@@ -39,6 +50,23 @@ describe("reducers: lineageQuery", () => {
|
|
|
39
50
|
).toMatchObject({ excludes: [], ids, type, levels });
|
|
40
51
|
});
|
|
41
52
|
|
|
53
|
+
it("should append a default {fromLineageContextMenu: false} it it was not specified in the createGraph.TRIGGER action payload", () => {
|
|
54
|
+
const ids = ["foo", "bar"];
|
|
55
|
+
const type = "type";
|
|
56
|
+
const levels = 3;
|
|
57
|
+
const state = { excludes: ["foo"] };
|
|
58
|
+
const payload = { ids, type, levels };
|
|
59
|
+
expect(
|
|
60
|
+
lineageQuery(state, { type: createGraph.TRIGGER, payload })
|
|
61
|
+
).toMatchObject({
|
|
62
|
+
excludes: [],
|
|
63
|
+
ids,
|
|
64
|
+
type,
|
|
65
|
+
levels,
|
|
66
|
+
fromLineageContextMenu: false,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
42
70
|
it("should extract the data from the payload of the fetchGraph.SUCCESS action", () => {
|
|
43
71
|
const ids = ["foo", "bar"];
|
|
44
72
|
const type = "type";
|
|
@@ -2,7 +2,8 @@ import { initialState, structureImpactGraph } from "../structureImpactGraph";
|
|
|
2
2
|
import {
|
|
3
3
|
clearStructure,
|
|
4
4
|
fetchStructure,
|
|
5
|
-
fetchStructureGraph
|
|
5
|
+
fetchStructureGraph,
|
|
6
|
+
createGraph
|
|
6
7
|
} from "../../routines";
|
|
7
8
|
|
|
8
9
|
const fooState = { foo: "bar" };
|
|
@@ -35,6 +36,28 @@ describe("reducers: structureImpactGraph", () => {
|
|
|
35
36
|
).toBe(data);
|
|
36
37
|
});
|
|
37
38
|
|
|
39
|
+
it("should extract the data from the payload after receiving the createGraph.SUCCESS action", () => {
|
|
40
|
+
const data = { opts: { type: "impact" } };
|
|
41
|
+
const payload = { data };
|
|
42
|
+
expect(
|
|
43
|
+
structureImpactGraph(fooState, {
|
|
44
|
+
type: createGraph.SUCCESS,
|
|
45
|
+
payload
|
|
46
|
+
})
|
|
47
|
+
).toBe(data);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should leave the state unchanged if createGraph succeeds and was called from LineageContextMenu", () => {
|
|
51
|
+
const data = { opts: { type: "impact" }, fromLineageContextMenu: true };
|
|
52
|
+
const payload = { data };
|
|
53
|
+
expect(
|
|
54
|
+
structureImpactGraph(fooState, {
|
|
55
|
+
type: createGraph.SUCCESS,
|
|
56
|
+
payload
|
|
57
|
+
})
|
|
58
|
+
).toBe(fooState);
|
|
59
|
+
});
|
|
60
|
+
|
|
38
61
|
it("should leave thes tate unchanged if the type of the fetchStructureGraph.SUCCESS action is not impact", () => {
|
|
39
62
|
const data = { opts: { type: "foo" } };
|
|
40
63
|
const payload = { data };
|
|
@@ -2,7 +2,8 @@ import { initialState, structureLineageGraph } from "../structureLineageGraph";
|
|
|
2
2
|
import {
|
|
3
3
|
clearStructure,
|
|
4
4
|
fetchStructure,
|
|
5
|
-
fetchStructureGraph
|
|
5
|
+
fetchStructureGraph,
|
|
6
|
+
createGraph,
|
|
6
7
|
} from "../../routines";
|
|
7
8
|
|
|
8
9
|
const fooState = { foo: "bar" };
|
|
@@ -35,6 +36,39 @@ describe("reducers: structureLineageGraph", () => {
|
|
|
35
36
|
).toBe(data);
|
|
36
37
|
});
|
|
37
38
|
|
|
39
|
+
it("should extract the data from the payload after receiving the createGraph.SUCCESS action", () => {
|
|
40
|
+
const data = { opts: { type: "lineage" } };
|
|
41
|
+
const payload = { data };
|
|
42
|
+
expect(
|
|
43
|
+
structureLineageGraph(fooState, {
|
|
44
|
+
type: createGraph.SUCCESS,
|
|
45
|
+
payload
|
|
46
|
+
})
|
|
47
|
+
).toBe(data);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("should leave the state unchanged if the type of the fetchStructureGraph.SUCCESS action is not lineage", () => {
|
|
51
|
+
const data = { opts: { type: "foo" } };
|
|
52
|
+
const payload = { data };
|
|
53
|
+
expect(
|
|
54
|
+
structureLineageGraph(fooState, {
|
|
55
|
+
type: fetchStructureGraph.SUCCESS,
|
|
56
|
+
payload
|
|
57
|
+
})
|
|
58
|
+
).toBe(fooState);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should leave the state unchanged if createGraph succeeds and was called from LineageContextMenu", () => {
|
|
62
|
+
const data = { opts: { type: "impact" }, fromLineageContextMenu: true };
|
|
63
|
+
const payload = { data };
|
|
64
|
+
expect(
|
|
65
|
+
structureLineageGraph(fooState, {
|
|
66
|
+
type: createGraph.SUCCESS,
|
|
67
|
+
payload
|
|
68
|
+
})
|
|
69
|
+
).toBe(fooState);
|
|
70
|
+
});
|
|
71
|
+
|
|
38
72
|
it("should leave thes tate unchanged if the type of the fetchStructureGraph.SUCCESS action is not lineage", () => {
|
|
39
73
|
const data = { opts: { type: "foo" } };
|
|
40
74
|
const payload = { data };
|
package/src/reducers/graph.js
CHANGED
|
@@ -11,8 +11,6 @@ export const initialState = {};
|
|
|
11
11
|
|
|
12
12
|
export const graph = (state = initialState, { type, payload }) => {
|
|
13
13
|
switch (type) {
|
|
14
|
-
case clearStructure.TRIGGER:
|
|
15
|
-
return initialState;
|
|
16
14
|
case fetchStructure.TRIGGER:
|
|
17
15
|
return initialState;
|
|
18
16
|
case clearGraph.TRIGGER:
|
|
@@ -6,21 +6,37 @@ export const initialState = { ids: [], type: "lineage", excludes: [] };
|
|
|
6
6
|
export const lineageQuery = (state = initialState, { type, payload }) => {
|
|
7
7
|
switch (type) {
|
|
8
8
|
case excludeNode.TRIGGER: {
|
|
9
|
-
const { id } = payload;
|
|
9
|
+
const { id, fromLineageContextMenu } = payload;
|
|
10
10
|
const { excludes } = state;
|
|
11
|
-
return {
|
|
11
|
+
return {
|
|
12
|
+
...state,
|
|
13
|
+
excludes: _.concat([id])(excludes),
|
|
14
|
+
fromLineageContextMenu: fromLineageContextMenu || false,
|
|
15
|
+
};
|
|
12
16
|
}
|
|
13
17
|
case createGraph.TRIGGER: {
|
|
14
|
-
const {
|
|
15
|
-
|
|
18
|
+
const {
|
|
19
|
+
ids = [],
|
|
20
|
+
type = "lineage",
|
|
21
|
+
levels,
|
|
22
|
+
fromLineageContextMenu,
|
|
23
|
+
} = payload;
|
|
24
|
+
return {
|
|
25
|
+
...state,
|
|
26
|
+
ids,
|
|
27
|
+
type,
|
|
28
|
+
excludes: [],
|
|
29
|
+
levels,
|
|
30
|
+
fromLineageContextMenu: fromLineageContextMenu || false,
|
|
31
|
+
};
|
|
16
32
|
}
|
|
17
33
|
case fetchGraph.SUCCESS: {
|
|
18
34
|
const {
|
|
19
35
|
data: {
|
|
20
36
|
ids,
|
|
21
37
|
opts: { type: type },
|
|
22
|
-
excludes: excludes
|
|
23
|
-
}
|
|
38
|
+
excludes: excludes,
|
|
39
|
+
},
|
|
24
40
|
} = payload;
|
|
25
41
|
return { ids, type, excludes, levels: state.levels };
|
|
26
42
|
}
|
|
@@ -2,7 +2,8 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import {
|
|
3
3
|
clearStructure,
|
|
4
4
|
fetchStructure,
|
|
5
|
-
fetchStructureGraph
|
|
5
|
+
fetchStructureGraph,
|
|
6
|
+
createGraph,
|
|
6
7
|
} from "../routines";
|
|
7
8
|
|
|
8
9
|
export const initialState = {};
|
|
@@ -16,8 +17,10 @@ export const structureImpactGraph = (
|
|
|
16
17
|
return initialState;
|
|
17
18
|
case fetchStructure.TRIGGER:
|
|
18
19
|
return initialState;
|
|
20
|
+
case createGraph.SUCCESS:
|
|
19
21
|
case fetchStructureGraph.SUCCESS:
|
|
20
|
-
return
|
|
22
|
+
return !payload?.data?.fromLineageContextMenu &&
|
|
23
|
+
_.pathEq("data.opts.type", "impact")(payload)
|
|
21
24
|
? _.prop("data")(payload)
|
|
22
25
|
: state;
|
|
23
26
|
default:
|
|
@@ -2,7 +2,8 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import {
|
|
3
3
|
clearStructure,
|
|
4
4
|
fetchStructure,
|
|
5
|
-
fetchStructureGraph
|
|
5
|
+
fetchStructureGraph,
|
|
6
|
+
createGraph,
|
|
6
7
|
} from "../routines";
|
|
7
8
|
|
|
8
9
|
export const initialState = {};
|
|
@@ -16,8 +17,10 @@ export const structureLineageGraph = (
|
|
|
16
17
|
return initialState;
|
|
17
18
|
case fetchStructure.TRIGGER:
|
|
18
19
|
return initialState;
|
|
20
|
+
case createGraph.SUCCESS:
|
|
19
21
|
case fetchStructureGraph.SUCCESS:
|
|
20
|
-
return
|
|
22
|
+
return !payload?.data?.fromLineageContextMenu &&
|
|
23
|
+
_.pathEq("data.opts.type", "lineage")(payload)
|
|
21
24
|
? _.prop("data")(payload)
|
|
22
25
|
: state;
|
|
23
26
|
default:
|
|
@@ -68,10 +68,13 @@ describe("sagas: createGraphRequestSaga", () => {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
describe("sagas: createGraphSaga", () => {
|
|
71
|
+
const fromLineageContextMenu = false;
|
|
72
|
+
|
|
71
73
|
const query = {
|
|
72
74
|
ids: ["BASILEAII_HIST_PROA_MOROSIDAD [ 2 ] [ 1 ].SOBREGIROCAPITAL"],
|
|
73
75
|
type: "lineage",
|
|
74
76
|
exclude: [],
|
|
77
|
+
fromLineageContextMenu,
|
|
75
78
|
};
|
|
76
79
|
|
|
77
80
|
const graphAccepted = {
|
|
@@ -80,7 +83,7 @@ describe("sagas: createGraphSaga", () => {
|
|
|
80
83
|
};
|
|
81
84
|
|
|
82
85
|
const graphCreated = {
|
|
83
|
-
data: graphData,
|
|
86
|
+
data: { ...graphData, fromLineageContextMenu },
|
|
84
87
|
status: 201,
|
|
85
88
|
};
|
|
86
89
|
|
|
@@ -114,7 +117,7 @@ describe("sagas: createGraphSaga", () => {
|
|
|
114
117
|
.next(graphAccepted)
|
|
115
118
|
.put(fetchGraph.request(graphAccepted))
|
|
116
119
|
.next()
|
|
117
|
-
.fork(polling, graphAccepted)
|
|
120
|
+
.fork(polling, graphAccepted, fromLineageContextMenu)
|
|
118
121
|
.next()
|
|
119
122
|
.take(cancelPoll.TRIGGER)
|
|
120
123
|
.next()
|
|
@@ -149,6 +152,8 @@ describe("sagas: createGraphSaga", () => {
|
|
|
149
152
|
});
|
|
150
153
|
|
|
151
154
|
describe("generator: polling", () => {
|
|
155
|
+
const fromLineageContextMenu = false;
|
|
156
|
+
|
|
152
157
|
const graphAccepted = {
|
|
153
158
|
data: graphAcceptedData,
|
|
154
159
|
status: 202,
|
|
@@ -160,13 +165,13 @@ describe("generator: polling", () => {
|
|
|
160
165
|
};
|
|
161
166
|
|
|
162
167
|
const graphCompleted = {
|
|
163
|
-
data: graphData,
|
|
168
|
+
data: { ...graphData, fromLineageContextMenu },
|
|
164
169
|
status: 200,
|
|
165
170
|
};
|
|
166
171
|
|
|
167
172
|
it("polling should keep requesting by graph hash until graph is received", () => {
|
|
168
173
|
expect(() => {
|
|
169
|
-
testSaga(polling, graphAccepted)
|
|
174
|
+
testSaga(polling, graphAccepted, fromLineageContextMenu)
|
|
170
175
|
.next()
|
|
171
176
|
.delay(1000)
|
|
172
177
|
.next()
|
|
@@ -202,7 +207,7 @@ describe("generator: polling", () => {
|
|
|
202
207
|
|
|
203
208
|
it("cancel should stop polling and return createGraph failure", () => {
|
|
204
209
|
expect(() => {
|
|
205
|
-
testSaga(polling, graphAccepted)
|
|
210
|
+
testSaga(polling, graphAccepted, fromLineageContextMenu)
|
|
206
211
|
.next()
|
|
207
212
|
.delay(1000)
|
|
208
213
|
.next()
|
package/src/sagas/createGraph.js
CHANGED
|
@@ -48,7 +48,11 @@ export function* createGraphSaga() {
|
|
|
48
48
|
if (graphAcceptedOrCreated.status == 202) {
|
|
49
49
|
yield put(fetchGraph.request(graphAcceptedOrCreated));
|
|
50
50
|
// starts the task in the background
|
|
51
|
-
const pollingTask = yield fork(
|
|
51
|
+
const pollingTask = yield fork(
|
|
52
|
+
polling,
|
|
53
|
+
graphAcceptedOrCreated,
|
|
54
|
+
body.fromLineageContextMenu
|
|
55
|
+
);
|
|
52
56
|
|
|
53
57
|
// wait for the user stop action
|
|
54
58
|
yield take(cancelPoll.TRIGGER);
|
|
@@ -56,7 +60,15 @@ export function* createGraphSaga() {
|
|
|
56
60
|
// this will cause the forked bgSync task to jump into its finally block
|
|
57
61
|
yield cancel(pollingTask);
|
|
58
62
|
} else if (graphAcceptedOrCreated.status == 201) {
|
|
59
|
-
yield put(
|
|
63
|
+
yield put(
|
|
64
|
+
createGraph.success({
|
|
65
|
+
...graphAcceptedOrCreated,
|
|
66
|
+
data: {
|
|
67
|
+
...graphAcceptedOrCreated.data,
|
|
68
|
+
fromLineageContextMenu: body.fromLineageContextMenu,
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
);
|
|
60
72
|
}
|
|
61
73
|
} catch (error) {
|
|
62
74
|
if (error.response) {
|
|
@@ -70,7 +82,7 @@ export function* createGraphSaga() {
|
|
|
70
82
|
}
|
|
71
83
|
}
|
|
72
84
|
|
|
73
|
-
export function* polling(graphAccepted) {
|
|
85
|
+
export function* polling(graphAccepted, fromLineageContextMenu) {
|
|
74
86
|
const backoff = exponentialBackoff(1.2, 0);
|
|
75
87
|
let backoffTime,
|
|
76
88
|
retry = 0,
|
|
@@ -113,7 +125,12 @@ export function* polling(graphAccepted) {
|
|
|
113
125
|
} while (!isCancelled && graphResp?.status == 202);
|
|
114
126
|
|
|
115
127
|
graphResp?.status == 200 && !isCancelled
|
|
116
|
-
? yield put(
|
|
128
|
+
? yield put(
|
|
129
|
+
createGraph.success({
|
|
130
|
+
...graphResp,
|
|
131
|
+
data: { ...graphResp.data, fromLineageContextMenu },
|
|
132
|
+
})
|
|
133
|
+
)
|
|
117
134
|
: yield put(createGraph.failure({}));
|
|
118
135
|
}
|
|
119
136
|
|
|
@@ -12,7 +12,8 @@ const getFields = (parent, structuresFields) =>
|
|
|
12
12
|
_.propOr([], _.path("id")(parent)),
|
|
13
13
|
_.map((sf) => ({
|
|
14
14
|
...sf,
|
|
15
|
-
label: _.prop("name")(parent),
|
|
15
|
+
label: _.prop("alias.text")(parent) || _.prop("name")(parent),
|
|
16
|
+
parent_index: _.prop("alias.index")(parent),
|
|
16
17
|
}))
|
|
17
18
|
)(structuresFields);
|
|
18
19
|
|
|
@@ -20,7 +21,7 @@ const getFieldsFromStructures = (structuresFields, parentStructures) =>
|
|
|
20
21
|
_.flow(
|
|
21
22
|
_.map((parent) => getFields(parent, structuresFields)),
|
|
22
23
|
_.flatten,
|
|
23
|
-
_.uniqBy(
|
|
24
|
+
_.uniqBy((s) => `${s.data_structure_id}/${s.parent_index}`),
|
|
24
25
|
_.map(withFieldType)
|
|
25
26
|
)(parentStructures);
|
|
26
27
|
|