@truedat/dq 4.33.10 → 4.35.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 +26 -0
- package/package.json +5 -5
- package/src/api.js +7 -1
- package/src/components/ConditionSummary.js +23 -21
- package/src/components/ExecutionDetails.js +11 -14
- package/src/components/ExecutionGroup.js +24 -15
- package/src/components/ImplementationResultBar.js +80 -0
- package/src/components/ImplementationSummary.js +33 -72
- package/src/components/ImplementationsUploadButton.js +61 -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 +3 -59
- package/src/components/RuleImplementationsDownload.js +86 -0
- package/src/components/RuleImplementationsOptions.js +28 -0
- package/src/components/RuleProperties.js +1 -10
- package/src/components/RuleResultDecorator.js +43 -26
- package/src/components/RuleResultRow.js +4 -1
- package/src/components/RuleResultsUpload.js +47 -0
- 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__/ExecutionGroup.spec.js +11 -7
- 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 +0 -9
- package/src/components/__tests__/RuleImplementationsOptions.spec.js +18 -0
- 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__/RuleResultsUpload.spec.js +18 -0
- 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__/ExecutionGroup.spec.js.snap +5 -4
- 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 +1 -7
- package/src/components/__tests__/__snapshots__/RuleImplementationsOptions.spec.js.snap +58 -0
- package/src/components/__tests__/__snapshots__/RuleProperties.spec.js.snap +0 -1
- package/src/components/__tests__/__snapshots__/RuleResultsUpload.spec.js.snap +18 -0
- 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/FiltersGroup.js +1 -0
- 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/ValueConditions.js +11 -0
- 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 +167 -76
- package/src/messages/es.js +292 -185
- 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/__tests__/uploadingResults.spec.js +28 -0
- package/src/reducers/dqMessage.js +121 -1
- package/src/reducers/index.js +6 -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/reducers/uploadingResults.js +16 -0
- package/src/routines.js +3 -0
- package/src/sagas/__tests__/uploadResults.spec.js +65 -0
- package/src/sagas/index.js +9 -0
- package/src/sagas/uploadImplementations.js +28 -0
- package/src/sagas/uploadResults.js +32 -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
|
@@ -2,9 +2,7 @@ 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 {
|
|
6
|
-
import { useIntl } from "react-intl";
|
|
7
|
-
import { downloadImplementations } from "../routines";
|
|
5
|
+
import { Checkbox } from "semantic-ui-react";
|
|
8
6
|
import { getImplementationsExecution } from "../selectors";
|
|
9
7
|
import {
|
|
10
8
|
addImplementationFilter,
|
|
@@ -13,35 +11,11 @@ import {
|
|
|
13
11
|
createExecutionGroup,
|
|
14
12
|
} from "../routines";
|
|
15
13
|
import ExecutionPopup from "./ExecutionPopup";
|
|
16
|
-
|
|
17
|
-
const staticHeaderLabels = [
|
|
18
|
-
"implementation_key",
|
|
19
|
-
"implementation_type",
|
|
20
|
-
"rule",
|
|
21
|
-
"template",
|
|
22
|
-
"goal",
|
|
23
|
-
"minimum",
|
|
24
|
-
"business_concept",
|
|
25
|
-
"last_execution_at",
|
|
26
|
-
"result",
|
|
27
|
-
"execution",
|
|
28
|
-
"inserted_at",
|
|
29
|
-
"executable",
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
const staticContentLabels = [
|
|
33
|
-
"quality_result.under_minimum",
|
|
34
|
-
"quality_result.under_goal",
|
|
35
|
-
"quality_result.over_goal",
|
|
36
|
-
"quality_result.no_execution",
|
|
37
|
-
"executable.true",
|
|
38
|
-
"executable.false",
|
|
39
|
-
];
|
|
14
|
+
import RuleImplementationsOptions from "./RuleImplementationsOptions";
|
|
40
15
|
|
|
41
16
|
export const RuleImplementationsActions = ({
|
|
42
17
|
addImplementationFilter,
|
|
43
18
|
canExecute,
|
|
44
|
-
downloadImplementations,
|
|
45
19
|
executeImplementationsOn,
|
|
46
20
|
toggleImplementationFilterValue,
|
|
47
21
|
removeImplementationFilter,
|
|
@@ -51,21 +25,8 @@ export const RuleImplementationsActions = ({
|
|
|
51
25
|
setMode,
|
|
52
26
|
implementationsExecution,
|
|
53
27
|
ruleImplementationCount,
|
|
54
|
-
ruleImplementationsDownloading,
|
|
55
28
|
ruleImplementationsLoading,
|
|
56
29
|
}) => {
|
|
57
|
-
const { formatMessage } = useIntl();
|
|
58
|
-
|
|
59
|
-
const headerLabels = _.flow(
|
|
60
|
-
_.map((l) => [l, formatMessage({ id: `ruleImplementations.props.${l}` })]),
|
|
61
|
-
_.fromPairs
|
|
62
|
-
)(staticHeaderLabels);
|
|
63
|
-
|
|
64
|
-
const contentLabels = _.flow(
|
|
65
|
-
_.map((l) => [l, formatMessage({ id: `ruleImplementations.props.${l}` })]),
|
|
66
|
-
_.fromPairs
|
|
67
|
-
)(staticContentLabels);
|
|
68
|
-
|
|
69
30
|
const showExecutableInfo = () => {
|
|
70
31
|
addImplementationFilter({ filter: "executable" });
|
|
71
32
|
toggleImplementationFilterValue({
|
|
@@ -112,27 +73,13 @@ export const RuleImplementationsActions = ({
|
|
|
112
73
|
/>
|
|
113
74
|
</>
|
|
114
75
|
)}
|
|
115
|
-
{
|
|
116
|
-
<Button
|
|
117
|
-
floated="right"
|
|
118
|
-
secondary
|
|
119
|
-
icon="download"
|
|
120
|
-
data-tooltip={formatMessage({
|
|
121
|
-
id: "implementations.actions.download.tooltip",
|
|
122
|
-
})}
|
|
123
|
-
onClick={() =>
|
|
124
|
-
downloadImplementations({ contentLabels, headerLabels })
|
|
125
|
-
}
|
|
126
|
-
loading={ruleImplementationsDownloading}
|
|
127
|
-
/>
|
|
128
|
-
)}
|
|
76
|
+
<RuleImplementationsOptions loading={ruleImplementationsLoading} />
|
|
129
77
|
</div>
|
|
130
78
|
);
|
|
131
79
|
};
|
|
132
80
|
|
|
133
81
|
RuleImplementationsActions.propTypes = {
|
|
134
82
|
addImplementationFilter: PropTypes.func,
|
|
135
|
-
downloadImplementations: PropTypes.func,
|
|
136
83
|
canExecute: PropTypes.bool,
|
|
137
84
|
createExecutionGroup: PropTypes.func,
|
|
138
85
|
executeImplementationsOn: PropTypes.bool,
|
|
@@ -143,7 +90,6 @@ RuleImplementationsActions.propTypes = {
|
|
|
143
90
|
selectedImplementations: PropTypes.array,
|
|
144
91
|
setMode: PropTypes.func,
|
|
145
92
|
toggleImplementationFilterValue: PropTypes.func,
|
|
146
|
-
ruleImplementationsDownloading: PropTypes.bool,
|
|
147
93
|
ruleImplementationsLoading: PropTypes.bool,
|
|
148
94
|
};
|
|
149
95
|
|
|
@@ -151,13 +97,11 @@ const mapStateToProps = (state) => ({
|
|
|
151
97
|
canExecute: _.propOr(false, "userImplementationsPermissions.execute")(state),
|
|
152
98
|
ruleImplementationCount: state.ruleImplementationCount,
|
|
153
99
|
implementationsExecution: getImplementationsExecution(state),
|
|
154
|
-
ruleImplementationsDownloading: state.ruleImplementationsDownloading,
|
|
155
100
|
ruleImplementationsLoading: state.ruleImplementationsLoading,
|
|
156
101
|
});
|
|
157
102
|
|
|
158
103
|
export default connect(mapStateToProps, {
|
|
159
104
|
addImplementationFilter,
|
|
160
|
-
downloadImplementations,
|
|
161
105
|
toggleImplementationFilterValue,
|
|
162
106
|
removeImplementationFilter,
|
|
163
107
|
createExecutionGroup,
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { connect } from "react-redux";
|
|
5
|
+
import { Dropdown } from "semantic-ui-react";
|
|
6
|
+
import { useIntl } from "react-intl";
|
|
7
|
+
import { downloadImplementations } from "../routines";
|
|
8
|
+
|
|
9
|
+
const staticHeaderLabels = [
|
|
10
|
+
"implementation_key",
|
|
11
|
+
"implementation_type",
|
|
12
|
+
"rule",
|
|
13
|
+
"template",
|
|
14
|
+
"goal",
|
|
15
|
+
"minimum",
|
|
16
|
+
"business_concept",
|
|
17
|
+
"last_execution_at",
|
|
18
|
+
"result",
|
|
19
|
+
"execution",
|
|
20
|
+
"inserted_at",
|
|
21
|
+
"executable",
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const staticContentLabels = [
|
|
25
|
+
"quality_result.under_minimum",
|
|
26
|
+
"quality_result.under_goal",
|
|
27
|
+
"quality_result.over_goal",
|
|
28
|
+
"quality_result.no_execution",
|
|
29
|
+
"executable.true",
|
|
30
|
+
"executable.false",
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
export const RuleImplementationsDownload = ({
|
|
34
|
+
downloadImplementations,
|
|
35
|
+
ruleImplementationsDownloading,
|
|
36
|
+
ruleImplementations,
|
|
37
|
+
}) => {
|
|
38
|
+
const { formatMessage } = useIntl();
|
|
39
|
+
|
|
40
|
+
const headerLabels = _.flow(
|
|
41
|
+
_.map((l) => [l, formatMessage({ id: `ruleImplementations.props.${l}` })]),
|
|
42
|
+
_.fromPairs
|
|
43
|
+
)(staticHeaderLabels);
|
|
44
|
+
|
|
45
|
+
const contentLabels = _.flow(
|
|
46
|
+
_.map((l) => [l, formatMessage({ id: `ruleImplementations.props.${l}` })]),
|
|
47
|
+
_.fromPairs
|
|
48
|
+
)(staticContentLabels);
|
|
49
|
+
|
|
50
|
+
const isDisabled = _.isEmpty(ruleImplementations);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Dropdown.Item
|
|
54
|
+
icon="download"
|
|
55
|
+
content={
|
|
56
|
+
<>
|
|
57
|
+
<span>
|
|
58
|
+
{formatMessage({ id: "implementations.actions.download.tooltip" })}
|
|
59
|
+
</span>
|
|
60
|
+
{isDisabled && (
|
|
61
|
+
<p className="menu-item-description">
|
|
62
|
+
{formatMessage({ id: "implementations.actions.download.empty" })}
|
|
63
|
+
</p>
|
|
64
|
+
)}
|
|
65
|
+
</>
|
|
66
|
+
}
|
|
67
|
+
onClick={() => downloadImplementations({ contentLabels, headerLabels })}
|
|
68
|
+
disabled={isDisabled || ruleImplementationsDownloading}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
RuleImplementationsDownload.propTypes = {
|
|
74
|
+
downloadImplementations: PropTypes.func,
|
|
75
|
+
ruleImplementationsDownloading: PropTypes.bool,
|
|
76
|
+
ruleImplementations: PropTypes.array,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const mapStateToProps = _.pick([
|
|
80
|
+
"ruleImplementationsDownloading",
|
|
81
|
+
"ruleImplementations",
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
export default connect(mapStateToProps, {
|
|
85
|
+
downloadImplementations,
|
|
86
|
+
})(RuleImplementationsDownload);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { Dropdown } from "semantic-ui-react";
|
|
4
|
+
import RuleImplementationsDownload from "./RuleImplementationsDownload";
|
|
5
|
+
import RuleResultsUpload from "./RuleResultsUpload";
|
|
6
|
+
import ImplementationsUploadButton from "./ImplementationsUploadButton";
|
|
7
|
+
|
|
8
|
+
export const RuleImplementationsOptions = ({ loading }) => (
|
|
9
|
+
<Dropdown
|
|
10
|
+
icon="ellipsis vertical"
|
|
11
|
+
className="button icon group-actions button-update"
|
|
12
|
+
direction="left"
|
|
13
|
+
floating
|
|
14
|
+
disabled={loading}
|
|
15
|
+
>
|
|
16
|
+
<Dropdown.Menu>
|
|
17
|
+
<RuleImplementationsDownload />
|
|
18
|
+
<ImplementationsUploadButton />
|
|
19
|
+
<RuleResultsUpload />
|
|
20
|
+
</Dropdown.Menu>
|
|
21
|
+
</Dropdown>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
RuleImplementationsOptions.propTypes = {
|
|
25
|
+
loading: PropTypes.bool,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default RuleImplementationsOptions;
|
|
@@ -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>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { connect } from "react-redux";
|
|
4
|
+
import { Dropdown } from "semantic-ui-react";
|
|
5
|
+
import { useIntl } from "react-intl";
|
|
6
|
+
import { UploadModal } from "@truedat/core/components";
|
|
7
|
+
import { uploadResults } from "../routines";
|
|
8
|
+
|
|
9
|
+
export const RuleResultsUpload = ({ uploadResults, loading }) => {
|
|
10
|
+
const { formatMessage } = useIntl();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<UploadModal
|
|
14
|
+
icon="upload"
|
|
15
|
+
trigger={
|
|
16
|
+
<Dropdown.Item
|
|
17
|
+
icon="upload"
|
|
18
|
+
text={formatMessage({ id: "ruleResults.actions.upload.tooltip" })}
|
|
19
|
+
disabled={loading}
|
|
20
|
+
/>
|
|
21
|
+
}
|
|
22
|
+
header={formatMessage({
|
|
23
|
+
id: "ruleResults.actions.upload.confirmation.header",
|
|
24
|
+
})}
|
|
25
|
+
content={formatMessage({
|
|
26
|
+
id: "uploadModal.actions.upload.confirmation.content",
|
|
27
|
+
})}
|
|
28
|
+
param={"rule_results"}
|
|
29
|
+
handleSubmit={(data) =>
|
|
30
|
+
uploadResults({
|
|
31
|
+
data,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
RuleResultsUpload.propTypes = {
|
|
39
|
+
uploadResults: PropTypes.func,
|
|
40
|
+
loading: PropTypes.bool,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const mapStateToProps = ({ uploadingResults }) => ({
|
|
44
|
+
loading: uploadingResults,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export default connect(mapStateToProps, { uploadResults })(RuleResultsUpload);
|
|
@@ -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">
|
|
@@ -5,26 +5,33 @@ import { Link } from "react-router-dom";
|
|
|
5
5
|
import { Button } from "semantic-ui-react";
|
|
6
6
|
import { FormattedMessage } from "react-intl";
|
|
7
7
|
import { RULE_NEW } from "@truedat/core/routes";
|
|
8
|
+
import { uploadRules } from "../routines";
|
|
9
|
+
import RulesUploadButton from "./RulesUploadButton";
|
|
8
10
|
|
|
9
|
-
export const RulesActions = ({ userRulesPermissions }) => (
|
|
11
|
+
export const RulesActions = ({ userRulesPermissions, upload }) => (
|
|
10
12
|
<div style={{ float: "right" }}>
|
|
11
13
|
{userRulesPermissions.manage_quality_rules && (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
<>
|
|
15
|
+
<Button
|
|
16
|
+
primary
|
|
17
|
+
as={Link}
|
|
18
|
+
to={RULE_NEW}
|
|
19
|
+
content={<FormattedMessage id="quality.actions.create" />}
|
|
20
|
+
/>
|
|
21
|
+
{upload && <RulesUploadButton />}
|
|
22
|
+
<RulesUploadButton />
|
|
23
|
+
</>
|
|
18
24
|
)}
|
|
19
25
|
</div>
|
|
20
26
|
);
|
|
21
27
|
|
|
22
28
|
RulesActions.propTypes = {
|
|
23
|
-
userRulesPermissions: PropTypes.object
|
|
29
|
+
userRulesPermissions: PropTypes.object,
|
|
30
|
+
upload: PropTypes.bool,
|
|
24
31
|
};
|
|
25
32
|
|
|
26
33
|
const mapStateToProps = ({ userRulesPermissions }) => ({
|
|
27
|
-
userRulesPermissions
|
|
34
|
+
userRulesPermissions,
|
|
28
35
|
});
|
|
29
36
|
|
|
30
|
-
export default connect(mapStateToProps)(RulesActions);
|
|
37
|
+
export default connect(mapStateToProps)(RulesActions, uploadRules);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import { connect } from "react-redux";
|
|
4
|
+
import { Button } from "semantic-ui-react";
|
|
5
|
+
import { FormattedMessage, useIntl } from "react-intl";
|
|
6
|
+
import { UploadModal } from "@truedat/core/components";
|
|
7
|
+
import { API_RULES_UPLOAD } from "../api";
|
|
8
|
+
import { uploadRules } from "../routines";
|
|
9
|
+
|
|
10
|
+
const uploadAction = {
|
|
11
|
+
method: "POST",
|
|
12
|
+
href: API_RULES_UPLOAD,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const RulesUploadButton = ({ uploadRules, loading }) => {
|
|
16
|
+
const { formatMessage } = useIntl();
|
|
17
|
+
return (
|
|
18
|
+
<UploadModal
|
|
19
|
+
icon="upload"
|
|
20
|
+
trigger={
|
|
21
|
+
<Button
|
|
22
|
+
secondary
|
|
23
|
+
floated="right"
|
|
24
|
+
icon="upload"
|
|
25
|
+
loading={loading}
|
|
26
|
+
data-tooltip={formatMessage({
|
|
27
|
+
id: "rules.actions.upload.tooltip",
|
|
28
|
+
})}
|
|
29
|
+
/>
|
|
30
|
+
}
|
|
31
|
+
header={
|
|
32
|
+
<FormattedMessage id="rules.actions.upload.confirmation.header" />
|
|
33
|
+
}
|
|
34
|
+
content={
|
|
35
|
+
<FormattedMessage id="rules.actions.upload.confirmation.content" />
|
|
36
|
+
}
|
|
37
|
+
param={"rules"}
|
|
38
|
+
handleSubmit={(data) =>
|
|
39
|
+
uploadRules({
|
|
40
|
+
action: "upload",
|
|
41
|
+
data,
|
|
42
|
+
...uploadAction,
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
RulesUploadButton.propTypes = {
|
|
50
|
+
uploadRules: PropTypes.func,
|
|
51
|
+
loading: PropTypes.bool,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const mapStateToProps = ({ uploadRulesFile: { loading } }) => ({
|
|
55
|
+
loading,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export default connect(mapStateToProps, { uploadRules })(RulesUploadButton);
|
|
@@ -11,11 +11,15 @@ describe("<ExecutionGroup />", () => {
|
|
|
11
11
|
const rule = {
|
|
12
12
|
id: 1,
|
|
13
13
|
name: "rule_name",
|
|
14
|
+
};
|
|
15
|
+
const implementation = {
|
|
16
|
+
id: 1,
|
|
17
|
+
implementation_key: "foo",
|
|
18
|
+
rule_id: 1,
|
|
14
19
|
result_type: "percentage",
|
|
15
20
|
minimum: 10,
|
|
16
|
-
goal: 20
|
|
21
|
+
goal: 20,
|
|
17
22
|
};
|
|
18
|
-
const implementation = { id: 1, implementation_key: "foo", rule_id: 1 };
|
|
19
23
|
const result = {
|
|
20
24
|
id: 1,
|
|
21
25
|
implementation_key: "foo",
|
|
@@ -25,7 +29,7 @@ describe("<ExecutionGroup />", () => {
|
|
|
25
29
|
errors: 30,
|
|
26
30
|
result_type: "percentage",
|
|
27
31
|
minimum: 10,
|
|
28
|
-
goal: 20
|
|
32
|
+
goal: 20,
|
|
29
33
|
};
|
|
30
34
|
const quality_events = [
|
|
31
35
|
{
|
|
@@ -33,14 +37,14 @@ describe("<ExecutionGroup />", () => {
|
|
|
33
37
|
execution_id: 1,
|
|
34
38
|
id: 1,
|
|
35
39
|
type: "SUCCESS",
|
|
36
|
-
message: ""
|
|
37
|
-
}
|
|
40
|
+
message: "",
|
|
41
|
+
},
|
|
38
42
|
];
|
|
39
43
|
const executions = [
|
|
40
|
-
{ id: 1, _embedded: { rule, implementation, result, quality_events } }
|
|
44
|
+
{ id: 1, _embedded: { rule, implementation, result, quality_events } },
|
|
41
45
|
];
|
|
42
46
|
const props = {
|
|
43
|
-
executionGroup: { id: 1, _embedded: { executions } }
|
|
47
|
+
executionGroup: { id: 1, _embedded: { executions } },
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
it("matches the latest snapshot", () => {
|