@truedat/dq 4.33.8 → 4.34.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 +21 -1
- package/package.json +5 -5
- package/src/api.js +5 -1
- package/src/components/ConditionSummary.js +23 -21
- package/src/components/ExecutionDetails.js +11 -14
- package/src/components/ExecutionForm.js +116 -0
- package/src/components/ExecutionGroup.js +24 -15
- package/src/components/ExecutionPopup.js +58 -0
- package/src/components/ImplementationResultBar.js +80 -0
- package/src/components/ImplementationSummary.js +33 -72
- package/src/components/ImplementationsRoutes.js +15 -5
- package/src/components/ImplementationsUploadButton.js +63 -0
- package/src/components/InformationSummary.js +68 -0
- package/src/components/NewRuleImplementation.js +12 -0
- package/src/components/RuleForm.js +0 -178
- package/src/components/RuleImplementation.js +10 -6
- package/src/components/RuleImplementationProperties.js +31 -64
- package/src/components/RuleImplementationResults.js +87 -53
- package/src/components/RuleImplementationsActions.js +18 -48
- package/src/components/RuleProperties.js +1 -10
- package/src/components/RuleResultDecorator.js +43 -26
- package/src/components/RuleResultRow.js +4 -1
- package/src/components/RuleRoutes.js +0 -13
- package/src/components/RuleSummary.js +15 -2
- package/src/components/RulesActions.js +17 -10
- package/src/components/RulesUploadButton.js +58 -0
- package/src/components/__tests__/ExecutionForm.spec.js +25 -0
- package/src/components/__tests__/ExecutionGroup.spec.js +11 -7
- package/src/components/__tests__/ExecutionPopup.spec.js +20 -0
- package/src/components/__tests__/ImplementationResultBar.spec.js +98 -0
- package/src/components/__tests__/ImplementationSummary.spec.js +9 -26
- package/src/components/__tests__/InformationSummary.spec.js +35 -0
- package/src/components/__tests__/NewRuleImplementation.spec.js +1 -1
- package/src/components/__tests__/RuleForm.spec.js +0 -191
- package/src/components/__tests__/RuleImplementation.spec.js +1 -0
- package/src/components/__tests__/RuleImplementationProperties.spec.js +23 -33
- package/src/components/__tests__/RuleImplementationsActions.spec.js +10 -32
- package/src/components/__tests__/RuleProperties.spec.js +7 -9
- package/src/components/__tests__/RuleResultDecorator.spec.js +17 -11
- package/src/components/__tests__/RuleResultRow.spec.js +25 -46
- package/src/components/__tests__/RuleRow.spec.js +0 -4
- package/src/components/__tests__/RuleSummary.spec.js +6 -6
- package/src/components/__tests__/Rules.spec.js +15 -39
- package/src/components/__tests__/__snapshots__/ConditionSummary.spec.js.snap +55 -51
- package/src/components/__tests__/__snapshots__/ExecutionForm.spec.js.snap +33 -0
- package/src/components/__tests__/__snapshots__/ExecutionGroup.spec.js.snap +5 -4
- package/src/components/__tests__/__snapshots__/ExecutionPopup.spec.js.snap +11 -0
- package/src/components/__tests__/__snapshots__/ImplementationResultBar.spec.js.snap +141 -0
- package/src/components/__tests__/__snapshots__/ImplementationSummary.spec.js.snap +194 -457
- package/src/components/__tests__/__snapshots__/InformationSummary.spec.js.snap +185 -0
- package/src/components/__tests__/__snapshots__/NewRuleImplementation.spec.js.snap +6 -0
- package/src/components/__tests__/__snapshots__/RuleForm.spec.js.snap +0 -148
- package/src/components/__tests__/__snapshots__/RuleImplementation.spec.js.snap +20 -0
- package/src/components/__tests__/__snapshots__/RuleImplementationProperties.spec.js.snap +43 -49
- package/src/components/__tests__/__snapshots__/RuleImplementationResults.spec.js.snap +63 -61
- package/src/components/__tests__/__snapshots__/RuleImplementationsActions.spec.js.snap +5 -49
- package/src/components/__tests__/__snapshots__/RuleProperties.spec.js.snap +0 -1
- package/src/components/__tests__/__snapshots__/RuleRow.spec.js.snap +0 -28
- package/src/components/__tests__/__snapshots__/Rules.spec.js.snap +0 -101
- package/src/components/ruleImplementationForm/InformationForm.js +5 -5
- package/src/components/ruleImplementationForm/LimitsForm.js +142 -0
- package/src/components/ruleImplementationForm/RuleImplementationForm.js +14 -4
- package/src/components/ruleImplementationForm/RuleImplementationRawForm.js +16 -6
- package/src/components/ruleImplementationForm/__tests__/LimitsForm.spec.js +186 -0
- package/src/components/ruleImplementationForm/__tests__/RuleImplementationRawForm.spec.js +42 -35
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/LimitsForm.spec.js.snap +1104 -0
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationForm.spec.js.snap +4 -1
- package/src/components/ruleImplementationForm/__tests__/__snapshots__/RuleImplementationRawForm.spec.js.snap +12 -1
- package/src/components/ruleImplementationForm/limitsValidation.js +72 -0
- package/src/messages/en.js +145 -71
- package/src/messages/es.js +270 -180
- package/src/reducers/__tests__/rule.spec.js +2 -4
- package/src/reducers/__tests__/ruleImplementation.spec.js +2 -0
- package/src/reducers/__tests__/ruleImplementations.spec.js +12 -8
- package/src/reducers/dqMessage.js +100 -1
- package/src/reducers/index.js +4 -0
- package/src/reducers/rule.js +0 -3
- package/src/reducers/ruleImplementation.js +3 -0
- package/src/reducers/ruleImplementationRedirect.js +6 -1
- package/src/reducers/ruleImplementations.js +3 -0
- package/src/reducers/ruleRedirect.js +5 -0
- package/src/reducers/uploadImplementationsFile.js +28 -0
- package/src/reducers/uploadRulesFile.js +25 -0
- package/src/routines.js +2 -0
- package/src/sagas/index.js +6 -0
- package/src/sagas/uploadImplementations.js +28 -0
- package/src/sagas/uploadRules.js +28 -0
- package/src/selectors/getRuleImplementationColumns.js +38 -3
- package/src/selectors/ruleColumnsSelector.js +0 -31
- package/src/styles/ruleSummary.less +17 -10
|
@@ -3,19 +3,22 @@ import React from "react";
|
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { FormattedMessage } from "react-intl";
|
|
5
5
|
import { connect } from "react-redux";
|
|
6
|
-
import {
|
|
6
|
+
import { Grid, Label, Segment } from "semantic-ui-react";
|
|
7
|
+
import InformationSummary from "./InformationSummary";
|
|
7
8
|
import ImplementationSummary from "./ImplementationSummary";
|
|
8
9
|
import RawContent from "./RawContent";
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
const DynamicFormViewer = React.lazy(() =>
|
|
12
|
+
import("@truedat/df/components/DynamicFormViewer")
|
|
13
|
+
);
|
|
11
14
|
|
|
12
15
|
const summarySteps = ["dataset", "population", "validations"];
|
|
13
16
|
|
|
14
17
|
export const RuleImplementationProperties = ({
|
|
15
|
-
rule,
|
|
16
18
|
ruleImplementation,
|
|
17
19
|
ruleImplementationRaw,
|
|
18
|
-
|
|
20
|
+
templateImpl,
|
|
21
|
+
ruleImplementationLoaded,
|
|
19
22
|
}) => {
|
|
20
23
|
return _.isEmpty(ruleImplementation) &&
|
|
21
24
|
_.isEmpty(ruleImplementationRaw) ? null : (
|
|
@@ -30,6 +33,18 @@ export const RuleImplementationProperties = ({
|
|
|
30
33
|
</Label>
|
|
31
34
|
</Grid.Column>
|
|
32
35
|
</Grid.Row>
|
|
36
|
+
<Grid.Row>
|
|
37
|
+
<Grid.Column width={10}>
|
|
38
|
+
<InformationSummary ruleImplementation={ruleImplementation} />
|
|
39
|
+
{!_.isEmpty(templateImpl) && ruleImplementationLoaded && (
|
|
40
|
+
<DynamicFormViewer
|
|
41
|
+
boxLayout
|
|
42
|
+
template={templateImpl}
|
|
43
|
+
content={ruleImplementation.df_content}
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
</Grid.Column>
|
|
47
|
+
</Grid.Row>
|
|
33
48
|
<Grid.Column width={10}>
|
|
34
49
|
{_.isEmpty(ruleImplementationRaw) ? (
|
|
35
50
|
<ImplementationSummary
|
|
@@ -41,85 +56,37 @@ export const RuleImplementationProperties = ({
|
|
|
41
56
|
)}
|
|
42
57
|
</Grid.Column>
|
|
43
58
|
</Grid>
|
|
44
|
-
<Header as="h3">
|
|
45
|
-
<FormattedMessage id={`rule.props.result_type.${rule.result_type}`} />
|
|
46
|
-
</Header>
|
|
47
|
-
<List>
|
|
48
|
-
<List.Item>
|
|
49
|
-
<Icon name="circle" color="yellow" />
|
|
50
|
-
<List.Content>
|
|
51
|
-
<List.Description>
|
|
52
|
-
<FormattedMessage id="quality.threshold" />
|
|
53
|
-
{`: ${rule.minimum} ${
|
|
54
|
-
rule.result_type !== "errors_number" ? "%" : ""
|
|
55
|
-
}`}
|
|
56
|
-
</List.Description>
|
|
57
|
-
</List.Content>
|
|
58
|
-
</List.Item>
|
|
59
|
-
<List.Item>
|
|
60
|
-
<Icon name="circle" color="green" />
|
|
61
|
-
<List.Content>
|
|
62
|
-
<List.Description>
|
|
63
|
-
<FormattedMessage id="quality.goal" />
|
|
64
|
-
{`: ${rule.goal} ${
|
|
65
|
-
rule.result_type !== "errors_number" ? "%" : ""
|
|
66
|
-
}`}
|
|
67
|
-
</List.Description>
|
|
68
|
-
</List.Content>
|
|
69
|
-
</List.Item>
|
|
70
|
-
</List>
|
|
71
|
-
<Header as="h3">
|
|
72
|
-
<FormattedMessage id="quality.rule.quality" />
|
|
73
|
-
</Header>
|
|
74
|
-
{ruleResult ? (
|
|
75
|
-
<p>
|
|
76
|
-
<RuleResultDecorator
|
|
77
|
-
ruleResult={ruleResult}
|
|
78
|
-
date={ruleResult?.date}
|
|
79
|
-
rule={rule}
|
|
80
|
-
/>
|
|
81
|
-
</p>
|
|
82
|
-
) : (
|
|
83
|
-
<FormattedMessage id="quality.result.no.data" />
|
|
84
|
-
)}
|
|
85
|
-
{ruleImplementation.event_type !== "FAILED" ? null : (
|
|
86
|
-
<>
|
|
87
|
-
<Header as="h3">
|
|
88
|
-
<Icon name="warning circle" color="red" size="small" />
|
|
89
|
-
<FormattedMessage id="quality.error" />
|
|
90
|
-
</Header>
|
|
91
|
-
<QualityEventError
|
|
92
|
-
inserted_at={ruleImplementation.event_inserted_at}
|
|
93
|
-
message={ruleImplementation.event_message}
|
|
94
|
-
type={ruleImplementation.event_type}
|
|
95
|
-
/>
|
|
96
|
-
</>
|
|
97
|
-
)}
|
|
98
59
|
</Segment>
|
|
99
60
|
);
|
|
100
61
|
};
|
|
101
62
|
RuleImplementationProperties.propTypes = {
|
|
102
|
-
rule: PropTypes.object,
|
|
103
63
|
ruleImplementation: PropTypes.object.isRequired,
|
|
104
64
|
ruleImplementationRaw: PropTypes.object,
|
|
105
|
-
|
|
65
|
+
templateImpl: PropTypes.object,
|
|
66
|
+
ruleImplementationLoaded: PropTypes.bool,
|
|
106
67
|
};
|
|
107
68
|
|
|
108
69
|
const mapStateToProps = ({
|
|
109
|
-
rule,
|
|
110
70
|
ruleImplementation,
|
|
111
71
|
ruleImplementationRaw,
|
|
72
|
+
templates,
|
|
73
|
+
ruleImplementationLoading,
|
|
112
74
|
}) => ({
|
|
113
|
-
rule,
|
|
114
75
|
ruleImplementation: _.pick([
|
|
115
76
|
...summarySteps,
|
|
116
77
|
"executable",
|
|
117
78
|
"event_type",
|
|
118
79
|
"event_message",
|
|
119
80
|
"event_inserted_at",
|
|
81
|
+
"result_type",
|
|
82
|
+
"minimum",
|
|
83
|
+
"goal",
|
|
84
|
+
"df_content",
|
|
120
85
|
])(ruleImplementation),
|
|
121
86
|
ruleImplementationRaw,
|
|
122
|
-
|
|
87
|
+
templateImpl: _.find(_.propEq("name", ruleImplementation.df_name))(templates),
|
|
88
|
+
ruleImplementationLoaded:
|
|
89
|
+
!ruleImplementationLoading && !_.isEmpty(ruleImplementation),
|
|
123
90
|
});
|
|
124
91
|
|
|
125
92
|
export default connect(mapStateToProps)(RuleImplementationProperties);
|
|
@@ -3,8 +3,9 @@ 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 { Table, Message } from "semantic-ui-react";
|
|
6
|
+
import { Table, Message, Divider } from "semantic-ui-react";
|
|
7
7
|
import { columnDecorator } from "@truedat/core/services";
|
|
8
|
+
import Moment from "react-moment";
|
|
8
9
|
import { getRuleResultsColumns } from "../selectors";
|
|
9
10
|
import RuleResultRow from "./RuleResultRow";
|
|
10
11
|
|
|
@@ -25,65 +26,98 @@ export const RuleImplementationResults = ({
|
|
|
25
26
|
customColumns,
|
|
26
27
|
isAdmin,
|
|
27
28
|
}) => {
|
|
28
|
-
const { formatMessage } = useIntl();
|
|
29
|
+
const { formatMessage, locale } = useIntl();
|
|
29
30
|
|
|
30
31
|
if (_.isEmpty(rule) || _.isEmpty(ruleImplementation)) return null;
|
|
31
32
|
|
|
32
33
|
const ruleResults = ruleImplementation.results;
|
|
33
34
|
const optionalColumns = getOptionalColumnsWithData(ruleResults);
|
|
34
35
|
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
{ruleImplementation.event_type === "FAILED" && (
|
|
39
|
+
<Message negative style={{ marginTop: "14px" }}>
|
|
40
|
+
<Message.Header>
|
|
41
|
+
{formatMessage({
|
|
42
|
+
id: "quality.error",
|
|
43
|
+
})}
|
|
44
|
+
</Message.Header>
|
|
45
|
+
<Divider />
|
|
46
|
+
<Moment
|
|
47
|
+
style={{
|
|
48
|
+
position: "absolute",
|
|
49
|
+
top: "14px",
|
|
50
|
+
right: "21px",
|
|
51
|
+
}}
|
|
52
|
+
locale={locale}
|
|
53
|
+
date={ruleImplementation.event_inserted_at}
|
|
54
|
+
format="YYYY-MM-DD HH:mm"
|
|
46
55
|
/>
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
56
|
+
<p
|
|
57
|
+
style={{
|
|
58
|
+
whiteSpace: "pre-wrap",
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
{ruleImplementation.event_message}
|
|
62
|
+
</p>
|
|
63
|
+
</Message>
|
|
64
|
+
)}
|
|
65
|
+
{_.isEmpty(ruleResults) ? (
|
|
66
|
+
<Message
|
|
67
|
+
style={{ marginTop: "14px" }}
|
|
68
|
+
header={formatMessage({
|
|
69
|
+
id: "rule.ruleImplementation.results.empty",
|
|
70
|
+
})}
|
|
71
|
+
/>
|
|
72
|
+
) : (
|
|
73
|
+
<Table className="implementation-results small" selectable>
|
|
74
|
+
<Table.Header>
|
|
75
|
+
<Table.Row>
|
|
76
|
+
<Table.HeaderCell
|
|
77
|
+
content={formatMessage({ id: "ruleResult.props.quality" })}
|
|
78
|
+
/>
|
|
79
|
+
<Table.HeaderCell
|
|
80
|
+
content={formatMessage({ id: "ruleResult.props.date" })}
|
|
81
|
+
/>
|
|
82
|
+
{_.includes("records")(optionalColumns) && (
|
|
83
|
+
<Table.HeaderCell
|
|
84
|
+
content={formatMessage({ id: "ruleResult.props.records" })}
|
|
85
|
+
/>
|
|
86
|
+
)}
|
|
87
|
+
{_.includes("errors")(optionalColumns) && (
|
|
88
|
+
<Table.HeaderCell
|
|
89
|
+
content={formatMessage({ id: "ruleResult.props.errors" })}
|
|
90
|
+
/>
|
|
91
|
+
)}
|
|
92
|
+
{customColumns.map((column, index) => (
|
|
93
|
+
<Table.HeaderCell
|
|
94
|
+
key={index}
|
|
95
|
+
content={formatMessage({
|
|
96
|
+
id: `ruleResult.props.${column.name}`,
|
|
97
|
+
defaultMessage: column.name,
|
|
98
|
+
})}
|
|
99
|
+
/>
|
|
100
|
+
))}
|
|
101
|
+
{<Table.HeaderCell />}
|
|
102
|
+
{isAdmin && <Table.HeaderCell />}
|
|
103
|
+
</Table.Row>
|
|
104
|
+
</Table.Header>
|
|
105
|
+
<Table.Body>
|
|
106
|
+
{ruleResults.map((result, i) => (
|
|
107
|
+
<RuleResultRow
|
|
108
|
+
key={i}
|
|
109
|
+
optionalColumns={optionalColumns}
|
|
110
|
+
ruleResult={result}
|
|
111
|
+
customColumns={customColumns}
|
|
112
|
+
isAdmin={isAdmin}
|
|
113
|
+
ruleImplementation={ruleImplementation}
|
|
114
|
+
rule={rule}
|
|
115
|
+
/>
|
|
116
|
+
))}
|
|
117
|
+
</Table.Body>
|
|
118
|
+
</Table>
|
|
119
|
+
)}
|
|
120
|
+
</>
|
|
87
121
|
);
|
|
88
122
|
};
|
|
89
123
|
|
|
@@ -4,9 +4,7 @@ import PropTypes from "prop-types";
|
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
5
|
import { Button, Checkbox } from "semantic-ui-react";
|
|
6
6
|
import { useIntl } from "react-intl";
|
|
7
|
-
import {
|
|
8
|
-
import { ConfirmModal } from "@truedat/core/components";
|
|
9
|
-
import { downloadImplementations } from "../routines";
|
|
7
|
+
import { downloadImplementations, uploadImplementations } from "../routines";
|
|
10
8
|
import { getImplementationsExecution } from "../selectors";
|
|
11
9
|
import {
|
|
12
10
|
addImplementationFilter,
|
|
@@ -14,6 +12,9 @@ import {
|
|
|
14
12
|
removeImplementationFilter,
|
|
15
13
|
createExecutionGroup,
|
|
16
14
|
} from "../routines";
|
|
15
|
+
import ImplementationsUploadButton from "./ImplementationsUploadButton";
|
|
16
|
+
|
|
17
|
+
import ExecutionPopup from "./ExecutionPopup";
|
|
17
18
|
|
|
18
19
|
const staticHeaderLabels = [
|
|
19
20
|
"implementation_key",
|
|
@@ -39,20 +40,6 @@ const staticContentLabels = [
|
|
|
39
40
|
"executable.false",
|
|
40
41
|
];
|
|
41
42
|
|
|
42
|
-
const actions = (handleSubmit) => [
|
|
43
|
-
{
|
|
44
|
-
key: "no",
|
|
45
|
-
secondary: true,
|
|
46
|
-
content: <FormattedMessage id="confirmation.no" />,
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
key: "yes",
|
|
50
|
-
primary: true,
|
|
51
|
-
content: <FormattedMessage id="confirmation.yes" />,
|
|
52
|
-
onClick: handleSubmit,
|
|
53
|
-
},
|
|
54
|
-
];
|
|
55
|
-
|
|
56
43
|
export const RuleImplementationsActions = ({
|
|
57
44
|
addImplementationFilter,
|
|
58
45
|
canExecute,
|
|
@@ -60,7 +47,6 @@ export const RuleImplementationsActions = ({
|
|
|
60
47
|
executeImplementationsOn,
|
|
61
48
|
toggleImplementationFilterValue,
|
|
62
49
|
removeImplementationFilter,
|
|
63
|
-
executionGroupLoading,
|
|
64
50
|
createExecutionGroup,
|
|
65
51
|
selectedImplementations,
|
|
66
52
|
implementationQuery,
|
|
@@ -69,6 +55,7 @@ export const RuleImplementationsActions = ({
|
|
|
69
55
|
ruleImplementationCount,
|
|
70
56
|
ruleImplementationsDownloading,
|
|
71
57
|
ruleImplementationsLoading,
|
|
58
|
+
upload,
|
|
72
59
|
}) => {
|
|
73
60
|
const { formatMessage } = useIntl();
|
|
74
61
|
|
|
@@ -99,11 +86,11 @@ export const RuleImplementationsActions = ({
|
|
|
99
86
|
checked ? showExecutableInfo() : hideExecutableInfo();
|
|
100
87
|
};
|
|
101
88
|
|
|
102
|
-
const handleSubmit = () => {
|
|
89
|
+
const handleSubmit = (df_content) => {
|
|
103
90
|
const query = _.isEmpty(selectedImplementations)
|
|
104
91
|
? implementationQuery
|
|
105
92
|
: { filters: { id: selectedImplementations } };
|
|
106
|
-
createExecutionGroup({ ...query });
|
|
93
|
+
createExecutionGroup({ ...query, df_content });
|
|
107
94
|
};
|
|
108
95
|
return (
|
|
109
96
|
<div style={{ float: "right" }}>
|
|
@@ -117,32 +104,14 @@ export const RuleImplementationsActions = ({
|
|
|
117
104
|
checked={executeImplementationsOn}
|
|
118
105
|
style={{ top: "6px", marginRight: "7.5px" }}
|
|
119
106
|
/>
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
disabled={!executeImplementationsOn}
|
|
127
|
-
loading={executionGroupLoading}
|
|
128
|
-
content={
|
|
129
|
-
<FormattedMessage id="implementations.actions.do_execution" />
|
|
130
|
-
}
|
|
131
|
-
/>
|
|
132
|
-
}
|
|
133
|
-
header={
|
|
134
|
-
<FormattedMessage id="implementations.actions.execution.confirmation.header" />
|
|
135
|
-
}
|
|
136
|
-
content={
|
|
137
|
-
<FormattedMessage
|
|
138
|
-
id="implementations.actions.execution.confirmation.content"
|
|
139
|
-
values={{
|
|
140
|
-
implementations_count: _.isEmpty(selectedImplementations)
|
|
141
|
-
? ruleImplementationCount
|
|
142
|
-
: selectedImplementations.length,
|
|
143
|
-
}}
|
|
144
|
-
/>
|
|
107
|
+
<ExecutionPopup
|
|
108
|
+
disabled={!executeImplementationsOn}
|
|
109
|
+
count={
|
|
110
|
+
_.isEmpty(selectedImplementations)
|
|
111
|
+
? ruleImplementationCount
|
|
112
|
+
: selectedImplementations.length
|
|
145
113
|
}
|
|
114
|
+
handleSubmit={handleSubmit}
|
|
146
115
|
/>
|
|
147
116
|
</>
|
|
148
117
|
)}
|
|
@@ -160,6 +129,8 @@ export const RuleImplementationsActions = ({
|
|
|
160
129
|
loading={ruleImplementationsDownloading}
|
|
161
130
|
/>
|
|
162
131
|
)}
|
|
132
|
+
{upload && <ImplementationsUploadButton />}
|
|
133
|
+
<ImplementationsUploadButton />
|
|
163
134
|
</div>
|
|
164
135
|
);
|
|
165
136
|
};
|
|
@@ -170,7 +141,6 @@ RuleImplementationsActions.propTypes = {
|
|
|
170
141
|
canExecute: PropTypes.bool,
|
|
171
142
|
createExecutionGroup: PropTypes.func,
|
|
172
143
|
executeImplementationsOn: PropTypes.bool,
|
|
173
|
-
executionGroupLoading: PropTypes.bool,
|
|
174
144
|
implementationsExecution: PropTypes.bool,
|
|
175
145
|
implementationQuery: PropTypes.object,
|
|
176
146
|
removeImplementationFilter: PropTypes.func,
|
|
@@ -180,11 +150,11 @@ RuleImplementationsActions.propTypes = {
|
|
|
180
150
|
toggleImplementationFilterValue: PropTypes.func,
|
|
181
151
|
ruleImplementationsDownloading: PropTypes.bool,
|
|
182
152
|
ruleImplementationsLoading: PropTypes.bool,
|
|
153
|
+
upload: PropTypes.bool,
|
|
183
154
|
};
|
|
184
155
|
|
|
185
156
|
const mapStateToProps = (state) => ({
|
|
186
157
|
canExecute: _.propOr(false, "userImplementationsPermissions.execute")(state),
|
|
187
|
-
executionGroupLoading: state.executionGroupLoading,
|
|
188
158
|
ruleImplementationCount: state.ruleImplementationCount,
|
|
189
159
|
implementationsExecution: getImplementationsExecution(state),
|
|
190
160
|
ruleImplementationsDownloading: state.ruleImplementationsDownloading,
|
|
@@ -197,4 +167,4 @@ export default connect(mapStateToProps, {
|
|
|
197
167
|
toggleImplementationFilterValue,
|
|
198
168
|
removeImplementationFilter,
|
|
199
169
|
createExecutionGroup,
|
|
200
|
-
})(RuleImplementationsActions);
|
|
170
|
+
})(RuleImplementationsActions, uploadImplementations);
|
|
@@ -3,12 +3,10 @@ import React from "react";
|
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { FormattedMessage } from "react-intl";
|
|
5
5
|
import { connect } from "react-redux";
|
|
6
|
-
import {
|
|
6
|
+
import { Link } from "react-router-dom";
|
|
7
7
|
import { List, Label } from "semantic-ui-react";
|
|
8
8
|
import "rc-slider/assets/index.css";
|
|
9
9
|
import { linkTo } from "@truedat/core/routes";
|
|
10
|
-
import RuleRangeNumber from "./RuleRangeNumber";
|
|
11
|
-
import RuleRangePercentage from "./RuleRangePercentage";
|
|
12
10
|
|
|
13
11
|
const RichTextEditor = React.lazy(() =>
|
|
14
12
|
import("@truedat/core/components/RichTextEditor")
|
|
@@ -27,7 +25,6 @@ export const RuleProperties = ({
|
|
|
27
25
|
domain,
|
|
28
26
|
domain_id,
|
|
29
27
|
active,
|
|
30
|
-
result_type,
|
|
31
28
|
}) => {
|
|
32
29
|
return (
|
|
33
30
|
<List size="big" relaxed>
|
|
@@ -67,11 +64,6 @@ export const RuleProperties = ({
|
|
|
67
64
|
</Link>
|
|
68
65
|
</List.Item>
|
|
69
66
|
)}
|
|
70
|
-
{["percentage", "deviation"].includes(result_type) ? (
|
|
71
|
-
<RuleRangePercentage />
|
|
72
|
-
) : (
|
|
73
|
-
<RuleRangeNumber />
|
|
74
|
-
)}
|
|
75
67
|
</List>
|
|
76
68
|
);
|
|
77
69
|
};
|
|
@@ -83,7 +75,6 @@ RuleProperties.propTypes = {
|
|
|
83
75
|
description: PropTypes.object,
|
|
84
76
|
domain: PropTypes.object,
|
|
85
77
|
domain_id: PropTypes.number,
|
|
86
|
-
result_type: PropTypes.string,
|
|
87
78
|
};
|
|
88
79
|
|
|
89
80
|
const mapStateToProps = ({ rule }) => rule;
|
|
@@ -10,31 +10,30 @@ const nilResult = (ruleResult) =>
|
|
|
10
10
|
isNil(ruleResult) ||
|
|
11
11
|
(has("result_text")(ruleResult) && isNil(ruleResult?.result_text));
|
|
12
12
|
|
|
13
|
-
export const
|
|
14
|
-
|
|
13
|
+
export const calculateResultDecoration = ({
|
|
14
|
+
ruleResult,
|
|
15
|
+
ruleImplementation,
|
|
16
|
+
date,
|
|
17
|
+
intl: { formatMessage, formatNumber: _formatNumber },
|
|
18
|
+
}) => {
|
|
15
19
|
const formatNumber = (num) => (isNil(num) ? num : _formatNumber(num));
|
|
16
|
-
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
20
|
+
|
|
19
21
|
if (ruleResult?.result_text === "quality_result.failed") {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
{formatMessage({ id: "quality_result.failed" })}
|
|
28
|
-
</>
|
|
29
|
-
);
|
|
22
|
+
const resultText = formatMessage({ id: "quality_result.failed" });
|
|
23
|
+
return {
|
|
24
|
+
iconName: "warning circle",
|
|
25
|
+
resultText: resultText,
|
|
26
|
+
color: "red",
|
|
27
|
+
resultText,
|
|
28
|
+
};
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
const resultType =
|
|
30
|
+
|
|
31
|
+
const resultType = ruleImplementation?.result_type;
|
|
33
32
|
const result =
|
|
34
33
|
resultType === "errors_number"
|
|
35
34
|
? formatNumber(ruleResult?.errors)
|
|
36
35
|
: ruleResult?.result;
|
|
37
|
-
const
|
|
36
|
+
const resultText = isNil(result)
|
|
38
37
|
? formatMessage({ id: "quality.result.no.data" })
|
|
39
38
|
: date
|
|
40
39
|
? formatMessage(
|
|
@@ -45,23 +44,41 @@ export const RuleResultDecorator = ({ ruleResult, rule, date }) => {
|
|
|
45
44
|
{ id: `quality.result.${resultType}.description` },
|
|
46
45
|
{ result }
|
|
47
46
|
);
|
|
48
|
-
const color = selectColor({ ...
|
|
47
|
+
const color = selectColor({ ...ruleImplementation, ...ruleResult });
|
|
48
|
+
const iconTitle = ruleResult?.result_text
|
|
49
|
+
? formatMessage({ id: ruleResult?.result_text })
|
|
50
|
+
: null;
|
|
51
|
+
|
|
52
|
+
return { iconName: "circle", color, resultText, iconTitle };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const RuleResultDecorator = ({
|
|
56
|
+
ruleResult,
|
|
57
|
+
ruleImplementation,
|
|
58
|
+
date,
|
|
59
|
+
}) => {
|
|
60
|
+
const intl = useIntl();
|
|
61
|
+
if (nilResult(ruleResult) && isNil(date)) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const { iconName, color, resultText, iconTitle } = calculateResultDecoration({
|
|
65
|
+
ruleResult,
|
|
66
|
+
ruleImplementation,
|
|
67
|
+
date,
|
|
68
|
+
intl,
|
|
69
|
+
});
|
|
49
70
|
|
|
50
71
|
return (
|
|
51
72
|
<>
|
|
52
|
-
<Icon
|
|
53
|
-
|
|
54
|
-
title={resultText ? formatMessage({ id: resultText }) : null}
|
|
55
|
-
color={color}
|
|
56
|
-
/>
|
|
57
|
-
{resultTitle}
|
|
73
|
+
<Icon name={iconName} title={iconTitle} color={color} />
|
|
74
|
+
{resultText}
|
|
58
75
|
</>
|
|
59
76
|
);
|
|
60
77
|
};
|
|
61
78
|
|
|
62
79
|
RuleResultDecorator.propTypes = {
|
|
63
80
|
ruleResult: PropTypes.object,
|
|
64
|
-
|
|
81
|
+
ruleImplementation: PropTypes.object,
|
|
65
82
|
date: PropTypes.string,
|
|
66
83
|
};
|
|
67
84
|
|
|
@@ -41,7 +41,10 @@ export const RuleResultRow = ({
|
|
|
41
41
|
}
|
|
42
42
|
>
|
|
43
43
|
<Table.Cell>
|
|
44
|
-
<Icon
|
|
44
|
+
<Icon
|
|
45
|
+
name="circle"
|
|
46
|
+
color={selectColor({ ...ruleImplementation, ...ruleResult })}
|
|
47
|
+
/>
|
|
45
48
|
{`${parseFloat(ruleResult.result)} %`}
|
|
46
49
|
</Table.Cell>
|
|
47
50
|
<Table.Cell>
|
|
@@ -66,7 +66,6 @@ const RuleRoutes = ({
|
|
|
66
66
|
templatesLoaded,
|
|
67
67
|
template,
|
|
68
68
|
structuresAliasesLoading,
|
|
69
|
-
templateImpl,
|
|
70
69
|
ruleImplementation,
|
|
71
70
|
}) => {
|
|
72
71
|
const latest = _.head(ruleImplementation.results);
|
|
@@ -227,14 +226,6 @@ const RuleRoutes = ({
|
|
|
227
226
|
<RuleImplementationProperties />
|
|
228
227
|
</RuleImplementation>
|
|
229
228
|
)}
|
|
230
|
-
{!_.isEmpty(templateImpl) && ruleImplementationLoaded && (
|
|
231
|
-
<Segment attached="bottom">
|
|
232
|
-
<DynamicFormViewer
|
|
233
|
-
template={templateImpl}
|
|
234
|
-
content={ruleImplementation.df_content}
|
|
235
|
-
/>
|
|
236
|
-
</Segment>
|
|
237
|
-
)}
|
|
238
229
|
</Segment>
|
|
239
230
|
</>
|
|
240
231
|
)}
|
|
@@ -305,7 +296,6 @@ RuleRoutes.propTypes = {
|
|
|
305
296
|
implementationStructures: PropTypes.array,
|
|
306
297
|
ruleLoaded: PropTypes.bool,
|
|
307
298
|
template: PropTypes.object,
|
|
308
|
-
templateImpl: PropTypes.object,
|
|
309
299
|
ruleImplementation: PropTypes.object,
|
|
310
300
|
ruleImplementationLoaded: PropTypes.bool,
|
|
311
301
|
implementationStructuresLoaded: PropTypes.bool,
|
|
@@ -325,9 +315,6 @@ const mapStateToProps = (state) => ({
|
|
|
325
315
|
templatesLoaded: !state.templatesLoading && !_.isEmpty(state.templates),
|
|
326
316
|
template: _.find(_.propEq("name", state.rule.df_name))(state.templates),
|
|
327
317
|
structuresAliasesLoading: state.structuresAliasesLoading,
|
|
328
|
-
templateImpl: _.find(_.propEq("name", state.ruleImplementation.df_name))(
|
|
329
|
-
state.templates
|
|
330
|
-
),
|
|
331
318
|
ruleImplementation: state.ruleImplementation,
|
|
332
319
|
});
|
|
333
320
|
|
|
@@ -22,8 +22,12 @@ const mapSummary = (implementations) => {
|
|
|
22
22
|
const failed = _.size(failedImplementations);
|
|
23
23
|
const quality = _.reduce(
|
|
24
24
|
(summary, implementation) => {
|
|
25
|
-
const {
|
|
26
|
-
|
|
25
|
+
const {
|
|
26
|
+
goal,
|
|
27
|
+
minimum,
|
|
28
|
+
result_type,
|
|
29
|
+
execution_result_info: { errors, result },
|
|
30
|
+
} = implementation;
|
|
27
31
|
const color = selectColor({ errors, result, minimum, goal, result_type });
|
|
28
32
|
return _.set(color, summary[color] + 1)(summary);
|
|
29
33
|
},
|
|
@@ -71,6 +75,15 @@ const SummaryBar = ({
|
|
|
71
75
|
</>
|
|
72
76
|
);
|
|
73
77
|
|
|
78
|
+
SummaryBar.propTypes = {
|
|
79
|
+
key: PropTypes.string,
|
|
80
|
+
className: PropTypes.string,
|
|
81
|
+
summary: PropTypes.object,
|
|
82
|
+
percentages: PropTypes.array,
|
|
83
|
+
showPercentages: PropTypes.bool,
|
|
84
|
+
tooltip: PropTypes.string,
|
|
85
|
+
};
|
|
86
|
+
|
|
74
87
|
const SummaryBars = (props) => {
|
|
75
88
|
return (
|
|
76
89
|
<div className="rule-summary">
|