@truedat/dq 4.56.2 → 4.56.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 +5 -5
- package/src/api/queries.js +37 -9
- package/src/components/ConditionSummary.js +35 -18
- package/src/components/ImplementationExecutions.js +30 -30
- package/src/components/RuleImplementationResults.js +37 -24
- package/src/components/RuleResultRow.js +4 -1
- package/src/components/RuleResultsTable.js +32 -25
- package/src/components/__tests__/NewRuleImplementation.spec.js +24 -0
- package/src/components/__tests__/RuleImplementationResults.spec.js +18 -65
- package/src/components/__tests__/__fixtures__/implementationResultsMocks.js +137 -0
- package/src/components/__tests__/__snapshots__/ConditionSummary.spec.js.snap +1 -3
- package/src/components/__tests__/__snapshots__/ImplementationExecutions.spec.js.snap +24 -28
- package/src/components/__tests__/__snapshots__/ImplementationSummary.spec.js.snap +1 -2
- package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +5 -9
- package/src/components/__tests__/__snapshots__/RuleImplementationResults.spec.js.snap +216 -177
- package/src/components/ruleImplementationForm/FieldModifier.js +1 -0
- package/src/components/ruleImplementationForm/FiltersField.js +1 -0
- package/src/components/ruleImplementationForm/FiltersGrid.js +18 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.56.4] 2022-11-26
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- [TD-5247] Keep table name if structure field dropdown item changes
|
|
8
|
+
|
|
9
|
+
## [4.56.3] 2022-11-24
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- [TD-5286] Implementation results pagination
|
|
14
|
+
|
|
3
15
|
## [4.56.2] 2022-11-24
|
|
4
16
|
|
|
5
17
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.56.
|
|
3
|
+
"version": "4.56.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.56.
|
|
37
|
+
"@truedat/test": "4.56.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",
|
|
@@ -93,8 +93,8 @@
|
|
|
93
93
|
},
|
|
94
94
|
"dependencies": {
|
|
95
95
|
"@apollo/client": "^3.7.0",
|
|
96
|
-
"@truedat/core": "4.56.
|
|
97
|
-
"@truedat/df": "4.56.
|
|
96
|
+
"@truedat/core": "4.56.4",
|
|
97
|
+
"@truedat/df": "4.56.4",
|
|
98
98
|
"graphql": "^15.5.3",
|
|
99
99
|
"path-to-regexp": "^1.7.0",
|
|
100
100
|
"prop-types": "^15.8.1",
|
|
@@ -114,5 +114,5 @@
|
|
|
114
114
|
"react-dom": ">= 16.8.6 < 17",
|
|
115
115
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
116
116
|
},
|
|
117
|
-
"gitHead": "
|
|
117
|
+
"gitHead": "f327860aa80db650f562d53dc22218307f43e0ac"
|
|
118
118
|
}
|
package/src/api/queries.js
CHANGED
|
@@ -15,16 +15,17 @@ export const IMPLEMENTATION_VERSIONS_QUERY = gql`
|
|
|
15
15
|
}
|
|
16
16
|
`;
|
|
17
17
|
|
|
18
|
-
export const
|
|
19
|
-
query Implementation(
|
|
18
|
+
export const IMPLEMENTATION_RESULTS_CONNECTION_QUERY = gql`
|
|
19
|
+
query Implementation(
|
|
20
|
+
$id: ID!
|
|
21
|
+
$after: Cursor
|
|
22
|
+
$before: Cursor
|
|
23
|
+
$last: Int
|
|
24
|
+
$first: Int
|
|
25
|
+
) {
|
|
20
26
|
implementation(id: $id) {
|
|
21
27
|
id
|
|
22
|
-
|
|
23
|
-
lastQualityEvent {
|
|
24
|
-
insertedAt
|
|
25
|
-
message
|
|
26
|
-
type
|
|
27
|
-
}
|
|
28
|
+
version
|
|
28
29
|
versions {
|
|
29
30
|
id
|
|
30
31
|
implementationKey
|
|
@@ -32,7 +33,20 @@ export const IMPLEMENTATION_RESULTS_QUERY = gql`
|
|
|
32
33
|
status
|
|
33
34
|
minimum
|
|
34
35
|
goal
|
|
35
|
-
|
|
36
|
+
}
|
|
37
|
+
lastQualityEvent {
|
|
38
|
+
insertedAt
|
|
39
|
+
message
|
|
40
|
+
type
|
|
41
|
+
}
|
|
42
|
+
resultsConnection(
|
|
43
|
+
first: $first
|
|
44
|
+
last: $last
|
|
45
|
+
before: $before
|
|
46
|
+
after: $after
|
|
47
|
+
) {
|
|
48
|
+
totalCount
|
|
49
|
+
page {
|
|
36
50
|
id
|
|
37
51
|
date
|
|
38
52
|
details
|
|
@@ -43,8 +57,22 @@ export const IMPLEMENTATION_RESULTS_QUERY = gql`
|
|
|
43
57
|
records
|
|
44
58
|
result
|
|
45
59
|
resultType
|
|
60
|
+
implementation {
|
|
61
|
+
id
|
|
62
|
+
version
|
|
63
|
+
}
|
|
64
|
+
__typename
|
|
65
|
+
}
|
|
66
|
+
pageInfo {
|
|
67
|
+
startCursor
|
|
68
|
+
endCursor
|
|
69
|
+
hasNextPage
|
|
70
|
+
hasPreviousPage
|
|
71
|
+
__typename
|
|
46
72
|
}
|
|
73
|
+
__typename
|
|
47
74
|
}
|
|
75
|
+
__typename
|
|
48
76
|
}
|
|
49
77
|
}
|
|
50
78
|
`;
|
|
@@ -9,26 +9,31 @@ import { linkTo } from "@truedat/core/routes";
|
|
|
9
9
|
|
|
10
10
|
const concatValues = (values, link) => _.join(link)(values);
|
|
11
11
|
|
|
12
|
-
const LinkToStructure = ({ value }) =>
|
|
12
|
+
const LinkToStructure = ({ value, aliasArray }) =>
|
|
13
13
|
value?.id ? (
|
|
14
14
|
<Link to={linkTo.STRUCTURE({ id: value.id })}>
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
<div className="highlighted">
|
|
16
|
+
{qualifySqlIdentifier({ aliasArray, value })}
|
|
17
|
+
</div>{" "}
|
|
18
18
|
</Link>
|
|
19
19
|
) : (
|
|
20
20
|
<span>{value.name}</span>
|
|
21
21
|
);
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
LinkToStructure.propTypes = {
|
|
24
|
+
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
25
|
+
aliasArray: PropTypes.array,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const FormattedLink = ({ value, aliasArray, operator = {} }) => {
|
|
24
29
|
switch (operator?.value_type) {
|
|
25
30
|
case "field":
|
|
26
|
-
return <LinkToStructure value={value} />;
|
|
31
|
+
return <LinkToStructure value={value} aliasArray={aliasArray} />;
|
|
27
32
|
case "field_list":
|
|
28
33
|
return (
|
|
29
34
|
<>
|
|
30
35
|
{_.map.convert({ cap: false })((v, i) => (
|
|
31
|
-
<LinkToStructure key={i} value={v} />
|
|
36
|
+
<LinkToStructure key={i} value={v} aliasArray={aliasArray} />
|
|
32
37
|
))(value)}
|
|
33
38
|
</>
|
|
34
39
|
);
|
|
@@ -49,6 +54,7 @@ const FormattedLink = ({ value, operator = {} }) => {
|
|
|
49
54
|
FormattedLink.propTypes = {
|
|
50
55
|
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
|
51
56
|
operator: PropTypes.object,
|
|
57
|
+
aliasArray: PropTypes.array,
|
|
52
58
|
};
|
|
53
59
|
|
|
54
60
|
const nilOrEmpty = (v) => _.isNil(v) || v === "";
|
|
@@ -101,7 +107,7 @@ export const getValues = ({ value = [], operator = {}, value_modifier }) => {
|
|
|
101
107
|
? valuesFromKeys(
|
|
102
108
|
defaultOrValue,
|
|
103
109
|
["name"],
|
|
104
|
-
["path", "id", "type", "parent_index"],
|
|
110
|
+
["path", "metadata", "id", "type", "parent_index"],
|
|
105
111
|
value_modifier
|
|
106
112
|
)
|
|
107
113
|
: valuesFromKeys(defaultOrValue, ["raw"], [], value_modifier);
|
|
@@ -124,12 +130,15 @@ OperatorMessage.propTypes = {
|
|
|
124
130
|
operator: PropTypes.object,
|
|
125
131
|
};
|
|
126
132
|
|
|
133
|
+
const qualifySqlIdentifier = ({ aliasArray, value }) =>
|
|
134
|
+
_.flow(
|
|
135
|
+
_.find({ index: value?.parent_index }),
|
|
136
|
+
_.propOr(null, "text"),
|
|
137
|
+
_.defaultTo(value?.metadata?.table || _.last(value?.path)),
|
|
138
|
+
(qualifier) => (qualifier ? `(${qualifier}).${value?.name}` : value?.name)
|
|
139
|
+
)(aliasArray);
|
|
140
|
+
|
|
127
141
|
const ConditionCell = ({ row, alias, validationPopulationCondition }) => {
|
|
128
|
-
const alias_text =
|
|
129
|
-
_.flow(
|
|
130
|
-
_.find({ index: row.structure?.parent_index }),
|
|
131
|
-
_.propOr(null, "text")
|
|
132
|
-
)(alias) || (row.structure ? _.last(row.structure.path) : null);
|
|
133
142
|
const values = getValues(row);
|
|
134
143
|
const operator = _.prop("operator")(row);
|
|
135
144
|
const { formatMessage } = useIntl();
|
|
@@ -154,8 +163,10 @@ const ConditionCell = ({ row, alias, validationPopulationCondition }) => {
|
|
|
154
163
|
})}
|
|
155
164
|
>
|
|
156
165
|
<span className="highlighted">
|
|
157
|
-
{
|
|
158
|
-
|
|
166
|
+
{qualifySqlIdentifier({
|
|
167
|
+
aliasArray: alias,
|
|
168
|
+
value: row.structure,
|
|
169
|
+
})}
|
|
159
170
|
</span>
|
|
160
171
|
</Link>
|
|
161
172
|
</>
|
|
@@ -190,8 +201,10 @@ const ConditionCell = ({ row, alias, validationPopulationCondition }) => {
|
|
|
190
201
|
})}
|
|
191
202
|
>
|
|
192
203
|
<span className="highlighted">
|
|
193
|
-
{
|
|
194
|
-
|
|
204
|
+
{qualifySqlIdentifier({
|
|
205
|
+
aliasArray: alias,
|
|
206
|
+
value: row,
|
|
207
|
+
})}
|
|
195
208
|
</span>
|
|
196
209
|
</Link>
|
|
197
210
|
) : (
|
|
@@ -214,7 +227,11 @@ const ConditionCell = ({ row, alias, validationPopulationCondition }) => {
|
|
|
214
227
|
<Table.Cell width={5}>
|
|
215
228
|
{_.map.convert({ cap: false })((value, i) => (
|
|
216
229
|
<Fragment key={i}>
|
|
217
|
-
<FormattedLink
|
|
230
|
+
<FormattedLink
|
|
231
|
+
value={value}
|
|
232
|
+
operator={operator}
|
|
233
|
+
aliasArray={alias}
|
|
234
|
+
/>
|
|
218
235
|
{i + 1 < _.size(values) && (
|
|
219
236
|
<span>
|
|
220
237
|
{" "}
|
|
@@ -58,33 +58,36 @@ ExecutionRow.propTypes = {
|
|
|
58
58
|
implementation: PropTypes.object,
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
export const ImplementationExecutions = (
|
|
62
|
-
|
|
63
|
-
<Table
|
|
64
|
-
<Table.
|
|
65
|
-
<Table.
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
61
|
+
export const ImplementationExecutions = (connection) => (
|
|
62
|
+
<>
|
|
63
|
+
<Table basic="very">
|
|
64
|
+
<Table.Header>
|
|
65
|
+
<Table.Row>
|
|
66
|
+
<Table.HeaderCell width="1" textAlign="right">
|
|
67
|
+
<FormattedMessage id="ruleImplementations.props.version" />
|
|
68
|
+
</Table.HeaderCell>
|
|
69
|
+
<Table.HeaderCell width="2">
|
|
70
|
+
<FormattedMessage id="execution" />
|
|
71
|
+
</Table.HeaderCell>
|
|
72
|
+
<Table.HeaderCell width="2">
|
|
73
|
+
<FormattedMessage id="execution.latestEvent.insertedAt" />
|
|
74
|
+
</Table.HeaderCell>
|
|
75
|
+
<Table.HeaderCell width="2">
|
|
76
|
+
<FormattedMessage id="execution.latestEvent.type" />
|
|
77
|
+
</Table.HeaderCell>
|
|
78
|
+
<Table.HeaderCell>
|
|
79
|
+
<FormattedMessage id="execution.latestEvent.message" />
|
|
80
|
+
</Table.HeaderCell>
|
|
81
|
+
</Table.Row>
|
|
82
|
+
</Table.Header>
|
|
83
|
+
<Table.Body>
|
|
84
|
+
{connection.page.map((props, key) => (
|
|
85
|
+
<ExecutionRow key={key} {...props} />
|
|
86
|
+
))}
|
|
87
|
+
</Table.Body>
|
|
88
|
+
</Table>
|
|
89
|
+
<CursorPagination {...connection} />
|
|
90
|
+
</>
|
|
88
91
|
);
|
|
89
92
|
|
|
90
93
|
ImplementationExecutions.propTypes = {
|
|
@@ -111,9 +114,6 @@ export const ImplementationExecutionsLoader = () => {
|
|
|
111
114
|
<Grid.Column>
|
|
112
115
|
<ImplementationExecutionFilters />
|
|
113
116
|
</Grid.Column>
|
|
114
|
-
<Grid.Column textAlign="right">
|
|
115
|
-
<CursorPagination {...connection} />
|
|
116
|
-
</Grid.Column>
|
|
117
117
|
</Grid.Row>
|
|
118
118
|
</Grid>
|
|
119
119
|
{loading ? <Loading /> : null}
|
|
@@ -4,29 +4,28 @@ import { useParams } from "react-router-dom";
|
|
|
4
4
|
import { useQuery } from "@apollo/client";
|
|
5
5
|
import PropTypes from "prop-types";
|
|
6
6
|
import { useIntl } from "react-intl";
|
|
7
|
-
import { Message, Divider } from "semantic-ui-react";
|
|
7
|
+
import { Segment, Message, Divider } from "semantic-ui-react";
|
|
8
8
|
import { columnDecorator } from "@truedat/core/services";
|
|
9
9
|
import { DateTime, Loading } from "@truedat/core/components";
|
|
10
|
-
import {
|
|
10
|
+
import { CursorPagination } from "@truedat/core/components";
|
|
11
|
+
import { useLocation } from "react-router-dom";
|
|
12
|
+
import queryString from "query-string";
|
|
13
|
+
import { IMPLEMENTATION_RESULTS_CONNECTION_QUERY } from "../api/queries";
|
|
11
14
|
import RuleResultsTable from "./RuleResultsTable";
|
|
12
15
|
|
|
16
|
+
export const PAGE_SIZE = 20;
|
|
17
|
+
|
|
13
18
|
export const getCustomColumnsWithData = (ruleResults, columns) =>
|
|
14
19
|
_.filter((column) =>
|
|
15
20
|
_.any(_.flow(columnDecorator(column), _.negate(_.isEmpty)))(ruleResults)
|
|
16
21
|
)(columns);
|
|
17
22
|
|
|
18
|
-
export const RuleImplementationResults = ({
|
|
23
|
+
export const RuleImplementationResults = ({ implementation, results }) => {
|
|
19
24
|
const { formatMessage, locale } = useIntl();
|
|
20
25
|
|
|
21
|
-
if (_.isEmpty(
|
|
22
|
-
|
|
23
|
-
const implementationVersions = _.propOr([], "versions")(ruleImplementation);
|
|
24
|
-
const currentImplementationVersion = _.flow(
|
|
25
|
-
_.filter((version) => version.id === ruleImplementation.id),
|
|
26
|
-
_.first
|
|
27
|
-
)(implementationVersions);
|
|
26
|
+
if (_.isEmpty(implementation)) return null;
|
|
28
27
|
|
|
29
|
-
const { lastQualityEvent } =
|
|
28
|
+
const { lastQualityEvent } = implementation;
|
|
30
29
|
|
|
31
30
|
return (
|
|
32
31
|
<>
|
|
@@ -46,31 +45,45 @@ export const RuleImplementationResults = ({ ruleImplementation }) => {
|
|
|
46
45
|
<p style={{ whiteSpace: "pre-wrap" }}>{lastQualityEvent.message}</p>
|
|
47
46
|
</Message>
|
|
48
47
|
) : null}
|
|
49
|
-
<RuleResultsTable
|
|
50
|
-
currentImplementationVersion={currentImplementationVersion}
|
|
51
|
-
implementationVersions={implementationVersions}
|
|
52
|
-
/>
|
|
48
|
+
<RuleResultsTable implementation={implementation} results={results} />
|
|
53
49
|
</>
|
|
54
50
|
);
|
|
55
51
|
};
|
|
56
52
|
|
|
57
53
|
RuleImplementationResults.propTypes = {
|
|
58
|
-
|
|
54
|
+
results: PropTypes.array,
|
|
55
|
+
implementation: PropTypes.object,
|
|
59
56
|
};
|
|
60
57
|
|
|
61
58
|
export const RuleImplementationResultsLoader = (props) => {
|
|
62
59
|
const { implementation_id: id } = useParams();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
});
|
|
60
|
+
|
|
61
|
+
const { search } = useLocation();
|
|
62
|
+
const { before, after } = queryString.parse(search);
|
|
63
|
+
const variables = after
|
|
64
|
+
? { id, after, before, first: PAGE_SIZE }
|
|
65
|
+
: { id, after, before, last: PAGE_SIZE };
|
|
66
|
+
|
|
67
|
+
const { loading, error, data } = useQuery(
|
|
68
|
+
IMPLEMENTATION_RESULTS_CONNECTION_QUERY,
|
|
69
|
+
{
|
|
70
|
+
variables,
|
|
71
|
+
}
|
|
72
|
+
);
|
|
66
73
|
if (error) return null;
|
|
67
74
|
if (loading) return <Loading />;
|
|
68
|
-
const
|
|
75
|
+
const implementation = data?.implementation;
|
|
76
|
+
const connection = data?.implementation?.resultsConnection;
|
|
77
|
+
const results = implementation?.resultsConnection?.page;
|
|
69
78
|
return (
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
<Segment attached="bottom">
|
|
80
|
+
<RuleImplementationResults
|
|
81
|
+
implementation={implementation}
|
|
82
|
+
results={results}
|
|
83
|
+
{...props}
|
|
84
|
+
/>
|
|
85
|
+
<CursorPagination {...connection} />
|
|
86
|
+
</Segment>
|
|
74
87
|
);
|
|
75
88
|
};
|
|
76
89
|
|
|
@@ -79,7 +79,10 @@ export const RuleResultRow = ({
|
|
|
79
79
|
<>
|
|
80
80
|
<Icon
|
|
81
81
|
name="circle"
|
|
82
|
-
color={selectColor({
|
|
82
|
+
color={selectColor({
|
|
83
|
+
...ruleImplementation,
|
|
84
|
+
...ruleResult,
|
|
85
|
+
})}
|
|
83
86
|
/>
|
|
84
87
|
{`${parseFloat(ruleResult.result)} %`}
|
|
85
88
|
</>
|
|
@@ -21,22 +21,14 @@ export const getCustomColumnsWithData = (ruleResults, columns) =>
|
|
|
21
21
|
_.any(_.flow(columnDecorator(column), _.negate(_.isEmpty)))(ruleResults)
|
|
22
22
|
)(columns);
|
|
23
23
|
|
|
24
|
-
export const RuleResultsTable = ({
|
|
25
|
-
columns,
|
|
26
|
-
implementationVersions,
|
|
27
|
-
currentImplementationVersion,
|
|
28
|
-
}) => {
|
|
24
|
+
export const RuleResultsTable = ({ columns, implementation, results }) => {
|
|
29
25
|
const isAdmin = useAuthorized();
|
|
30
26
|
const { formatMessage } = useIntl();
|
|
31
27
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
_.flatten
|
|
35
|
-
)(implementationVersions);
|
|
36
|
-
const optionalColumns = getOptionalColumnsWithData(ruleResults);
|
|
37
|
-
const customColumns = getCustomColumnsWithData(ruleResults, columns);
|
|
28
|
+
const optionalColumns = getOptionalColumnsWithData(results);
|
|
29
|
+
const customColumns = getCustomColumnsWithData(results, columns);
|
|
38
30
|
|
|
39
|
-
return _.isEmpty(
|
|
31
|
+
return _.isEmpty(results) ? (
|
|
40
32
|
<Message
|
|
41
33
|
style={{ marginTop: "14px" }}
|
|
42
34
|
header={formatMessage({
|
|
@@ -77,28 +69,43 @@ export const RuleResultsTable = ({
|
|
|
77
69
|
</Table.Row>
|
|
78
70
|
</Table.Header>
|
|
79
71
|
<Table.Body>
|
|
80
|
-
{
|
|
81
|
-
_.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
{_.flow(
|
|
73
|
+
_.groupBy("implementation.version"),
|
|
74
|
+
_.toPairs, // first element: version number; second element: version results.
|
|
75
|
+
// order by descending version number
|
|
76
|
+
_.orderBy(
|
|
77
|
+
(versionAndResultsTuple) => versionAndResultsTuple[0],
|
|
78
|
+
"desc"
|
|
79
|
+
),
|
|
80
|
+
_.mapValues((versionAndResultsTuple) =>
|
|
81
|
+
versionAndResultsTuple[1].map(
|
|
82
|
+
(result, indexWithinVersionGroup) => ({
|
|
83
|
+
indexWithinVersionGroup,
|
|
84
|
+
...result,
|
|
85
|
+
})
|
|
86
|
+
)
|
|
87
|
+
),
|
|
88
|
+
_.reduce((acc, versionResults) => [...acc, ...versionResults], []),
|
|
89
|
+
_.map((result) => (
|
|
85
90
|
<RuleResultRow
|
|
86
|
-
key={
|
|
91
|
+
key={result.id}
|
|
87
92
|
optionalColumns={optionalColumns}
|
|
88
93
|
ruleResult={result}
|
|
89
94
|
customColumns={customColumns}
|
|
90
|
-
ruleImplementation={
|
|
91
|
-
|
|
95
|
+
ruleImplementation={_.find(
|
|
96
|
+
(version) => version?.id === result?.implementation?.id
|
|
97
|
+
)(implementation?.versions)}
|
|
98
|
+
active={implementation.version === result.implementation.version}
|
|
92
99
|
tagLabel={
|
|
93
|
-
|
|
100
|
+
result.indexWithinVersionGroup === 0
|
|
94
101
|
? `${formatMessage({
|
|
95
102
|
id: "ruleImplementations.props.version",
|
|
96
|
-
})}: ${
|
|
103
|
+
})}: ${result.implementation.version}`
|
|
97
104
|
: null
|
|
98
105
|
}
|
|
99
106
|
/>
|
|
100
107
|
))
|
|
101
|
-
)}
|
|
108
|
+
)(results)}
|
|
102
109
|
</Table.Body>
|
|
103
110
|
</Table>
|
|
104
111
|
);
|
|
@@ -106,8 +113,8 @@ export const RuleResultsTable = ({
|
|
|
106
113
|
|
|
107
114
|
RuleResultsTable.propTypes = {
|
|
108
115
|
columns: PropTypes.array,
|
|
109
|
-
|
|
110
|
-
|
|
116
|
+
implementation: PropTypes.object,
|
|
117
|
+
results: PropTypes.array,
|
|
111
118
|
};
|
|
112
119
|
|
|
113
120
|
const mapStateToProps = (state) => ({
|
|
@@ -266,6 +266,18 @@ describe("<NewRuleImplementation> NewRuleImplementation doSubmit", () => {
|
|
|
266
266
|
fields: [
|
|
267
267
|
{
|
|
268
268
|
id: 11127109,
|
|
269
|
+
metadata: {
|
|
270
|
+
data_type_class: "string",
|
|
271
|
+
database: "xe",
|
|
272
|
+
default: "None",
|
|
273
|
+
host: "localhost",
|
|
274
|
+
nullable: false,
|
|
275
|
+
order: "4",
|
|
276
|
+
precision: "25",
|
|
277
|
+
schema: "HR",
|
|
278
|
+
table: "EMPLOYEES",
|
|
279
|
+
type: "VARCHAR2",
|
|
280
|
+
},
|
|
269
281
|
name: "EMAIL",
|
|
270
282
|
parent_index: 4,
|
|
271
283
|
path: undefined,
|
|
@@ -273,6 +285,18 @@ describe("<NewRuleImplementation> NewRuleImplementation doSubmit", () => {
|
|
|
273
285
|
},
|
|
274
286
|
{
|
|
275
287
|
id: 11127116,
|
|
288
|
+
metadata: {
|
|
289
|
+
data_type_class: "string",
|
|
290
|
+
database: "xe",
|
|
291
|
+
default: "None",
|
|
292
|
+
host: "localhost",
|
|
293
|
+
nullable: true,
|
|
294
|
+
order: "5",
|
|
295
|
+
precision: "20",
|
|
296
|
+
schema: "HR",
|
|
297
|
+
table: "EMPLOYEES",
|
|
298
|
+
type: "VARCHAR2",
|
|
299
|
+
},
|
|
276
300
|
name: "PHONE_NUMBER",
|
|
277
301
|
parent_index: 4,
|
|
278
302
|
path: undefined,
|
|
@@ -1,78 +1,31 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { render } from "@truedat/test/render";
|
|
4
|
-
import {
|
|
5
|
-
RuleImplementationResults,
|
|
4
|
+
import RuleImplementationResults, {
|
|
6
5
|
getCustomColumnsWithData,
|
|
6
|
+
PAGE_SIZE,
|
|
7
7
|
} from "../RuleImplementationResults";
|
|
8
8
|
|
|
9
|
+
import { implementationResultsMock } from "./__fixtures__/implementationResultsMocks";
|
|
10
|
+
|
|
11
|
+
jest.mock("react-router-dom", () => ({
|
|
12
|
+
...jest.requireActual("react-router-dom"),
|
|
13
|
+
useParams: () => ({ implementation_id: "2" }),
|
|
14
|
+
}));
|
|
15
|
+
|
|
9
16
|
describe("<RuleImplementationResults />", () => {
|
|
10
|
-
const
|
|
11
|
-
id:
|
|
12
|
-
implementation_key: "default_key",
|
|
13
|
-
versions: [
|
|
14
|
-
{
|
|
15
|
-
implementation_key: "default_key",
|
|
16
|
-
id: 1,
|
|
17
|
-
goal: "20.0",
|
|
18
|
-
minimum: "10.0",
|
|
19
|
-
results: [
|
|
20
|
-
{
|
|
21
|
-
errors: 2,
|
|
22
|
-
hasRemediation: false,
|
|
23
|
-
hasSegments: true,
|
|
24
|
-
id: "66577",
|
|
25
|
-
records: 31,
|
|
26
|
-
result: "93.54",
|
|
27
|
-
resultType: "percentage",
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
errors: 2,
|
|
31
|
-
hasRemediation: false,
|
|
32
|
-
hasSegments: true,
|
|
33
|
-
id: "66578",
|
|
34
|
-
records: 31,
|
|
35
|
-
result: "93.54",
|
|
36
|
-
resultType: "percentage",
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
implementation_key: "key_2",
|
|
42
|
-
id: 2,
|
|
43
|
-
goal: "20.0",
|
|
44
|
-
minimum: "10.0",
|
|
45
|
-
results: [
|
|
46
|
-
{
|
|
47
|
-
errors: 2,
|
|
48
|
-
hasRemediation: false,
|
|
49
|
-
hasSegments: true,
|
|
50
|
-
id: "66579",
|
|
51
|
-
records: 31,
|
|
52
|
-
result: "93.54",
|
|
53
|
-
resultType: "percentage",
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
errors: 2,
|
|
57
|
-
hasRemediation: false,
|
|
58
|
-
hasSegments: true,
|
|
59
|
-
id: "66580",
|
|
60
|
-
records: 31,
|
|
61
|
-
result: "93.54",
|
|
62
|
-
resultType: "percentage",
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
},
|
|
66
|
-
],
|
|
17
|
+
const renderOpts = {
|
|
18
|
+
mocks: [implementationResultsMock({ id: "2", last: PAGE_SIZE })],
|
|
67
19
|
};
|
|
20
|
+
|
|
68
21
|
const ruleResultsColumns = [{ foo: "bar", name: "foo" }];
|
|
69
|
-
const props = {
|
|
70
|
-
ruleImplementation,
|
|
71
|
-
ruleResultsColumns,
|
|
72
|
-
};
|
|
73
22
|
|
|
74
|
-
it("matches the latest snapshot", () => {
|
|
75
|
-
const { container } = render(
|
|
23
|
+
it("matches the latest snapshot", async () => {
|
|
24
|
+
const { container, findByRole } = render(
|
|
25
|
+
<RuleImplementationResults />,
|
|
26
|
+
renderOpts
|
|
27
|
+
);
|
|
28
|
+
expect(await findByRole("table")).toBeInTheDocument();
|
|
76
29
|
expect(container).toMatchSnapshot();
|
|
77
30
|
});
|
|
78
31
|
});
|