@truedat/dq 4.53.8 → 4.53.10
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 +7 -1
- package/package.json +6 -6
- package/src/api/queries.js +76 -16
- package/src/components/ExecutionGroups.js +4 -50
- package/src/components/ImplementationExecutionFilters.js +79 -0
- package/src/components/ImplementationExecutions.js +125 -0
- package/src/components/ImplementationsRoutes.js +18 -1
- package/src/components/RuleImplementationHistory.js +5 -8
- package/src/components/RuleImplementationHistoryRow.js +23 -28
- package/src/components/RuleImplementationResultTabs.js +2 -2
- package/src/components/RuleImplementationResults.js +24 -149
- package/src/components/RuleImplementationSelectedFilters.js +2 -1
- package/src/components/RuleImplementationTabs.js +14 -8
- package/src/components/RuleResultDecorator.js +10 -9
- package/src/components/RuleResultRow.js +9 -15
- package/src/components/RuleResultsRoutes.js +2 -2
- package/src/components/RuleResultsTable.js +117 -0
- package/src/components/__tests__/ImplementationExecutionFilters.spec.js +24 -0
- package/src/components/__tests__/ImplementationExecutions.spec.js +32 -0
- package/src/components/__tests__/RuleImplementationResults.spec.js +16 -45
- package/src/components/__tests__/RuleImplementationTabs.spec.js +1 -18
- package/src/components/__tests__/RuleResultDecorator.spec.js +12 -32
- package/src/components/__tests__/RuleResultDetails.spec.js +3 -3
- package/src/components/__tests__/RuleResultRemediations.spec.js +3 -3
- package/src/components/__tests__/RuleResultRoutes.spec.js +5 -5
- package/src/components/__tests__/RuleResultRow.spec.js +86 -82
- package/src/components/__tests__/RuleResultSegmentRow.spec.js +6 -6
- package/src/components/__tests__/RuleResultSegments.spec.js +1 -1
- package/src/components/__tests__/__fixtures__/executionMocks.js +80 -0
- package/src/components/__tests__/__snapshots__/ExecutionGroups.spec.js.snap +0 -1
- package/src/components/__tests__/__snapshots__/ImplementationExecutionFilters.spec.js.snap +37 -0
- package/src/components/__tests__/__snapshots__/ImplementationExecutions.spec.js.snap +194 -0
- package/src/components/__tests__/__snapshots__/RuleImplementation.spec.js.snap +6 -0
- package/src/components/__tests__/__snapshots__/RuleImplementationHistory.spec.js.snap +12 -24
- package/src/components/__tests__/__snapshots__/RuleImplementationResults.spec.js.snap +8 -8
- package/src/components/__tests__/__snapshots__/RuleImplementationTabs.spec.js.snap +12 -6
- package/src/components/__tests__/__snapshots__/RuleResultDecorator.spec.js.snap +4 -4
- package/src/functions/selectors.js +12 -4
- package/src/messages/en.js +6 -0
- package/src/messages/es.js +6 -0
- package/src/selectors/getRuleImplementationColumns.js +4 -2
- package/src/selectors/index.js +1 -1
- package/src/selectors/{getRuleResultsColumns.js → ruleResultsColumnsSelector.js} +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.53.10] 2022-10-17
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- [TD-4177] Implementation executions components
|
|
8
|
+
|
|
3
9
|
## [4.53.8] 2022-10-17
|
|
4
10
|
|
|
5
11
|
### Added
|
|
@@ -23,7 +29,7 @@
|
|
|
23
29
|
|
|
24
30
|
### Fixed
|
|
25
31
|
|
|
26
|
-
- [TD-5098] Missing value modifier parameter translations
|
|
32
|
+
- [TD-5098] Missing value modifier parameter translations
|
|
27
33
|
|
|
28
34
|
## [4.53.2] 2022-10-07
|
|
29
35
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.53.
|
|
3
|
+
"version": "4.53.10",
|
|
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.53.
|
|
37
|
+
"@truedat/test": "4.53.10",
|
|
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",
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
]
|
|
93
93
|
},
|
|
94
94
|
"dependencies": {
|
|
95
|
-
"@apollo/client": "^3.
|
|
96
|
-
"@truedat/core": "4.53.
|
|
97
|
-
"@truedat/df": "4.53.
|
|
95
|
+
"@apollo/client": "^3.7.0",
|
|
96
|
+
"@truedat/core": "4.53.10",
|
|
97
|
+
"@truedat/df": "4.53.10",
|
|
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": "66304ff9ac3d25820b3bec2d0147f21cb0a2c579"
|
|
118
118
|
}
|
package/src/api/queries.js
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
import { gql } from "@apollo/client";
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
query
|
|
3
|
+
export const IMPLEMENTATION_VERSIONS_QUERY = gql`
|
|
4
|
+
query ImplementationVersions($id: ID!) {
|
|
5
5
|
implementation(id: $id) {
|
|
6
6
|
id
|
|
7
7
|
versions {
|
|
8
8
|
id
|
|
9
|
-
|
|
9
|
+
implementationKey
|
|
10
10
|
version
|
|
11
11
|
status
|
|
12
|
-
|
|
12
|
+
updatedAt
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
`;
|
|
17
17
|
|
|
18
|
-
export const
|
|
18
|
+
export const IMPLEMENTATION_RESULTS_QUERY = gql`
|
|
19
19
|
query Implementation($id: ID!) {
|
|
20
20
|
implementation(id: $id) {
|
|
21
21
|
id
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
implementationKey
|
|
23
|
+
lastQualityEvent {
|
|
24
|
+
insertedAt
|
|
25
25
|
message
|
|
26
26
|
type
|
|
27
27
|
}
|
|
28
28
|
versions {
|
|
29
29
|
id
|
|
30
|
-
|
|
30
|
+
implementationKey
|
|
31
31
|
version
|
|
32
32
|
status
|
|
33
33
|
minimum
|
|
@@ -37,19 +37,19 @@ export const IMPLEMENTATION_RESULTS = gql`
|
|
|
37
37
|
date
|
|
38
38
|
details
|
|
39
39
|
errors
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
hasRemediation
|
|
41
|
+
hasSegments
|
|
42
42
|
params
|
|
43
43
|
records
|
|
44
44
|
result
|
|
45
|
-
|
|
45
|
+
resultType
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
`;
|
|
51
51
|
|
|
52
|
-
export const
|
|
52
|
+
export const IMPLEMENTATION_RESULT_QUERY = gql`
|
|
53
53
|
query ImplementationResult($id: ID!) {
|
|
54
54
|
implementationResult(id: $id) {
|
|
55
55
|
id
|
|
@@ -59,9 +59,9 @@ export const IMPLEMENTATION_RESULT = gql`
|
|
|
59
59
|
errors
|
|
60
60
|
records
|
|
61
61
|
result
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
resultType
|
|
63
|
+
hasSegments
|
|
64
|
+
hasRemediation
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
`;
|
|
@@ -98,3 +98,63 @@ export const MY_EXECUTION_GROUPS_QUERY = gql`
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
`;
|
|
101
|
+
|
|
102
|
+
export const IMPLEMENTATION_EXECUTION_FILTERS_QUERY = gql`
|
|
103
|
+
query ImplementationExecutionFilters($id: ID!) {
|
|
104
|
+
implementation(id: $id) {
|
|
105
|
+
id
|
|
106
|
+
executionFilters {
|
|
107
|
+
field
|
|
108
|
+
values
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
|
|
114
|
+
export const IMPLEMENTATION_EXECUTIONS_QUERY = gql`
|
|
115
|
+
query ImplementationExecutions(
|
|
116
|
+
$id: ID!
|
|
117
|
+
$after: Cursor
|
|
118
|
+
$before: Cursor
|
|
119
|
+
$last: Int
|
|
120
|
+
$first: Int
|
|
121
|
+
$filters: [ExecutionFilterInput]
|
|
122
|
+
) {
|
|
123
|
+
implementation(id: $id) {
|
|
124
|
+
id
|
|
125
|
+
executionFilters {
|
|
126
|
+
field
|
|
127
|
+
values
|
|
128
|
+
}
|
|
129
|
+
executionsConnection(
|
|
130
|
+
first: $first
|
|
131
|
+
last: $last
|
|
132
|
+
before: $before
|
|
133
|
+
after: $after
|
|
134
|
+
filters: $filters
|
|
135
|
+
) {
|
|
136
|
+
totalCount
|
|
137
|
+
page {
|
|
138
|
+
id
|
|
139
|
+
insertedAt
|
|
140
|
+
implementation {
|
|
141
|
+
id
|
|
142
|
+
version
|
|
143
|
+
}
|
|
144
|
+
latestEvent {
|
|
145
|
+
id
|
|
146
|
+
insertedAt
|
|
147
|
+
type
|
|
148
|
+
message
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
pageInfo {
|
|
152
|
+
startCursor
|
|
153
|
+
endCursor
|
|
154
|
+
hasNextPage
|
|
155
|
+
hasPreviousPage
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
`;
|
|
@@ -1,61 +1,15 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
2
|
import { useQuery } from "@apollo/client";
|
|
4
3
|
import queryString from "query-string";
|
|
5
4
|
import { useIntl } from "react-intl";
|
|
6
|
-
import { useLocation
|
|
7
|
-
import { Header,
|
|
5
|
+
import { useLocation } from "react-router-dom";
|
|
6
|
+
import { Header, Segment } from "semantic-ui-react";
|
|
7
|
+
import { CursorPagination } from "@truedat/core/components";
|
|
8
8
|
import { MY_EXECUTION_GROUPS_QUERY } from "../api/queries";
|
|
9
9
|
import ExecutionGroupsTable from "./ExecutionGroupsTable";
|
|
10
10
|
|
|
11
11
|
const PAGE_SIZE = 20;
|
|
12
12
|
|
|
13
|
-
export const Pagination = ({ pageInfo }) => {
|
|
14
|
-
const { endCursor, startCursor, hasPreviousPage, hasNextPage } =
|
|
15
|
-
pageInfo || {};
|
|
16
|
-
const next =
|
|
17
|
-
hasNextPage && endCursor ? { search: "?after=" + endCursor } : null;
|
|
18
|
-
const prev =
|
|
19
|
-
hasPreviousPage && startCursor
|
|
20
|
-
? { search: "?before=" + startCursor }
|
|
21
|
-
: null;
|
|
22
|
-
return (
|
|
23
|
-
<Menu pagination role="navigation">
|
|
24
|
-
<Menu.Item
|
|
25
|
-
as={next ? Link : null}
|
|
26
|
-
link={!!next}
|
|
27
|
-
content="«"
|
|
28
|
-
disabled={!hasNextPage}
|
|
29
|
-
to={{ search: "" }}
|
|
30
|
-
replace={next ? true : null}
|
|
31
|
-
aria-label="Latest"
|
|
32
|
-
/>
|
|
33
|
-
<Menu.Item
|
|
34
|
-
as={next ? Link : null}
|
|
35
|
-
link={!!next}
|
|
36
|
-
content="⟨"
|
|
37
|
-
disabled={!hasNextPage}
|
|
38
|
-
to={next}
|
|
39
|
-
replace={next ? true : null}
|
|
40
|
-
aria-label="Later"
|
|
41
|
-
/>
|
|
42
|
-
<Menu.Item
|
|
43
|
-
as={prev ? Link : null}
|
|
44
|
-
link={!!prev}
|
|
45
|
-
content="⟩"
|
|
46
|
-
disabled={!hasPreviousPage}
|
|
47
|
-
to={prev}
|
|
48
|
-
replace={prev ? true : null}
|
|
49
|
-
aria-label="Earlier"
|
|
50
|
-
/>
|
|
51
|
-
</Menu>
|
|
52
|
-
);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
Pagination.propTypes = {
|
|
56
|
-
pageInfo: PropTypes.object,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
13
|
export const ExecutionGroups = () => {
|
|
60
14
|
const { formatMessage } = useIntl();
|
|
61
15
|
const { search } = useLocation();
|
|
@@ -71,7 +25,7 @@ export const ExecutionGroups = () => {
|
|
|
71
25
|
return (
|
|
72
26
|
<Segment loading={loading}>
|
|
73
27
|
<Header as="h2" content={formatMessage({ id: "sidemenu.executions" })} />
|
|
74
|
-
<
|
|
28
|
+
<CursorPagination {...connection} />
|
|
75
29
|
{loading ? null : <ExecutionGroupsTable {...connection} />}
|
|
76
30
|
</Segment>
|
|
77
31
|
);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { useQuery } from "@apollo/client";
|
|
5
|
+
import queryString from "query-string";
|
|
6
|
+
import { useIntl } from "react-intl";
|
|
7
|
+
import { useLocation, useParams, Link } from "react-router-dom";
|
|
8
|
+
import { Menu } from "semantic-ui-react";
|
|
9
|
+
import { Loading } from "@truedat/core/components";
|
|
10
|
+
import { IMPLEMENTATION_EXECUTION_FILTERS_QUERY } from "../api/queries";
|
|
11
|
+
|
|
12
|
+
export const ExecutionFilter = ({ field, values, header }) => {
|
|
13
|
+
const { search } = useLocation();
|
|
14
|
+
const { formatMessage } = useIntl();
|
|
15
|
+
const { [field]: value } = queryString.parse(search);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Menu compact secondary pointing>
|
|
19
|
+
{header ? (
|
|
20
|
+
<Menu.Item
|
|
21
|
+
header
|
|
22
|
+
disabled
|
|
23
|
+
name={formatMessage({
|
|
24
|
+
id: `execution.filter.${field}`,
|
|
25
|
+
defaultMessage: _.capitalize(field),
|
|
26
|
+
})}
|
|
27
|
+
/>
|
|
28
|
+
) : null}
|
|
29
|
+
<Menu.Item
|
|
30
|
+
link
|
|
31
|
+
name={formatMessage({
|
|
32
|
+
id: `execution.${field}.all`,
|
|
33
|
+
defaultMessage: "All",
|
|
34
|
+
})}
|
|
35
|
+
value={null}
|
|
36
|
+
active={!value}
|
|
37
|
+
as={Link}
|
|
38
|
+
to={{ search: null }}
|
|
39
|
+
replace
|
|
40
|
+
/>
|
|
41
|
+
{values.map((v, i) => (
|
|
42
|
+
<Menu.Item
|
|
43
|
+
key={i}
|
|
44
|
+
link
|
|
45
|
+
name={formatMessage({
|
|
46
|
+
id: `execution.${field}.${v}`,
|
|
47
|
+
defaultMessage: _.capitalize(v),
|
|
48
|
+
})}
|
|
49
|
+
value={v}
|
|
50
|
+
active={value === v}
|
|
51
|
+
as={Link}
|
|
52
|
+
to={{ search: "?" + queryString.stringify({ [field]: v }) }}
|
|
53
|
+
replace
|
|
54
|
+
/>
|
|
55
|
+
))}
|
|
56
|
+
</Menu>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
ExecutionFilter.propTypes = {
|
|
61
|
+
header: PropTypes.bool,
|
|
62
|
+
field: PropTypes.string,
|
|
63
|
+
values: PropTypes.arrayOf(PropTypes.string),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const ImplementationExecutionFilters = () => {
|
|
67
|
+
const { implementation_id: id } = useParams();
|
|
68
|
+
const variables = { id };
|
|
69
|
+
const { data, error, loading } = useQuery(
|
|
70
|
+
IMPLEMENTATION_EXECUTION_FILTERS_QUERY,
|
|
71
|
+
{ variables }
|
|
72
|
+
);
|
|
73
|
+
if (error) return null;
|
|
74
|
+
if (loading) return <Loading />;
|
|
75
|
+
const filters = data?.implementation?.executionFilters || [];
|
|
76
|
+
return filters.map((props, i) => <ExecutionFilter key={i} {...props} />);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default ImplementationExecutionFilters;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { useQuery } from "@apollo/client";
|
|
5
|
+
import queryString from "query-string";
|
|
6
|
+
import { FormattedMessage } from "react-intl";
|
|
7
|
+
import { useLocation, useParams } from "react-router-dom";
|
|
8
|
+
import { Grid, Segment, Table } from "semantic-ui-react";
|
|
9
|
+
import { CursorPagination, DateTime, Loading } from "@truedat/core/components";
|
|
10
|
+
import { IMPLEMENTATION_EXECUTIONS_QUERY } from "../api/queries";
|
|
11
|
+
import ImplementationExecutionFilters from "./ImplementationExecutionFilters";
|
|
12
|
+
|
|
13
|
+
const PAGE_SIZE = 20;
|
|
14
|
+
|
|
15
|
+
const STYLES = {
|
|
16
|
+
PENDING: { warning: true },
|
|
17
|
+
STARTED: { warning: true },
|
|
18
|
+
SUCCEEDED: { positive: true },
|
|
19
|
+
FAILED: { error: true },
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const ExecutionRow = ({
|
|
23
|
+
id,
|
|
24
|
+
insertedAt,
|
|
25
|
+
latestEvent,
|
|
26
|
+
implementation,
|
|
27
|
+
}) => {
|
|
28
|
+
const status = latestEvent?.type;
|
|
29
|
+
const styles = _.propOr(STYLES.PENDING, latestEvent?.type)(STYLES);
|
|
30
|
+
return (
|
|
31
|
+
<Table.Row key={id} {...styles}>
|
|
32
|
+
<Table.Cell width="1" textAlign="right">
|
|
33
|
+
{implementation?.version}
|
|
34
|
+
</Table.Cell>
|
|
35
|
+
<Table.Cell width="2">
|
|
36
|
+
<DateTime value={insertedAt} />
|
|
37
|
+
</Table.Cell>
|
|
38
|
+
<Table.Cell width="2">
|
|
39
|
+
{latestEvent ? <DateTime value={latestEvent.insertedAt} /> : null}
|
|
40
|
+
</Table.Cell>
|
|
41
|
+
<Table.Cell width="2">
|
|
42
|
+
{status ? (
|
|
43
|
+
<FormattedMessage
|
|
44
|
+
id={`execution.status.${status}`}
|
|
45
|
+
defaultMessage={_.capitalize(status)}
|
|
46
|
+
/>
|
|
47
|
+
) : null}
|
|
48
|
+
</Table.Cell>
|
|
49
|
+
<Table.Cell>{latestEvent?.message}</Table.Cell>
|
|
50
|
+
</Table.Row>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
ExecutionRow.propTypes = {
|
|
55
|
+
id: PropTypes.string,
|
|
56
|
+
insertedAt: PropTypes.string,
|
|
57
|
+
latestEvent: PropTypes.object,
|
|
58
|
+
implementation: PropTypes.object,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const ImplementationExecutions = ({ page }) => (
|
|
62
|
+
<Table basic="very">
|
|
63
|
+
<Table.Header>
|
|
64
|
+
<Table.Row>
|
|
65
|
+
<Table.HeaderCell width="1" textAlign="right">
|
|
66
|
+
<FormattedMessage id="ruleImplementations.props.version" />
|
|
67
|
+
</Table.HeaderCell>
|
|
68
|
+
<Table.HeaderCell width="2">
|
|
69
|
+
<FormattedMessage id="execution" />
|
|
70
|
+
</Table.HeaderCell>
|
|
71
|
+
<Table.HeaderCell width="2">
|
|
72
|
+
<FormattedMessage id="execution.latestEvent.insertedAt" />
|
|
73
|
+
</Table.HeaderCell>
|
|
74
|
+
<Table.HeaderCell width="2">
|
|
75
|
+
<FormattedMessage id="execution.latestEvent.type" />
|
|
76
|
+
</Table.HeaderCell>
|
|
77
|
+
<Table.HeaderCell>
|
|
78
|
+
<FormattedMessage id="execution.latestEvent.message" />
|
|
79
|
+
</Table.HeaderCell>
|
|
80
|
+
</Table.Row>
|
|
81
|
+
</Table.Header>
|
|
82
|
+
<Table.Body>
|
|
83
|
+
{page.map((props, key) => (
|
|
84
|
+
<ExecutionRow key={key} {...props} />
|
|
85
|
+
))}
|
|
86
|
+
</Table.Body>
|
|
87
|
+
</Table>
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
ImplementationExecutions.propTypes = {
|
|
91
|
+
filters: PropTypes.array,
|
|
92
|
+
page: PropTypes.array,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const ImplementationExecutionsLoader = () => {
|
|
96
|
+
const { implementation_id: id } = useParams();
|
|
97
|
+
const { search } = useLocation();
|
|
98
|
+
const { before, after, status } = queryString.parse(search);
|
|
99
|
+
const filters = status ? [{ field: "status", values: [status] }] : [];
|
|
100
|
+
const variables = after
|
|
101
|
+
? { id, after, before, first: PAGE_SIZE, filters }
|
|
102
|
+
: { id, after, before, last: PAGE_SIZE, filters };
|
|
103
|
+
const { data, loading } = useQuery(IMPLEMENTATION_EXECUTIONS_QUERY, {
|
|
104
|
+
variables: _.pickBy(_.identity)(variables),
|
|
105
|
+
});
|
|
106
|
+
const connection = data?.implementation?.executionsConnection;
|
|
107
|
+
return (
|
|
108
|
+
<Segment attached="bottom">
|
|
109
|
+
<Grid>
|
|
110
|
+
<Grid.Row columns={2}>
|
|
111
|
+
<Grid.Column>
|
|
112
|
+
<ImplementationExecutionFilters />
|
|
113
|
+
</Grid.Column>
|
|
114
|
+
<Grid.Column textAlign="right">
|
|
115
|
+
<CursorPagination {...connection} />
|
|
116
|
+
</Grid.Column>
|
|
117
|
+
</Grid.Row>
|
|
118
|
+
</Grid>
|
|
119
|
+
{loading ? <Loading /> : null}
|
|
120
|
+
{connection ? <ImplementationExecutions {...connection} /> : null}
|
|
121
|
+
</Segment>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export default ImplementationExecutionsLoader;
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
IMPLEMENTATION_CONCEPT_LINKS,
|
|
13
13
|
IMPLEMENTATION_EDIT,
|
|
14
14
|
IMPLEMENTATION_EVENTS,
|
|
15
|
+
IMPLEMENTATION_EXECUTIONS,
|
|
15
16
|
IMPLEMENTATION_HISTORY,
|
|
16
17
|
IMPLEMENTATION_MOVE,
|
|
17
18
|
IMPLEMENTATION_NEW,
|
|
@@ -31,6 +32,7 @@ import {
|
|
|
31
32
|
getImplementationStructuresLoaded,
|
|
32
33
|
} from "../selectors";
|
|
33
34
|
import ImplementationCrumbs from "./ImplementationCrumbs";
|
|
35
|
+
import ImplementationExecutions from "./ImplementationExecutions";
|
|
34
36
|
import ImplementationStructures from "./ImplementationStructures";
|
|
35
37
|
import ImplementationStructuresNew from "./ImplementationStructuresNew";
|
|
36
38
|
import Implementations from "./Implementations";
|
|
@@ -143,6 +145,22 @@ export const ImplementationsRoutes = ({
|
|
|
143
145
|
</>
|
|
144
146
|
)}
|
|
145
147
|
/>
|
|
148
|
+
<Route
|
|
149
|
+
exact
|
|
150
|
+
path={IMPLEMENTATION_EXECUTIONS}
|
|
151
|
+
render={() => (
|
|
152
|
+
<>
|
|
153
|
+
<ImplementationCrumbs />
|
|
154
|
+
<Segment>
|
|
155
|
+
{ruleImplementationLoaded ? (
|
|
156
|
+
<RuleImplementation>
|
|
157
|
+
<ImplementationExecutions />
|
|
158
|
+
</RuleImplementation>
|
|
159
|
+
) : null}
|
|
160
|
+
</Segment>
|
|
161
|
+
</>
|
|
162
|
+
)}
|
|
163
|
+
/>
|
|
146
164
|
<Route
|
|
147
165
|
exact
|
|
148
166
|
path={IMPLEMENTATION_CLONE}
|
|
@@ -291,7 +309,6 @@ export const ImplementationsRoutes = ({
|
|
|
291
309
|
</>
|
|
292
310
|
)}
|
|
293
311
|
/>
|
|
294
|
-
|
|
295
312
|
<Route
|
|
296
313
|
exact
|
|
297
314
|
path={IMPLEMENTATION_RESULTS_DETAILS}
|
|
@@ -7,7 +7,7 @@ import { connect } from "react-redux";
|
|
|
7
7
|
import { Segment, Grid, Table } from "semantic-ui-react";
|
|
8
8
|
import { FormattedMessage } from "react-intl";
|
|
9
9
|
import { Loading } from "@truedat/core/components";
|
|
10
|
-
import {
|
|
10
|
+
import { IMPLEMENTATION_VERSIONS_QUERY } from "../api/queries";
|
|
11
11
|
|
|
12
12
|
import RuleImplementationHistoryRow from "./RuleImplementationHistoryRow";
|
|
13
13
|
|
|
@@ -16,7 +16,7 @@ export const RuleImplementationHistory = ({ implementation }) => (
|
|
|
16
16
|
<Grid>
|
|
17
17
|
<Grid.Row>
|
|
18
18
|
<Grid.Column>
|
|
19
|
-
{
|
|
19
|
+
{_.isEmpty(implementation) ? null : (
|
|
20
20
|
<Table selectable>
|
|
21
21
|
<Table.Header>
|
|
22
22
|
<Table.Row>
|
|
@@ -65,12 +65,9 @@ RuleImplementationHistory.propTypes = {
|
|
|
65
65
|
|
|
66
66
|
export const RuleImplementationHistoryLoader = (props) => {
|
|
67
67
|
const { implementation_id: id } = useParams();
|
|
68
|
-
const { loading, error, data } = useQuery(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
variables: { id },
|
|
72
|
-
}
|
|
73
|
-
);
|
|
68
|
+
const { loading, error, data } = useQuery(IMPLEMENTATION_VERSIONS_QUERY, {
|
|
69
|
+
variables: { id },
|
|
70
|
+
});
|
|
74
71
|
if (error) return null;
|
|
75
72
|
if (loading) return <Loading />;
|
|
76
73
|
const implementation = data?.implementation;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import _ from "lodash/fp";
|
|
2
1
|
import React from "react";
|
|
3
2
|
import PropTypes from "prop-types";
|
|
4
|
-
import {
|
|
3
|
+
import { Link } from "react-router-dom";
|
|
5
4
|
import { Table } from "semantic-ui-react";
|
|
6
5
|
import { FormattedMessage } from "react-intl";
|
|
7
6
|
import { DateTime } from "@truedat/core/components";
|
|
@@ -10,39 +9,35 @@ import { linkTo } from "@truedat/core/routes";
|
|
|
10
9
|
export const RuleImplementationHistoryRow = ({
|
|
11
10
|
id,
|
|
12
11
|
status,
|
|
13
|
-
|
|
12
|
+
updatedAt,
|
|
14
13
|
version,
|
|
15
|
-
|
|
14
|
+
implementationKey,
|
|
16
15
|
active,
|
|
17
|
-
}) =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
content={
|
|
29
|
-
<FormattedMessage
|
|
30
|
-
id={`concepts.status.${status}`}
|
|
31
|
-
defaultMessage={status}
|
|
32
|
-
/>
|
|
33
|
-
}
|
|
16
|
+
}) => (
|
|
17
|
+
<Table.Row active={active}>
|
|
18
|
+
<Table.Cell>
|
|
19
|
+
<Link to={linkTo.IMPLEMENTATION_HISTORY({ implementation_id: id })}>
|
|
20
|
+
{implementationKey}
|
|
21
|
+
</Link>
|
|
22
|
+
</Table.Cell>
|
|
23
|
+
<Table.Cell>
|
|
24
|
+
<FormattedMessage
|
|
25
|
+
id={`concepts.status.${status}`}
|
|
26
|
+
defaultMessage={status}
|
|
34
27
|
/>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
</Table.Cell>
|
|
29
|
+
<Table.Cell content={version} />
|
|
30
|
+
<Table.Cell>
|
|
31
|
+
<DateTime value={updatedAt} />
|
|
32
|
+
</Table.Cell>
|
|
33
|
+
</Table.Row>
|
|
34
|
+
);
|
|
40
35
|
|
|
41
36
|
RuleImplementationHistoryRow.propTypes = {
|
|
42
37
|
id: PropTypes.number,
|
|
43
|
-
|
|
38
|
+
implementationKey: PropTypes.string,
|
|
44
39
|
status: PropTypes.string,
|
|
45
|
-
|
|
40
|
+
updatedAt: PropTypes.string,
|
|
46
41
|
version: PropTypes.number,
|
|
47
42
|
active: PropTypes.bool,
|
|
48
43
|
};
|
|
@@ -21,7 +21,7 @@ export const RuleImplementationResultTabs = ({
|
|
|
21
21
|
templates,
|
|
22
22
|
}) => {
|
|
23
23
|
const renderSegmentResult = () => {
|
|
24
|
-
return ruleResult.
|
|
24
|
+
return ruleResult.hasSegments ? (
|
|
25
25
|
<Menu.Item
|
|
26
26
|
active={match.path === IMPLEMENTATION_RESULT_SEGMENTS_RESULTS}
|
|
27
27
|
as={Link}
|
|
@@ -37,7 +37,7 @@ export const RuleImplementationResultTabs = ({
|
|
|
37
37
|
|
|
38
38
|
const renderRemediationPlan = () => {
|
|
39
39
|
const canCreateRemediation = authCreateRemediation && !_.isEmpty(templates);
|
|
40
|
-
const renderCondition = ruleResult.
|
|
40
|
+
const renderCondition = ruleResult.hasRemediation || canCreateRemediation;
|
|
41
41
|
|
|
42
42
|
return renderCondition ? (
|
|
43
43
|
<Menu.Item
|