@truedat/dq 4.42.6 → 4.43.2
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 +22 -3
- package/package.json +5 -5
- package/src/api.js +8 -0
- package/src/components/ConditionSummary.js +1 -0
- package/src/components/FieldSummary.js +86 -0
- package/src/components/ImplementationStructureDelete.js +41 -0
- package/src/components/ImplementationStructureLink.js +24 -0
- package/src/components/ImplementationStructures.js +138 -0
- package/src/components/ImplementationStructuresNew.js +125 -0
- package/src/components/ImplementationSummary.js +11 -1
- package/src/components/NewRemediation.js +27 -20
- package/src/components/NewRuleImplementation.js +42 -6
- package/src/components/RemediationPlan.js +47 -78
- package/src/components/RuleImplementationProperties.js +2 -1
- package/src/components/RuleImplementationResultTabs.js +113 -0
- package/src/components/RuleImplementationResults.js +1 -1
- package/src/components/RuleImplementationTabs.js +16 -1
- package/src/components/RuleImplementationsTable.js +10 -3
- package/src/components/RuleResult.js +108 -0
- package/src/components/{ExecutionDetails.js → RuleResultDetails.js} +4 -21
- package/src/components/RuleResultRemediationLoader.js +44 -0
- package/src/components/RuleResultRemediations.js +47 -0
- package/src/components/RuleResultRow.js +0 -3
- package/src/components/RuleResultSegmentRow.js +83 -0
- package/src/components/RuleResultSegments.js +102 -0
- package/src/components/RuleResultSegmentsLoader.js +34 -0
- package/src/components/RuleResultsRoutes.js +73 -0
- package/src/components/RuleRoutes.js +38 -12
- package/src/components/__test_samples__/NewRuleImplementationProps.js +22 -2
- package/src/components/__tests__/ExecutionDetails.spec.js +5 -5
- package/src/components/__tests__/ImplementationStructureDelete.spec.js +27 -0
- package/src/components/__tests__/ImplementationStructureLink.spec.js +23 -0
- package/src/components/__tests__/ImplementationStructures.spec.js +88 -0
- package/src/components/__tests__/ImplementationStructuresNew.spec.js +34 -0
- package/src/components/__tests__/NewRuleImplementation.spec.js +27 -7
- package/src/components/__tests__/RuleImplementation.spec.js +2 -1
- package/src/components/__tests__/RuleImplementationTabs.spec.js +2 -1
- package/src/components/__tests__/RuleResultSegmentsLoader.spec.js +32 -0
- package/src/components/__tests__/__snapshots__/ExecutionDetails.spec.js.snap +2 -30
- package/src/components/__tests__/__snapshots__/ImplementationStructureDelete.spec.js.snap +10 -0
- package/src/components/__tests__/__snapshots__/ImplementationStructureLink.spec.js.snap +11 -0
- package/src/components/__tests__/__snapshots__/ImplementationStructures.spec.js.snap +208 -0
- package/src/components/__tests__/__snapshots__/ImplementationStructuresNew.spec.js.snap +106 -0
- package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +1211 -1217
- package/src/components/__tests__/__snapshots__/RuleImplementation.spec.js.snap +7 -1
- package/src/components/__tests__/__snapshots__/RuleImplementationProperties.spec.js.snap +1 -0
- package/src/components/__tests__/__snapshots__/RuleImplementationTabs.spec.js.snap +8 -2
- package/src/components/index.js +2 -2
- package/src/components/ruleImplementationForm/DatasetForm.js +4 -1
- package/src/components/ruleImplementationForm/FieldsGrid.js +57 -0
- package/src/components/ruleImplementationForm/FieldsGroup.js +107 -0
- package/src/components/ruleImplementationForm/RuleImplementationForm.js +45 -0
- package/src/components/ruleImplementationForm/SegmentsForm.js +35 -0
- package/src/components/ruleImplementationForm/__tests__/DataSetForm.spec.js +0 -1
- package/src/components/ruleImplementationForm/__tests__/RuleImplementationForm.spec.js +27 -10
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationForm.spec.js.snap +315 -91
- package/src/messages/en.js +20 -1
- package/src/messages/es.js +21 -1
- package/src/reducers/__tests__/segmentResult.spec.js +46 -0
- package/src/reducers/index.js +2 -0
- package/src/reducers/ruleImplementation.js +2 -0
- package/src/reducers/ruleImplementationRedirect.js +4 -0
- package/src/reducers/segmentResults.js +19 -0
- package/src/routines.js +10 -0
- package/src/sagas/__tests__/createImplementationStructure.spec.js +86 -0
- package/src/sagas/__tests__/deleteImplementationStructure.spec.js +84 -0
- package/src/sagas/__tests__/fetchSegmentResults.spec.js +78 -0
- package/src/sagas/createImplementationStructure.js +32 -0
- package/src/sagas/deleteImplementationStructure.js +37 -0
- package/src/sagas/fetchSegmentResults.js +30 -0
- package/src/sagas/index.js +19 -10
- package/src/services/encodeRawContent.js +5 -5
- package/src/styles/remediationPlan.less +5 -0
- package/src/styles/ruleImplementationForm/DatasetForm.less +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.43.2] 2022-05-03
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- [TD-4709] `DatasetForm` wasn't behaving correctly on implementations with
|
|
8
|
+
no dataset
|
|
9
|
+
|
|
10
|
+
## [4.43.1] 2022-04-28
|
|
11
|
+
|
|
12
|
+
# Added
|
|
13
|
+
|
|
14
|
+
- [TD-4538] Add Segment configuration and segment results for implementations
|
|
15
|
+
|
|
16
|
+
## [4.43.0] 2022-04-26
|
|
17
|
+
|
|
18
|
+
# Added
|
|
19
|
+
|
|
20
|
+
- [TD-3186] Support for linking Implementations and Structures
|
|
21
|
+
|
|
3
22
|
## [4.42.3] 2022-04-13
|
|
4
23
|
|
|
5
|
-
|
|
24
|
+
### Fixed
|
|
6
25
|
|
|
7
26
|
- [TD-4721] Remove sources error condition in NewRuleImplementation
|
|
8
27
|
|
|
9
28
|
## [4.42.1] 2022-04-12
|
|
10
29
|
|
|
11
|
-
|
|
30
|
+
### Changed
|
|
12
31
|
|
|
13
32
|
- [TD-4536] Support rule implementation with multiple populations
|
|
14
33
|
|
|
@@ -923,7 +942,7 @@ New major version for Truedat 4.0, no changes
|
|
|
923
942
|
|
|
924
943
|
- [TD-1802] Added individual saga to retrieve filter values
|
|
925
944
|
|
|
926
|
-
## [2.19.0]
|
|
945
|
+
## [2.19.0] 2019-05-16
|
|
927
946
|
|
|
928
947
|
### Added
|
|
929
948
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.43.2",
|
|
4
4
|
"description": "Truedat Web Data Quality Module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@babel/plugin-transform-modules-commonjs": "^7.15.0",
|
|
32
32
|
"@babel/preset-env": "^7.15.0",
|
|
33
33
|
"@babel/preset-react": "^7.14.5",
|
|
34
|
-
"@truedat/test": "4.
|
|
34
|
+
"@truedat/test": "4.43.2",
|
|
35
35
|
"babel-jest": "^27.0.6",
|
|
36
36
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
37
37
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"@apollo/client": "^3.4.10",
|
|
85
|
-
"@truedat/core": "4.
|
|
86
|
-
"@truedat/df": "4.
|
|
85
|
+
"@truedat/core": "4.43.2",
|
|
86
|
+
"@truedat/df": "4.43.2",
|
|
87
87
|
"axios": "^0.19.2",
|
|
88
88
|
"graphql": "^15.5.3",
|
|
89
89
|
"path-to-regexp": "^1.7.0",
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"react-dom": ">= 16.8.6 < 17",
|
|
104
104
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
105
105
|
},
|
|
106
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "26f59c4d36ab1ecfae705bbce4320ff443cce304"
|
|
107
107
|
}
|
package/src/api.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
const API_CONCEPT_RULES = "/api/rules/concept/:id";
|
|
2
2
|
const API_EXECUTION_GROUP = "/api/execution_groups/:id";
|
|
3
3
|
const API_EXECUTION_GROUPS = "/api/execution_groups";
|
|
4
|
+
const API_IMPLEMENTATIONS_STRUCTURES =
|
|
5
|
+
"/api/rule_implementations/:implementationId/data_structures";
|
|
6
|
+
const API_IMPLEMENTATIONS_STRUCTURE =
|
|
7
|
+
"/api/rule_implementations/data_structures/:id";
|
|
4
8
|
const API_RULE = "/api/rules/:id";
|
|
5
9
|
const API_REMEDIATION_PLAN = "/api/rule_results/:rule_result_id/remediation";
|
|
6
10
|
const API_RULES = "/api/rules";
|
|
@@ -18,6 +22,7 @@ const API_RULE_IMPLEMENTATION_FILTERS_SEARCH =
|
|
|
18
22
|
const API_RULE_IMPLEMENTATIONS_UPLOAD = "/api/rule_implementations/upload";
|
|
19
23
|
const API_RULE_RESULT = "/api/rule_results/:id";
|
|
20
24
|
const API_RULE_RESULTS = "/api/rule_results";
|
|
25
|
+
const API_SEGMENT_RESULTS = "/api/rule_results/:rule_result_id/segment_results";
|
|
21
26
|
const API_SUBSCRIPTIONS_SEARCH = "/api/subscriptions/user/me/search";
|
|
22
27
|
const API_SUBSCRIPTION = "/api/subscriptions/:id";
|
|
23
28
|
const API_SUBSCRIPTIONS = "/api/subscriptions";
|
|
@@ -26,6 +31,8 @@ export {
|
|
|
26
31
|
API_CONCEPT_RULES,
|
|
27
32
|
API_EXECUTION_GROUP,
|
|
28
33
|
API_EXECUTION_GROUPS,
|
|
34
|
+
API_IMPLEMENTATIONS_STRUCTURES,
|
|
35
|
+
API_IMPLEMENTATIONS_STRUCTURE,
|
|
29
36
|
API_REMEDIATION_PLAN,
|
|
30
37
|
API_RULE,
|
|
31
38
|
API_RULES,
|
|
@@ -41,6 +48,7 @@ export {
|
|
|
41
48
|
API_RULE_IMPLEMENTATIONS_UPLOAD,
|
|
42
49
|
API_RULE_RESULT,
|
|
43
50
|
API_RULE_RESULTS,
|
|
51
|
+
API_SEGMENT_RESULTS,
|
|
44
52
|
API_SUBSCRIPTIONS_SEARCH,
|
|
45
53
|
API_SUBSCRIPTION,
|
|
46
54
|
API_SUBSCRIPTIONS,
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Header, Icon, Segment, Table } from "semantic-ui-react";
|
|
5
|
+
import { Link } from "react-router-dom";
|
|
6
|
+
import { FormattedMessage } from "react-intl";
|
|
7
|
+
import { linkTo } from "@truedat/core/routes";
|
|
8
|
+
|
|
9
|
+
export const empty = (rows) =>
|
|
10
|
+
rows && _.every((r) => _.isEmpty(r) || _.isNil(r))(rows);
|
|
11
|
+
|
|
12
|
+
const ConditionCell = ({ row, alias }) => {
|
|
13
|
+
const alias_text = _.flow(
|
|
14
|
+
_.find({ index: row.structure?.parent_index }),
|
|
15
|
+
_.propOr(null, "text")
|
|
16
|
+
)(alias);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Table.Row>
|
|
20
|
+
<Table.Cell width={5}>
|
|
21
|
+
{_.has("structure")(row) && (
|
|
22
|
+
<>
|
|
23
|
+
<Link
|
|
24
|
+
to={linkTo.STRUCTURE({
|
|
25
|
+
id: _.path("structure.id")(row),
|
|
26
|
+
})}
|
|
27
|
+
>
|
|
28
|
+
<span className="highlighted">
|
|
29
|
+
{alias_text && `(${alias_text}).`}{" "}
|
|
30
|
+
{`"${_.pathOr("", "structure.name")(row)}"`}
|
|
31
|
+
</span>
|
|
32
|
+
</Link>
|
|
33
|
+
</>
|
|
34
|
+
)}
|
|
35
|
+
</Table.Cell>
|
|
36
|
+
</Table.Row>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
ConditionCell.propTypes = {
|
|
41
|
+
row: PropTypes.object,
|
|
42
|
+
alias: PropTypes.array,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const FieldSummary = ({ rows, type, icon, alias }) => {
|
|
46
|
+
const wrappedRows = [rows];
|
|
47
|
+
return empty(rows) ? null : (
|
|
48
|
+
<>
|
|
49
|
+
<Header as="h3">
|
|
50
|
+
<Icon name={icon} size="small" />
|
|
51
|
+
<Header.Content>
|
|
52
|
+
<FormattedMessage
|
|
53
|
+
id={`ruleImplementations.summary.headers.${type}`}
|
|
54
|
+
/>
|
|
55
|
+
</Header.Content>
|
|
56
|
+
</Header>
|
|
57
|
+
{wrappedRows.map((rows, i) => (
|
|
58
|
+
<Segment key={i}>
|
|
59
|
+
<Table basic="very">
|
|
60
|
+
<Table.Header>
|
|
61
|
+
<Table.Row>
|
|
62
|
+
<Table.HeaderCell>
|
|
63
|
+
<FormattedMessage id={`ruleImplementation.summary.field`} />
|
|
64
|
+
</Table.HeaderCell>
|
|
65
|
+
</Table.Row>
|
|
66
|
+
</Table.Header>
|
|
67
|
+
<Table.Body>
|
|
68
|
+
{rows.map((row, i) => (
|
|
69
|
+
<ConditionCell key={i} row={row} alias={alias} />
|
|
70
|
+
))}
|
|
71
|
+
</Table.Body>
|
|
72
|
+
</Table>
|
|
73
|
+
</Segment>
|
|
74
|
+
))}
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
FieldSummary.propTypes = {
|
|
80
|
+
icon: PropTypes.string,
|
|
81
|
+
rows: PropTypes.array,
|
|
82
|
+
type: PropTypes.string,
|
|
83
|
+
alias: PropTypes.array,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default FieldSummary;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { connect } from "react-redux";
|
|
4
|
+
import { Icon } from "semantic-ui-react";
|
|
5
|
+
import { FormattedMessage } from "react-intl";
|
|
6
|
+
import { ConfirmModal } from "@truedat/core/components";
|
|
7
|
+
import { deleteImplementationStructure } from "../routines";
|
|
8
|
+
|
|
9
|
+
export const ImplementationStructureDelete = ({
|
|
10
|
+
implementationId,
|
|
11
|
+
id,
|
|
12
|
+
deleteImplementationStructure,
|
|
13
|
+
}) => (
|
|
14
|
+
<ConfirmModal
|
|
15
|
+
icon="trash"
|
|
16
|
+
trigger={<Icon name="trash alternate outline" color="red" />}
|
|
17
|
+
header={
|
|
18
|
+
<FormattedMessage
|
|
19
|
+
id={"implementationsStructures.delete.confirmation.header"}
|
|
20
|
+
/>
|
|
21
|
+
}
|
|
22
|
+
content={
|
|
23
|
+
<FormattedMessage
|
|
24
|
+
id={"implementationsStructures.delete.confirmation.content"}
|
|
25
|
+
/>
|
|
26
|
+
}
|
|
27
|
+
onConfirm={() => deleteImplementationStructure({ implementationId, id })}
|
|
28
|
+
onOpen={(e) => e.stopPropagation()}
|
|
29
|
+
onClose={(e) => e.stopPropagation()}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
ImplementationStructureDelete.propTypes = {
|
|
34
|
+
implementationId: PropTypes.number,
|
|
35
|
+
id: PropTypes.number,
|
|
36
|
+
deleteImplementationStructure: PropTypes.func,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default connect(null, { deleteImplementationStructure })(
|
|
40
|
+
ImplementationStructureDelete
|
|
41
|
+
);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Link } from "react-router-dom";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { linkTo } from "@truedat/core/routes";
|
|
5
|
+
|
|
6
|
+
export const ImplementationStructureLink = ({
|
|
7
|
+
id,
|
|
8
|
+
current_version: { name },
|
|
9
|
+
}) => (
|
|
10
|
+
<Link
|
|
11
|
+
to={linkTo.STRUCTURE({
|
|
12
|
+
id,
|
|
13
|
+
})}
|
|
14
|
+
>
|
|
15
|
+
{name}
|
|
16
|
+
</Link>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
ImplementationStructureLink.propTypes = {
|
|
20
|
+
id: PropTypes.number,
|
|
21
|
+
current_version: PropTypes.object,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default ImplementationStructureLink;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { connect } from "react-redux";
|
|
5
|
+
import { Table, Button, Grid, Segment, Header, Icon } from "semantic-ui-react";
|
|
6
|
+
import { FormattedMessage } from "react-intl";
|
|
7
|
+
import { Link } from "react-router-dom";
|
|
8
|
+
import { linkTo } from "@truedat/core/routes";
|
|
9
|
+
import { columnDecorator } from "@truedat/core/services";
|
|
10
|
+
import ImplementationStructureDelete from "./ImplementationStructureDelete";
|
|
11
|
+
import ImplementationStructureLink from "./ImplementationStructureLink";
|
|
12
|
+
|
|
13
|
+
const ImplementationStructureDeleteDecorator = ({ id, implementation_id }) => (
|
|
14
|
+
<ImplementationStructureDelete id={id} implementationId={implementation_id} />
|
|
15
|
+
);
|
|
16
|
+
ImplementationStructureDeleteDecorator.propTypes = {
|
|
17
|
+
id: PropTypes.number,
|
|
18
|
+
implementation_id: PropTypes.number,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const PathDecorator = (path) => (
|
|
22
|
+
<span title={_.join(" › ")(path)}>
|
|
23
|
+
{_.flow(_.join(" › "), _.truncate({ length: 90 }))(path)}
|
|
24
|
+
</span>
|
|
25
|
+
);
|
|
26
|
+
PathDecorator.propTypes = {
|
|
27
|
+
path: PropTypes.string,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const ImplementationStructureTypeDecorator = (type) => (
|
|
31
|
+
<FormattedMessage id={`implementationsStructures.type.${type}`} />
|
|
32
|
+
);
|
|
33
|
+
ImplementationStructureTypeDecorator.propTypes = {
|
|
34
|
+
type: PropTypes.string,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const ImplementationStructures = ({ implementation, canCreateLink }) => {
|
|
38
|
+
const deleteColumn = canCreateLink
|
|
39
|
+
? [
|
|
40
|
+
{
|
|
41
|
+
fieldSelector: _.identity,
|
|
42
|
+
fieldDecorator: ImplementationStructureDeleteDecorator,
|
|
43
|
+
},
|
|
44
|
+
]
|
|
45
|
+
: [];
|
|
46
|
+
|
|
47
|
+
const columns = [
|
|
48
|
+
{
|
|
49
|
+
header: "structure.name",
|
|
50
|
+
fieldSelector: _.path("data_structure"),
|
|
51
|
+
fieldDecorator: ImplementationStructureLink,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
header: "structure.system",
|
|
55
|
+
fieldSelector: _.path("data_structure.system.name"),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
header: "structure.path",
|
|
59
|
+
fieldSelector: _.path("data_structure.current_version.path"),
|
|
60
|
+
fieldDecorator: PathDecorator,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
header: "implementationsStructures.type",
|
|
64
|
+
fieldSelector: _.path("type"),
|
|
65
|
+
fieldDecorator: ImplementationStructureTypeDecorator,
|
|
66
|
+
},
|
|
67
|
+
...deleteColumn,
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const headerRow = columns.map(({ header }, key) => (
|
|
71
|
+
<Table.HeaderCell
|
|
72
|
+
key={key}
|
|
73
|
+
content={header ? <FormattedMessage id={header} /> : null}
|
|
74
|
+
/>
|
|
75
|
+
));
|
|
76
|
+
|
|
77
|
+
const id = _.prop("rule_id")(implementation);
|
|
78
|
+
const implementation_id = _.prop("id")(implementation);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<Segment attached="bottom">
|
|
82
|
+
<Grid>
|
|
83
|
+
{id && canCreateLink && (
|
|
84
|
+
<Grid.Column width={16}>
|
|
85
|
+
<Button
|
|
86
|
+
floated="right"
|
|
87
|
+
primary
|
|
88
|
+
as={Link}
|
|
89
|
+
to={linkTo.IMPLEMENTATION_STRUCTURES_NEW({
|
|
90
|
+
id,
|
|
91
|
+
implementation_id,
|
|
92
|
+
})}
|
|
93
|
+
content={<FormattedMessage id="links.actions.create" />}
|
|
94
|
+
/>
|
|
95
|
+
</Grid.Column>
|
|
96
|
+
)}
|
|
97
|
+
{!_.isEmpty(implementation?.data_structures) ? (
|
|
98
|
+
<Grid.Column width={16}>
|
|
99
|
+
<Table
|
|
100
|
+
headerRow={headerRow}
|
|
101
|
+
renderBodyRow={(link, i) => (
|
|
102
|
+
<Table.Row key={i}>
|
|
103
|
+
{columns.map((column, ci) => (
|
|
104
|
+
<Table.Cell
|
|
105
|
+
key={ci}
|
|
106
|
+
textAlign={_.prop("textAlign")(column)}
|
|
107
|
+
content={columnDecorator(column)(link)}
|
|
108
|
+
/>
|
|
109
|
+
))}
|
|
110
|
+
</Table.Row>
|
|
111
|
+
)}
|
|
112
|
+
tableData={implementation?.data_structures}
|
|
113
|
+
/>
|
|
114
|
+
</Grid.Column>
|
|
115
|
+
) : (
|
|
116
|
+
<Header as="h4">
|
|
117
|
+
<Icon name="search" />
|
|
118
|
+
<Header.Content>
|
|
119
|
+
<FormattedMessage id="implementationStructures.empty" />
|
|
120
|
+
</Header.Content>
|
|
121
|
+
</Header>
|
|
122
|
+
)}
|
|
123
|
+
</Grid>
|
|
124
|
+
</Segment>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
ImplementationStructures.propTypes = {
|
|
129
|
+
implementation: PropTypes.object,
|
|
130
|
+
canCreateLink: PropTypes.bool,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const mapStateToProps = (state) => ({
|
|
134
|
+
implementation: state.ruleImplementation,
|
|
135
|
+
canCreateLink: _.propOr(false, "link_structure")(state.implementationActions),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export default connect(mapStateToProps)(ImplementationStructures);
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { connect } from "react-redux";
|
|
5
|
+
import { useIntl } from "react-intl";
|
|
6
|
+
import { Button, Dropdown, Grid, Header, Segment } from "semantic-ui-react";
|
|
7
|
+
import { HistoryBackButton } from "@truedat/core/components";
|
|
8
|
+
import { linkTo } from "@truedat/core/routes";
|
|
9
|
+
import { createImplementationStructure } from "../routines";
|
|
10
|
+
|
|
11
|
+
const StructureSelector = React.lazy(() =>
|
|
12
|
+
import("@truedat/dd/components/StructureSelector")
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export const ImplementationStructuresNew = ({
|
|
16
|
+
creatingImplementationStructure,
|
|
17
|
+
implementation,
|
|
18
|
+
createImplementationStructure,
|
|
19
|
+
}) => {
|
|
20
|
+
const { formatMessage } = useIntl();
|
|
21
|
+
const [selectedTarget, setSelectedTarget] = useState(null);
|
|
22
|
+
const [type, setType] = useState("dataset");
|
|
23
|
+
const submitDisabled = creatingImplementationStructure || !selectedTarget;
|
|
24
|
+
|
|
25
|
+
const handleTargetSelected = (selectedTarget) =>
|
|
26
|
+
setSelectedTarget(selectedTarget);
|
|
27
|
+
|
|
28
|
+
const handleSubmit = () => {
|
|
29
|
+
const redirectUrl = linkTo.IMPLEMENTATION_STRUCTURES({
|
|
30
|
+
id: implementation.rule_id,
|
|
31
|
+
implementation_id: implementation.id,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
createImplementationStructure({
|
|
35
|
+
implementationId: implementation.id,
|
|
36
|
+
dataStructureId: selectedTarget?.id,
|
|
37
|
+
type,
|
|
38
|
+
redirectUrl,
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const handleTypeChange = (e, { value }) => {
|
|
43
|
+
if (type !== value && (value === "dataset" || type === "dataset")) {
|
|
44
|
+
// Reset selectTarget only if changing type from or to "dataset"
|
|
45
|
+
// because structure class changes
|
|
46
|
+
setSelectedTarget(null);
|
|
47
|
+
}
|
|
48
|
+
setType(value);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const typeOptions = ["dataset", "population", "validation"].map((type) => ({
|
|
52
|
+
key: type,
|
|
53
|
+
value: type,
|
|
54
|
+
text: formatMessage({ id: `implementationsStructures.type.${type}` }),
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Segment attached="bottom">
|
|
59
|
+
<Grid>
|
|
60
|
+
<Grid.Column with={16}>
|
|
61
|
+
<Header
|
|
62
|
+
as="h4"
|
|
63
|
+
content={formatMessage({
|
|
64
|
+
id: "implementationsStructures.new.header",
|
|
65
|
+
})}
|
|
66
|
+
/>
|
|
67
|
+
<Dropdown
|
|
68
|
+
placeholder={formatMessage({
|
|
69
|
+
id: "implementationsStructures.type",
|
|
70
|
+
})}
|
|
71
|
+
selection
|
|
72
|
+
value={type}
|
|
73
|
+
onChange={handleTypeChange}
|
|
74
|
+
options={typeOptions}
|
|
75
|
+
/>
|
|
76
|
+
{
|
|
77
|
+
// Duplicated component and 'keys' to force Selector rerender on changing type to clean selection
|
|
78
|
+
type === "dataset" ? (
|
|
79
|
+
<StructureSelector
|
|
80
|
+
key="datasetSelector"
|
|
81
|
+
onSelect={handleTargetSelected}
|
|
82
|
+
defaultFilters={{ "class.raw": ["table"] }}
|
|
83
|
+
/>
|
|
84
|
+
) : (
|
|
85
|
+
<StructureSelector
|
|
86
|
+
key="nonDatasetSelector"
|
|
87
|
+
onSelect={handleTargetSelected}
|
|
88
|
+
defaultFilters={{ "class.raw": ["field"] }}
|
|
89
|
+
/>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
<div className="actions">
|
|
93
|
+
<HistoryBackButton
|
|
94
|
+
content={formatMessage({ id: "actions.cancel" })}
|
|
95
|
+
disabled={creatingImplementationStructure}
|
|
96
|
+
/>
|
|
97
|
+
|
|
98
|
+
<Button
|
|
99
|
+
primary
|
|
100
|
+
content={formatMessage({ id: "actions.create" })}
|
|
101
|
+
disabled={submitDisabled}
|
|
102
|
+
loading={creatingImplementationStructure}
|
|
103
|
+
onClick={handleSubmit}
|
|
104
|
+
/>
|
|
105
|
+
</div>
|
|
106
|
+
</Grid.Column>
|
|
107
|
+
</Grid>
|
|
108
|
+
</Segment>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
ImplementationStructuresNew.propTypes = {
|
|
113
|
+
implementation: PropTypes.object,
|
|
114
|
+
creatingImplementationStructure: PropTypes.bool,
|
|
115
|
+
createImplementationStructure: PropTypes.func,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const mapStateToProps = (state) => ({
|
|
119
|
+
creatingImplementationStructure: state.creatingImplementationStructure,
|
|
120
|
+
implementation: state.ruleImplementation,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
export default connect(mapStateToProps, { createImplementationStructure })(
|
|
124
|
+
ImplementationStructuresNew
|
|
125
|
+
);
|
|
@@ -6,6 +6,7 @@ import { Link } from "react-router-dom";
|
|
|
6
6
|
import { FormattedMessage } from "react-intl";
|
|
7
7
|
import { linkTo } from "@truedat/core/routes";
|
|
8
8
|
import ConditionSummary, { empty, path } from "./ConditionSummary";
|
|
9
|
+
import FieldSummary from "./FieldSummary";
|
|
9
10
|
import InformationSummary from "./InformationSummary";
|
|
10
11
|
import "../styles/ImplementationSummary.less";
|
|
11
12
|
|
|
@@ -15,6 +16,7 @@ const defaults = [
|
|
|
15
16
|
"dataset",
|
|
16
17
|
"populations",
|
|
17
18
|
"validations",
|
|
19
|
+
"segments",
|
|
18
20
|
];
|
|
19
21
|
|
|
20
22
|
const FormattedLink = ({ value, operator = {} }) =>
|
|
@@ -130,7 +132,7 @@ DatasetSummary.propTypes = {
|
|
|
130
132
|
|
|
131
133
|
export const ImplementationSummary = ({ ruleImplementation, activeSteps }) => {
|
|
132
134
|
const steps = _.isEmpty(activeSteps) ? defaults : activeSteps;
|
|
133
|
-
const { dataset, populations, validations } =
|
|
135
|
+
const { dataset, populations, validations, segments } =
|
|
134
136
|
_.pick(steps)(ruleImplementation);
|
|
135
137
|
const alias = _.map(_.propOr({}, "alias"))(dataset);
|
|
136
138
|
return (
|
|
@@ -158,6 +160,14 @@ export const ImplementationSummary = ({ ruleImplementation, activeSteps }) => {
|
|
|
158
160
|
alias={alias}
|
|
159
161
|
/>
|
|
160
162
|
)}
|
|
163
|
+
{segments && _.includes("segments")(steps) && (
|
|
164
|
+
<FieldSummary
|
|
165
|
+
type="segments"
|
|
166
|
+
icon="grid layout"
|
|
167
|
+
rows={segments}
|
|
168
|
+
alias={alias}
|
|
169
|
+
/>
|
|
170
|
+
)}
|
|
161
171
|
</>
|
|
162
172
|
);
|
|
163
173
|
};
|
|
@@ -2,11 +2,13 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import React, { useState } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
|
-
import { Button, Header, Icon, Segment } from "semantic-ui-react";
|
|
5
|
+
import { Button, Header, Icon, Container, Segment } from "semantic-ui-react";
|
|
6
6
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
7
7
|
import { createRemediation, fetchRuleImplementation } from "../routines";
|
|
8
8
|
import RemediationForm from "./RemediationForm";
|
|
9
9
|
|
|
10
|
+
import "../styles/remediationPlan.less";
|
|
11
|
+
|
|
10
12
|
export const NewRemediation = ({
|
|
11
13
|
manageRemediations,
|
|
12
14
|
onSaveRemediation,
|
|
@@ -23,25 +25,30 @@ export const NewRemediation = ({
|
|
|
23
25
|
|
|
24
26
|
return !manageRemediations || _.isEmpty(templates) ? null : (
|
|
25
27
|
<>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
28
|
+
<Container className="new-remedation-container" fluid>
|
|
29
|
+
{!isEdit ? (
|
|
30
|
+
<Button
|
|
31
|
+
primary
|
|
32
|
+
onClick={() => setIsEdit(!isEdit)}
|
|
33
|
+
content={formatMessage({ id: "remediation.actions.create" })}
|
|
34
|
+
/>
|
|
35
|
+
) : (
|
|
36
|
+
<>
|
|
37
|
+
<Header as="h2">
|
|
38
|
+
<Icon name="plug" />
|
|
39
|
+
<Header.Content>
|
|
40
|
+
<FormattedMessage id="remediation.actions.create" />
|
|
41
|
+
</Header.Content>
|
|
42
|
+
</Header>
|
|
43
|
+
<Segment>
|
|
44
|
+
<RemediationForm
|
|
45
|
+
onSave={onSave}
|
|
46
|
+
latestResultId={latestResultId}
|
|
47
|
+
/>
|
|
48
|
+
</Segment>
|
|
49
|
+
</>
|
|
50
|
+
)}
|
|
51
|
+
</Container>
|
|
45
52
|
</>
|
|
46
53
|
);
|
|
47
54
|
};
|