@truedat/dq 4.47.1 → 4.47.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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.47.4] 2022-06-29
4
+
5
+ - [TD-4921] Add implementation workflow events
6
+
7
+ ## [4.47.2] 2022-06-24
8
+
9
+ ### Added
10
+
11
+ - [TD-4920] Implementation results for workflow
12
+
3
13
  ## [4.46.13] 2022-06-21
4
14
 
5
15
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dq",
3
- "version": "4.47.1",
3
+ "version": "4.47.4",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.16.4",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.47.1",
37
+ "@truedat/test": "4.47.4",
38
38
  "babel-jest": "^28.1.0",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -88,8 +88,8 @@
88
88
  },
89
89
  "dependencies": {
90
90
  "@apollo/client": "^3.6.4",
91
- "@truedat/core": "4.47.1",
92
- "@truedat/df": "4.47.1",
91
+ "@truedat/core": "4.47.4",
92
+ "@truedat/df": "4.47.4",
93
93
  "axios": "^0.19.2",
94
94
  "graphql": "^15.5.3",
95
95
  "path-to-regexp": "^1.7.0",
@@ -110,5 +110,5 @@
110
110
  "react-dom": ">= 16.8.6 < 17",
111
111
  "semantic-ui-react": ">= 0.88.2 < 2.1"
112
112
  },
113
- "gitHead": "dffde75b85272debd04fb2fe17c2f54f9045f112"
113
+ "gitHead": "9d38ae9759ce669fe1b459a3ee80c314d33871e0"
114
114
  }
@@ -14,3 +14,49 @@ export const IMPLEMENTATION_WITH_VERSIONS_QUERY = gql`
14
14
  }
15
15
  }
16
16
  `;
17
+
18
+ export const IMPLEMENTATION_RESULTS = gql`
19
+ query Implementation($id: ID!) {
20
+ implementation(id: $id) {
21
+ id
22
+ implementation_key
23
+ versions {
24
+ id
25
+ implementation_key
26
+ version
27
+ status
28
+ minimum
29
+ goal
30
+ results {
31
+ id
32
+ date
33
+ details
34
+ errors
35
+ has_remediation
36
+ has_segments
37
+ params
38
+ records
39
+ result
40
+ result_type
41
+ }
42
+ }
43
+ }
44
+ }
45
+ `;
46
+
47
+ export const IMPLEMENTATION_RESULT = gql`
48
+ query ImplementationResult($id: ID!) {
49
+ implementationResult(id: $id) {
50
+ id
51
+ date
52
+ details
53
+ params
54
+ errors
55
+ records
56
+ result
57
+ result_type
58
+ has_segments
59
+ has_remediation
60
+ }
61
+ }
62
+ `;
@@ -8,15 +8,11 @@ import { FormattedMessage } from "react-intl";
8
8
  import { RULES, IMPLEMENTATIONS, linkTo } from "@truedat/core/routes";
9
9
  import { DateTime } from "@truedat/core/components";
10
10
 
11
- export const ImplementationCrumbs = ({ ruleImplementation }) => {
11
+ export const ImplementationCrumbs = ({ ruleImplementation, ruleResult }) => {
12
12
  const { rule_result_id } = useParams();
13
13
  const rule = _.get("rule")(ruleImplementation);
14
14
 
15
- const ruleResultDate = _.flow(
16
- _.propOr([], "results"),
17
- _.find(_.propEq("id", _.toNumber(rule_result_id))),
18
- _.pathOr("0000-00-00 00:00", "date")
19
- )(ruleImplementation);
15
+ const ruleResultDate = _.pathOr("0000-00-00 00:00", "date")(ruleResult);
20
16
 
21
17
  return (
22
18
  <Breadcrumb>
@@ -82,10 +78,10 @@ export const ImplementationCrumbs = ({ ruleImplementation }) => {
82
78
 
83
79
  ImplementationCrumbs.propTypes = {
84
80
  ruleImplementation: PropTypes.object,
81
+ ruleResult: PropTypes.object,
85
82
  };
86
83
 
87
- const mapStateToProps = ({ rule, ruleImplementation }) => ({
88
- rule,
84
+ const mapStateToProps = ({ ruleImplementation }) => ({
89
85
  ruleImplementation,
90
86
  });
91
87
  export default connect(mapStateToProps)(ImplementationCrumbs);
@@ -79,7 +79,6 @@ export const ImplementationsRoutes = ({
79
79
  implementationStructures,
80
80
  implementationStructuresLoaded,
81
81
  }) => {
82
- const latest = _.head(ruleImplementation.results);
83
82
  const authorized = useAuthorized();
84
83
  const { rule_result_id: ruleResultId } = useParams();
85
84
  return (
@@ -308,7 +307,7 @@ export const ImplementationsRoutes = ({
308
307
  <Segment>
309
308
  {ruleImplementationLoaded ? (
310
309
  <RuleImplementation>
311
- <RuleImplementationResults ruleResult={latest} />
310
+ <RuleImplementationResults />
312
311
  </RuleImplementation>
313
312
  ) : null}
314
313
  </Segment>
@@ -341,7 +340,7 @@ export const ImplementationsRoutes = ({
341
340
  <Segment>
342
341
  {ruleImplementationLoaded ? (
343
342
  <RuleImplementation>
344
- <RuleResultDetails ruleResultId={latest.id} />
343
+ <RuleResultDetails />
345
344
  </RuleImplementation>
346
345
  ) : null}
347
346
  </Segment>
@@ -1,12 +1,16 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
+ import { useParams } from "react-router-dom";
4
+ import { useQuery } from "@apollo/client";
3
5
  import PropTypes from "prop-types";
4
6
  import { useIntl } from "react-intl";
5
7
  import { connect } from "react-redux";
6
8
  import { Table, Message, Divider } from "semantic-ui-react";
7
9
  import { columnDecorator } from "@truedat/core/services";
8
10
  import Moment from "react-moment";
11
+ import { Loading } from "@truedat/core/components";
9
12
  import { getRuleResultsColumns } from "../selectors";
13
+ import { IMPLEMENTATION_RESULTS } from "../api/queries";
10
14
  import RuleResultRow from "./RuleResultRow";
11
15
 
12
16
  const optionalColumns = ["errors", "records", "details"];
@@ -22,15 +26,25 @@ export const getCustomColumnsWithData = (ruleResults, columns) =>
22
26
 
23
27
  export const RuleImplementationResults = ({
24
28
  ruleImplementation,
25
- customColumns,
29
+ ruleResultsColumns,
26
30
  isAdmin,
27
31
  }) => {
28
32
  const { formatMessage, locale } = useIntl();
29
33
 
30
34
  if (_.isEmpty(ruleImplementation)) return null;
31
35
 
32
- const ruleResults = ruleImplementation.results;
33
- const optionalColumns = getOptionalColumnsWithData(ruleResults);
36
+ const implementationVersions = _.propOr([], "versions")(ruleImplementation);
37
+ const currentImplementationVersion = _.flow(
38
+ _.filter((version) => version.id === ruleImplementation.id),
39
+ _.first
40
+ )(implementationVersions);
41
+
42
+ const commonProps = {
43
+ ruleImplementation,
44
+ isAdmin,
45
+ ruleResultsColumns,
46
+ formatMessage,
47
+ };
34
48
 
35
49
  return (
36
50
  <>
@@ -61,77 +75,126 @@ export const RuleImplementationResults = ({
61
75
  </p>
62
76
  </Message>
63
77
  ) : null}
64
- {_.isEmpty(ruleResults) ? (
65
- <Message
66
- style={{ marginTop: "14px" }}
67
- header={formatMessage({
68
- id: "rule.ruleImplementation.results.empty",
69
- })}
70
- />
71
- ) : (
72
- <Table className="implementation-results small">
73
- <Table.Header>
74
- <Table.Row>
75
- <Table.HeaderCell
76
- content={formatMessage({ id: "ruleResult.props.date" })}
77
- />
78
- <Table.HeaderCell
79
- content={formatMessage({ id: "ruleResult.props.quality" })}
80
- />
81
- {_.includes("records")(optionalColumns) ? (
82
- <Table.HeaderCell
83
- content={formatMessage({ id: "ruleResult.props.records" })}
84
- />
85
- ) : null}
86
- {_.includes("errors")(optionalColumns) ? (
87
- <Table.HeaderCell
88
- content={formatMessage({ id: "ruleResult.props.errors" })}
89
- />
90
- ) : null}
91
- {customColumns.map((column, index) => (
92
- <Table.HeaderCell
93
- key={index}
94
- content={formatMessage({
95
- id: `ruleResult.props.${column.name}`,
96
- defaultMessage: column.name,
97
- })}
98
- />
99
- ))}
100
- {<Table.HeaderCell />}
101
- {isAdmin ? <Table.HeaderCell /> : null}
102
- </Table.Row>
103
- </Table.Header>
104
- <Table.Body>
105
- {ruleResults.map((result, i) => (
106
- <RuleResultRow
107
- key={i}
108
- optionalColumns={optionalColumns}
109
- ruleResult={result}
110
- customColumns={customColumns}
111
- isAdmin={isAdmin}
112
- ruleImplementation={ruleImplementation}
113
- />
114
- ))}
115
- </Table.Body>
116
- </Table>
117
- )}
78
+ {resultsTable({
79
+ commonProps,
80
+ implementationVersions,
81
+ currentImplementationVersion,
82
+ })}
118
83
  </>
119
84
  );
120
85
  };
121
86
 
87
+ export const resultsTable = ({
88
+ commonProps,
89
+ implementationVersions,
90
+ currentImplementationVersion,
91
+ }) => {
92
+ const { isAdmin, ruleResultsColumns, formatMessage } = commonProps;
93
+
94
+ const ruleResults = _.flow(
95
+ _.map((iv) => _.pathOr([], "results")(iv)),
96
+ _.flatten
97
+ )(implementationVersions);
98
+ const optionalColumns = getOptionalColumnsWithData(ruleResults);
99
+ const customColumns = getCustomColumnsWithData(
100
+ ruleResults,
101
+ ruleResultsColumns
102
+ );
103
+
104
+ return _.isEmpty(ruleResults) ? (
105
+ <Message
106
+ style={{ marginTop: "14px" }}
107
+ header={formatMessage({
108
+ id: "rule.ruleImplementation.results.empty",
109
+ })}
110
+ />
111
+ ) : (
112
+ <Table className="implementation-results small">
113
+ <Table.Header>
114
+ <Table.Row>
115
+ <Table.HeaderCell
116
+ content={formatMessage({ id: "ruleResult.props.date" })}
117
+ />
118
+ <Table.HeaderCell
119
+ content={formatMessage({ id: "ruleResult.props.quality" })}
120
+ />
121
+ {_.includes("records")(optionalColumns) ? (
122
+ <Table.HeaderCell
123
+ content={formatMessage({ id: "ruleResult.props.records" })}
124
+ />
125
+ ) : null}
126
+ {_.includes("errors")(optionalColumns) ? (
127
+ <Table.HeaderCell
128
+ content={formatMessage({ id: "ruleResult.props.errors" })}
129
+ />
130
+ ) : null}
131
+ {customColumns.map((column, index) => (
132
+ <Table.HeaderCell
133
+ key={index}
134
+ content={formatMessage({
135
+ id: `ruleResult.props.${column.name}`,
136
+ defaultMessage: column.name,
137
+ })}
138
+ />
139
+ ))}
140
+ {<Table.HeaderCell />}
141
+ {isAdmin ? <Table.HeaderCell /> : null}
142
+ </Table.Row>
143
+ </Table.Header>
144
+ <Table.Body>
145
+ {implementationVersions.map((version, i) =>
146
+ _.pathOr(
147
+ [],
148
+ "results"
149
+ )(version).map((result, j) => (
150
+ <RuleResultRow
151
+ key={"version" + i + "_result" + j}
152
+ optionalColumns={optionalColumns}
153
+ ruleResult={result}
154
+ customColumns={customColumns}
155
+ isAdmin={isAdmin}
156
+ ruleImplementation={version}
157
+ active={currentImplementationVersion.id == version.id}
158
+ tagLabel={
159
+ j === 0
160
+ ? `${formatMessage({
161
+ id: "ruleImplementations.props.version",
162
+ })}: ${version.version}`
163
+ : null
164
+ }
165
+ />
166
+ ))
167
+ )}
168
+ </Table.Body>
169
+ </Table>
170
+ );
171
+ };
172
+
122
173
  RuleImplementationResults.propTypes = {
123
174
  ruleImplementation: PropTypes.object,
124
- customColumns: PropTypes.array,
125
175
  isAdmin: PropTypes.bool,
176
+ ruleResultsColumns: PropTypes.array,
126
177
  };
127
178
 
128
- const mapStateToProps = (state) => ({
129
- ruleImplementation: state.ruleImplementation,
130
- customColumns: getCustomColumnsWithData(
131
- state.ruleImplementation?.results,
132
- getRuleResultsColumns(state)
133
- ),
134
- isAdmin: state.authentication.role === "admin",
135
- });
179
+ const mapStateToProps = (state) => ({ state: state });
180
+
181
+ export const RuleImplementationResultsLoader = (props) => {
182
+ const { state } = props;
183
+ const { implementation_id: id } = useParams();
184
+ const { loading, error, data } = useQuery(IMPLEMENTATION_RESULTS, {
185
+ variables: { id },
186
+ });
187
+ if (error) return null;
188
+ if (loading) return <Loading />;
189
+ const ruleImplementation = data?.implementation;
190
+ const componentProperties = {
191
+ ruleImplementation,
192
+ ruleResultsColumns: getRuleResultsColumns(state),
193
+ isAdmin: state.authentication.role === "admin",
194
+ };
195
+ return <RuleImplementationResults {...componentProperties} />;
196
+ };
136
197
 
137
- export default connect(mapStateToProps)(RuleImplementationResults);
198
+ export default connect(mapStateToProps, { RuleImplementationResults })(
199
+ RuleImplementationResultsLoader
200
+ );
@@ -2,19 +2,11 @@ import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
- import { useParams } from "react-router-dom";
6
5
  import { Header, Icon } from "semantic-ui-react";
7
6
  import { FormattedMessage } from "react-intl";
8
7
  import RuleImplementationResultTabs from "./RuleImplementationResultTabs";
9
8
 
10
- export const RuleResult = ({ ruleImplementation, ruleResultId, children }) => {
11
- const { rule_result_id: paramsId } = useParams();
12
- const resultId = _.defaultTo(_.toNumber(paramsId))(ruleResultId);
13
-
14
- const ruleResult = _.find(_.propEq("id", resultId))(
15
- ruleImplementation.results
16
- );
17
-
9
+ export const RuleResult = ({ ruleResult, children }) => {
18
10
  const renderRuleResult = () => {
19
11
  return (
20
12
  <>
@@ -34,20 +26,14 @@ export const RuleResult = ({ ruleImplementation, ruleResultId, children }) => {
34
26
  };
35
27
 
36
28
  RuleResult.propTypes = {
37
- ruleImplementation: PropTypes.object,
38
- ruleResultId: PropTypes.number,
29
+ ruleResult: PropTypes.object,
39
30
  children: PropTypes.oneOfType([
40
31
  PropTypes.node,
41
32
  PropTypes.arrayOf(PropTypes.node),
42
33
  ]),
43
34
  };
44
35
 
45
- const mapStateToProps = ({
46
- ruleImplementation,
47
- remediationLoading,
48
- templatesLoading,
49
- }) => ({
50
- ruleImplementation,
36
+ const mapStateToProps = ({ remediationLoading, templatesLoading }) => ({
51
37
  remediationLoading,
52
38
  templatesLoading,
53
39
  });
@@ -3,7 +3,6 @@ import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { useIntl } from "react-intl";
5
5
  import { connect } from "react-redux";
6
- import { useParams } from "react-router-dom";
7
6
  import { Table, Icon } from "semantic-ui-react";
8
7
  import { DateTime } from "@truedat/core/components";
9
8
  import { selectColor } from "../functions/selectors";
@@ -82,15 +81,8 @@ const DetailRow = ({ details }) => {
82
81
 
83
82
  DetailRow.propTypes = { details: PropTypes.object };
84
83
 
85
- export const RuleResultDetails = ({ ruleImplementation, ruleResultId }) => {
84
+ export const RuleResultDetails = ({ ruleImplementation, ruleResult }) => {
86
85
  const { formatMessage } = useIntl();
87
- const { rule_result_id: paramsId } = useParams();
88
-
89
- const resultId = _.defaultTo(_.toNumber(paramsId))(ruleResultId);
90
-
91
- const ruleResult = _.find(_.propEq("id", resultId))(
92
- ruleImplementation.results
93
- );
94
86
 
95
87
  return _.isEmpty(ruleResult) ? null : (
96
88
  <>
@@ -136,6 +128,7 @@ export const RuleResultDetails = ({ ruleImplementation, ruleResultId }) => {
136
128
  RuleResultDetails.propTypes = {
137
129
  ruleImplementation: PropTypes.object,
138
130
  ruleResultId: PropTypes.number,
131
+ ruleResult: PropTypes.object,
139
132
  };
140
133
 
141
134
  const mapStateToProps = ({ ruleImplementation }) => ({ ruleImplementation });
@@ -1,38 +1,22 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
- import { connect } from "react-redux";
5
- import { useParams } from "react-router-dom";
6
4
  import RemediationPlan from "./RemediationPlan";
7
5
  import "../styles/executionDetails.less";
8
6
 
9
- export const RuleResultRemediations = ({
10
- ruleImplementation,
11
- ruleResultId,
12
- }) => {
13
- const { rule_result_id: paramsId } = useParams();
14
-
15
- const resultId = _.defaultTo(_.toNumber(paramsId))(ruleResultId);
16
-
17
- const ruleResult = _.find(_.propEq("id", resultId))(
18
- ruleImplementation.results
19
- );
20
-
7
+ export const RuleResultRemediations = ({ ruleResult }) => {
8
+ const resultId = ruleResult.id;
21
9
  return _.isEmpty(ruleResult) ? null : (
22
- <>
23
- <RemediationPlan
24
- className="execution-details-remediation"
25
- latestResultId={resultId}
26
- />
27
- </>
10
+ <RemediationPlan
11
+ className="execution-details-remediation"
12
+ latestResultId={resultId}
13
+ />
28
14
  );
29
15
  };
30
16
 
31
17
  RuleResultRemediations.propTypes = {
32
18
  ruleImplementation: PropTypes.object,
33
- ruleResultId: PropTypes.number,
19
+ ruleResult: PropTypes.object,
34
20
  };
35
21
 
36
- const mapStateToProps = ({ ruleImplementation }) => ({ ruleImplementation });
37
-
38
- export default connect(mapStateToProps)(RuleResultRemediations);
22
+ export default RuleResultRemediations;