@truedat/dq 4.34.2 → 4.34.3
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 +9 -1
- package/package.json +2 -2
- package/src/api.js +2 -0
- package/src/components/ImplementationsUploadButton.js +4 -6
- package/src/components/RuleImplementationsActions.js +4 -66
- package/src/components/RuleImplementationsDownload.js +86 -0
- package/src/components/RuleImplementationsOptions.js +28 -0
- package/src/components/RuleResultsUpload.js +47 -0
- package/src/components/__tests__/RuleImplementationsActions.spec.js +0 -9
- package/src/components/__tests__/RuleImplementationsOptions.spec.js +18 -0
- package/src/components/__tests__/RuleResultsUpload.spec.js +18 -0
- package/src/components/__tests__/__snapshots__/RuleImplementationsActions.spec.js.snap +1 -8
- package/src/components/__tests__/__snapshots__/RuleImplementationsOptions.spec.js.snap +58 -0
- package/src/components/__tests__/__snapshots__/RuleResultsUpload.spec.js.snap +18 -0
- package/src/messages/en.js +31 -13
- package/src/messages/es.js +34 -16
- package/src/reducers/__tests__/uploadingResults.spec.js +28 -0
- package/src/reducers/dqMessage.js +22 -1
- package/src/reducers/index.js +2 -0
- package/src/reducers/uploadingResults.js +16 -0
- package/src/routines.js +1 -0
- package/src/sagas/__tests__/uploadResults.spec.js +65 -0
- package/src/sagas/index.js +3 -0
- package/src/sagas/uploadResults.js +32 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.34.
|
|
3
|
+
"version": "4.34.3",
|
|
4
4
|
"description": "Truedat Web Data Quality Module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -103,5 +103,5 @@
|
|
|
103
103
|
"react-dom": ">= 16.8.6 < 17",
|
|
104
104
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
105
105
|
},
|
|
106
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "dd21b988a9cee4d2b5f329a7e20aea95ab6fb936"
|
|
107
107
|
}
|
package/src/api.js
CHANGED
|
@@ -16,6 +16,7 @@ const API_RULE_IMPLEMENTATION_FILTERS_SEARCH =
|
|
|
16
16
|
"/api/rule_implementation_filters/search";
|
|
17
17
|
const API_RULE_IMPLEMENTATIONS_UPLOAD = "/api/rule_implementations/upload";
|
|
18
18
|
const API_RULE_RESULT = "/api/rule_results/:id";
|
|
19
|
+
const API_RULE_RESULTS = "/api/rule_results";
|
|
19
20
|
const API_SUBSCRIPTIONS_SEARCH = "/api/subscriptions/user/me/search";
|
|
20
21
|
const API_SUBSCRIPTION = "/api/subscriptions/:id";
|
|
21
22
|
const API_SUBSCRIPTIONS = "/api/subscriptions";
|
|
@@ -37,6 +38,7 @@ export {
|
|
|
37
38
|
API_RULE_IMPLEMENTATION_FILTERS_SEARCH,
|
|
38
39
|
API_RULE_IMPLEMENTATIONS_UPLOAD,
|
|
39
40
|
API_RULE_RESULT,
|
|
41
|
+
API_RULE_RESULTS,
|
|
40
42
|
API_SUBSCRIPTIONS_SEARCH,
|
|
41
43
|
API_SUBSCRIPTION,
|
|
42
44
|
API_SUBSCRIPTIONS,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import { connect } from "react-redux";
|
|
4
|
-
import {
|
|
4
|
+
import { Dropdown } from "semantic-ui-react";
|
|
5
5
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
6
6
|
import { UploadModal } from "@truedat/core/components";
|
|
7
7
|
import { API_RULE_IMPLEMENTATIONS_UPLOAD } from "../api";
|
|
@@ -21,14 +21,12 @@ export const ImplementationsUploadButton = ({
|
|
|
21
21
|
<UploadModal
|
|
22
22
|
icon="upload"
|
|
23
23
|
trigger={
|
|
24
|
-
<
|
|
25
|
-
secondary
|
|
26
|
-
floated="right"
|
|
24
|
+
<Dropdown.Item
|
|
27
25
|
icon="upload"
|
|
28
|
-
|
|
29
|
-
data-tooltip={formatMessage({
|
|
26
|
+
text={formatMessage({
|
|
30
27
|
id: "ruleImplementations.actions.upload.tooltip",
|
|
31
28
|
})}
|
|
29
|
+
disabled={loading}
|
|
32
30
|
/>
|
|
33
31
|
}
|
|
34
32
|
header={
|
|
@@ -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, uploadImplementations } from "../routines";
|
|
5
|
+
import { Checkbox } from "semantic-ui-react";
|
|
8
6
|
import { getImplementationsExecution } from "../selectors";
|
|
9
7
|
import {
|
|
10
8
|
addImplementationFilter,
|
|
@@ -12,38 +10,12 @@ import {
|
|
|
12
10
|
removeImplementationFilter,
|
|
13
11
|
createExecutionGroup,
|
|
14
12
|
} from "../routines";
|
|
15
|
-
import ImplementationsUploadButton from "./ImplementationsUploadButton";
|
|
16
|
-
|
|
17
13
|
import ExecutionPopup from "./ExecutionPopup";
|
|
18
|
-
|
|
19
|
-
const staticHeaderLabels = [
|
|
20
|
-
"implementation_key",
|
|
21
|
-
"implementation_type",
|
|
22
|
-
"rule",
|
|
23
|
-
"template",
|
|
24
|
-
"goal",
|
|
25
|
-
"minimum",
|
|
26
|
-
"business_concept",
|
|
27
|
-
"last_execution_at",
|
|
28
|
-
"result",
|
|
29
|
-
"execution",
|
|
30
|
-
"inserted_at",
|
|
31
|
-
"executable",
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
const staticContentLabels = [
|
|
35
|
-
"quality_result.under_minimum",
|
|
36
|
-
"quality_result.under_goal",
|
|
37
|
-
"quality_result.over_goal",
|
|
38
|
-
"quality_result.no_execution",
|
|
39
|
-
"executable.true",
|
|
40
|
-
"executable.false",
|
|
41
|
-
];
|
|
14
|
+
import RuleImplementationsOptions from "./RuleImplementationsOptions";
|
|
42
15
|
|
|
43
16
|
export const RuleImplementationsActions = ({
|
|
44
17
|
addImplementationFilter,
|
|
45
18
|
canExecute,
|
|
46
|
-
downloadImplementations,
|
|
47
19
|
executeImplementationsOn,
|
|
48
20
|
toggleImplementationFilterValue,
|
|
49
21
|
removeImplementationFilter,
|
|
@@ -53,22 +25,8 @@ export const RuleImplementationsActions = ({
|
|
|
53
25
|
setMode,
|
|
54
26
|
implementationsExecution,
|
|
55
27
|
ruleImplementationCount,
|
|
56
|
-
ruleImplementationsDownloading,
|
|
57
28
|
ruleImplementationsLoading,
|
|
58
|
-
upload,
|
|
59
29
|
}) => {
|
|
60
|
-
const { formatMessage } = useIntl();
|
|
61
|
-
|
|
62
|
-
const headerLabels = _.flow(
|
|
63
|
-
_.map((l) => [l, formatMessage({ id: `ruleImplementations.props.${l}` })]),
|
|
64
|
-
_.fromPairs
|
|
65
|
-
)(staticHeaderLabels);
|
|
66
|
-
|
|
67
|
-
const contentLabels = _.flow(
|
|
68
|
-
_.map((l) => [l, formatMessage({ id: `ruleImplementations.props.${l}` })]),
|
|
69
|
-
_.fromPairs
|
|
70
|
-
)(staticContentLabels);
|
|
71
|
-
|
|
72
30
|
const showExecutableInfo = () => {
|
|
73
31
|
addImplementationFilter({ filter: "executable" });
|
|
74
32
|
toggleImplementationFilterValue({
|
|
@@ -115,29 +73,13 @@ export const RuleImplementationsActions = ({
|
|
|
115
73
|
/>
|
|
116
74
|
</>
|
|
117
75
|
)}
|
|
118
|
-
{
|
|
119
|
-
<Button
|
|
120
|
-
floated="right"
|
|
121
|
-
secondary
|
|
122
|
-
icon="download"
|
|
123
|
-
data-tooltip={formatMessage({
|
|
124
|
-
id: "implementations.actions.download.tooltip",
|
|
125
|
-
})}
|
|
126
|
-
onClick={() =>
|
|
127
|
-
downloadImplementations({ contentLabels, headerLabels })
|
|
128
|
-
}
|
|
129
|
-
loading={ruleImplementationsDownloading}
|
|
130
|
-
/>
|
|
131
|
-
)}
|
|
132
|
-
{upload && <ImplementationsUploadButton />}
|
|
133
|
-
<ImplementationsUploadButton />
|
|
76
|
+
<RuleImplementationsOptions loading={ruleImplementationsLoading} />
|
|
134
77
|
</div>
|
|
135
78
|
);
|
|
136
79
|
};
|
|
137
80
|
|
|
138
81
|
RuleImplementationsActions.propTypes = {
|
|
139
82
|
addImplementationFilter: PropTypes.func,
|
|
140
|
-
downloadImplementations: PropTypes.func,
|
|
141
83
|
canExecute: PropTypes.bool,
|
|
142
84
|
createExecutionGroup: PropTypes.func,
|
|
143
85
|
executeImplementationsOn: PropTypes.bool,
|
|
@@ -148,23 +90,19 @@ RuleImplementationsActions.propTypes = {
|
|
|
148
90
|
selectedImplementations: PropTypes.array,
|
|
149
91
|
setMode: PropTypes.func,
|
|
150
92
|
toggleImplementationFilterValue: PropTypes.func,
|
|
151
|
-
ruleImplementationsDownloading: PropTypes.bool,
|
|
152
93
|
ruleImplementationsLoading: PropTypes.bool,
|
|
153
|
-
upload: PropTypes.bool,
|
|
154
94
|
};
|
|
155
95
|
|
|
156
96
|
const mapStateToProps = (state) => ({
|
|
157
97
|
canExecute: _.propOr(false, "userImplementationsPermissions.execute")(state),
|
|
158
98
|
ruleImplementationCount: state.ruleImplementationCount,
|
|
159
99
|
implementationsExecution: getImplementationsExecution(state),
|
|
160
|
-
ruleImplementationsDownloading: state.ruleImplementationsDownloading,
|
|
161
100
|
ruleImplementationsLoading: state.ruleImplementationsLoading,
|
|
162
101
|
});
|
|
163
102
|
|
|
164
103
|
export default connect(mapStateToProps, {
|
|
165
104
|
addImplementationFilter,
|
|
166
|
-
downloadImplementations,
|
|
167
105
|
toggleImplementationFilterValue,
|
|
168
106
|
removeImplementationFilter,
|
|
169
107
|
createExecutionGroup,
|
|
170
|
-
})(RuleImplementationsActions
|
|
108
|
+
})(RuleImplementationsActions);
|
|
@@ -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;
|
|
@@ -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);
|
|
@@ -8,7 +8,6 @@ jest.spyOn(React, "useContext").mockImplementation(() => intl);
|
|
|
8
8
|
|
|
9
9
|
describe("<RuleImplementationsActions />", () => {
|
|
10
10
|
const addImplementationFilter = jest.fn();
|
|
11
|
-
const downloadImplementations = jest.fn();
|
|
12
11
|
const toggleImplementationFilterValue = jest.fn();
|
|
13
12
|
const setMode = jest.fn();
|
|
14
13
|
const removeImplementationFilter = jest.fn();
|
|
@@ -17,9 +16,7 @@ describe("<RuleImplementationsActions />", () => {
|
|
|
17
16
|
executionGroupLoading: false,
|
|
18
17
|
ruleImplementationCount: 12,
|
|
19
18
|
implementationsExecution: true,
|
|
20
|
-
ruleImplementationsDownloading: false,
|
|
21
19
|
ruleImplementationsLoading: false,
|
|
22
|
-
downloadImplementations,
|
|
23
20
|
toggleImplementationFilterValue,
|
|
24
21
|
addImplementationFilter,
|
|
25
22
|
executeImplementationsOn: false,
|
|
@@ -31,12 +28,6 @@ describe("<RuleImplementationsActions />", () => {
|
|
|
31
28
|
expect(wrapper).toMatchSnapshot();
|
|
32
29
|
});
|
|
33
30
|
|
|
34
|
-
it("calls downloadImplementations on button click", () => {
|
|
35
|
-
const wrapper = shallow(<RuleImplementationsActions {...props} />);
|
|
36
|
-
wrapper.find("Button").simulate("click");
|
|
37
|
-
expect(downloadImplementations.mock.calls.length).toBe(1);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
31
|
it("as user with permissions I see execute implementations button and checkbox", () => {
|
|
41
32
|
const props = {
|
|
42
33
|
canExecute: true,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { shallow } from "enzyme";
|
|
4
|
+
import { intl } from "@truedat/test/intl-stub";
|
|
5
|
+
import { RuleImplementationsOptions } from "../RuleImplementationsOptions";
|
|
6
|
+
|
|
7
|
+
jest.spyOn(React, "useContext").mockImplementation(() => intl);
|
|
8
|
+
|
|
9
|
+
describe("<RuleImplementationsOptions />", () => {
|
|
10
|
+
it("matches the latest snapshot", () => {
|
|
11
|
+
const wrapper = shallow(<RuleImplementationsOptions />);
|
|
12
|
+
expect(wrapper).toMatchSnapshot();
|
|
13
|
+
});
|
|
14
|
+
it("matches the latest loading snapshot", () => {
|
|
15
|
+
const wrapper = shallow(<RuleImplementationsOptions loading />);
|
|
16
|
+
expect(wrapper).toMatchSnapshot();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { shallow } from "enzyme";
|
|
4
|
+
import { intl } from "@truedat/test/intl-stub";
|
|
5
|
+
import { RuleResultsUpload } from "../RuleResultsUpload";
|
|
6
|
+
|
|
7
|
+
jest.spyOn(React, "useContext").mockImplementation(() => intl);
|
|
8
|
+
|
|
9
|
+
describe("<RuleResultsUpload />", () => {
|
|
10
|
+
it("matches the latest snapshot", () => {
|
|
11
|
+
const props = {
|
|
12
|
+
uploadResults: jest.fn(),
|
|
13
|
+
loading: false,
|
|
14
|
+
};
|
|
15
|
+
const wrapper = shallow(<RuleResultsUpload {...props} />);
|
|
16
|
+
expect(wrapper).toMatchSnapshot();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -27,15 +27,8 @@ exports[`<RuleImplementationsActions /> matches the latest snapshot 1`] = `
|
|
|
27
27
|
disabled={true}
|
|
28
28
|
handleSubmit={[Function]}
|
|
29
29
|
/>
|
|
30
|
-
<
|
|
31
|
-
as="button"
|
|
32
|
-
data-tooltip="implementations.actions.download.tooltip"
|
|
33
|
-
floated="right"
|
|
34
|
-
icon="download"
|
|
30
|
+
<RuleImplementationsOptions
|
|
35
31
|
loading={false}
|
|
36
|
-
onClick={[Function]}
|
|
37
|
-
secondary={true}
|
|
38
32
|
/>
|
|
39
|
-
<Connect(ImplementationsUploadButton) />
|
|
40
33
|
</div>
|
|
41
34
|
`;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`<RuleImplementationsOptions /> matches the latest loading snapshot 1`] = `
|
|
4
|
+
<Dropdown
|
|
5
|
+
additionLabel="Add "
|
|
6
|
+
additionPosition="top"
|
|
7
|
+
className="button icon group-actions button-update"
|
|
8
|
+
closeOnBlur={true}
|
|
9
|
+
closeOnEscape={true}
|
|
10
|
+
deburr={false}
|
|
11
|
+
direction="left"
|
|
12
|
+
disabled={true}
|
|
13
|
+
floating={true}
|
|
14
|
+
icon="ellipsis vertical"
|
|
15
|
+
minCharacters={1}
|
|
16
|
+
noResultsMessage="No results found."
|
|
17
|
+
openOnFocus={true}
|
|
18
|
+
renderLabel={[Function]}
|
|
19
|
+
searchInput="text"
|
|
20
|
+
selectOnBlur={true}
|
|
21
|
+
selectOnNavigation={true}
|
|
22
|
+
wrapSelection={true}
|
|
23
|
+
>
|
|
24
|
+
<DropdownMenu>
|
|
25
|
+
<Connect(RuleImplementationsDownload) />
|
|
26
|
+
<Connect(ImplementationsUploadButton) />
|
|
27
|
+
<Connect(RuleResultsUpload) />
|
|
28
|
+
</DropdownMenu>
|
|
29
|
+
</Dropdown>
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
exports[`<RuleImplementationsOptions /> matches the latest snapshot 1`] = `
|
|
33
|
+
<Dropdown
|
|
34
|
+
additionLabel="Add "
|
|
35
|
+
additionPosition="top"
|
|
36
|
+
className="button icon group-actions button-update"
|
|
37
|
+
closeOnBlur={true}
|
|
38
|
+
closeOnEscape={true}
|
|
39
|
+
deburr={false}
|
|
40
|
+
direction="left"
|
|
41
|
+
floating={true}
|
|
42
|
+
icon="ellipsis vertical"
|
|
43
|
+
minCharacters={1}
|
|
44
|
+
noResultsMessage="No results found."
|
|
45
|
+
openOnFocus={true}
|
|
46
|
+
renderLabel={[Function]}
|
|
47
|
+
searchInput="text"
|
|
48
|
+
selectOnBlur={true}
|
|
49
|
+
selectOnNavigation={true}
|
|
50
|
+
wrapSelection={true}
|
|
51
|
+
>
|
|
52
|
+
<DropdownMenu>
|
|
53
|
+
<Connect(RuleImplementationsDownload) />
|
|
54
|
+
<Connect(ImplementationsUploadButton) />
|
|
55
|
+
<Connect(RuleResultsUpload) />
|
|
56
|
+
</DropdownMenu>
|
|
57
|
+
</Dropdown>
|
|
58
|
+
`;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`<RuleResultsUpload /> matches the latest snapshot 1`] = `
|
|
4
|
+
<UploadModal
|
|
5
|
+
content="uploadModal.actions.upload.confirmation.content"
|
|
6
|
+
handleSubmit={[Function]}
|
|
7
|
+
header="ruleResults.actions.upload.confirmation.header"
|
|
8
|
+
icon="upload"
|
|
9
|
+
param="rule_results"
|
|
10
|
+
trigger={
|
|
11
|
+
<DropdownItem
|
|
12
|
+
disabled={false}
|
|
13
|
+
icon="upload"
|
|
14
|
+
text="ruleResults.actions.upload.tooltip"
|
|
15
|
+
/>
|
|
16
|
+
}
|
|
17
|
+
/>
|
|
18
|
+
`;
|
package/src/messages/en.js
CHANGED
|
@@ -19,13 +19,14 @@ export default {
|
|
|
19
19
|
"createRule.error.domain_id.required": "Domain is required",
|
|
20
20
|
"createRuleImplementation.error.implementation_key.duplicated":
|
|
21
21
|
"Duplicated implementation key",
|
|
22
|
-
"createRule.error.rule_name_bc_id.unique_constraint":
|
|
22
|
+
"createRule.error.rule_name_bc_id.unique_constraint":
|
|
23
|
+
"Duplicated rule name. Edit name or associated business concept.",
|
|
23
24
|
"dataset.form.button.add_join.popup":
|
|
24
25
|
"Select both fields to add a new clause",
|
|
25
26
|
"dataset.form.button.add_structure": "Add Structure",
|
|
26
27
|
"datasetForm.implementation_key.tooltip":
|
|
27
28
|
"Leave empty for autogeneration of implementation key after saving implementation",
|
|
28
|
-
|
|
29
|
+
executionGroup: "Executions",
|
|
29
30
|
"executions.completed.content": "{count} executions completed.",
|
|
30
31
|
"executions.completed.header": "Executions completed",
|
|
31
32
|
"executions.pending.content":
|
|
@@ -53,9 +54,13 @@ export default {
|
|
|
53
54
|
"filtersGrid.field.operator": "Operator",
|
|
54
55
|
"filtersGrid.field.value": "Value",
|
|
55
56
|
"implementations.actions.do_execution": "Execute implementations",
|
|
56
|
-
"implementations.actions.download.tooltip": "Download
|
|
57
|
-
"implementations.actions.
|
|
58
|
-
|
|
57
|
+
"implementations.actions.download.tooltip": "Download with csv format",
|
|
58
|
+
"implementations.actions.download.empty":
|
|
59
|
+
"There are no Implementations to be downloaded",
|
|
60
|
+
"implementations.actions.execution.confirmation.content":
|
|
61
|
+
"{implementations_count} implementations will be executed. Are you sure?",
|
|
62
|
+
"implementations.actions.execution.confirmation.header":
|
|
63
|
+
"Implementations execution",
|
|
59
64
|
"implementations.actions.execution.confirmation.legend": "Template fields",
|
|
60
65
|
"implementations.execute.filtered": "{count} implementations to execute",
|
|
61
66
|
"implementations.search.placeholder": "Search implementations...",
|
|
@@ -118,7 +123,7 @@ export default {
|
|
|
118
123
|
"quality_result.under_minimum": "Under threshold",
|
|
119
124
|
"quality_result.under_minumum": "Under threshold",
|
|
120
125
|
"quality_result.failed": "Failed",
|
|
121
|
-
|
|
126
|
+
rule: "Quality Rule",
|
|
122
127
|
"rule.date.placeholder": "YYYY-MM-DD",
|
|
123
128
|
"rule.error.goal.required": "Goal required",
|
|
124
129
|
"rule.error.minimum.required": "Minimun threshold required",
|
|
@@ -456,7 +461,8 @@ export default {
|
|
|
456
461
|
"ruleImplementations.actions.edit": "Edit Implementation",
|
|
457
462
|
"ruleImplementations.actions.popup.deprecated": "Deprecated Implementations",
|
|
458
463
|
"ruleImplementations.actions.upload.tooltip": "Upload Implementations",
|
|
459
|
-
"ruleImplementations.actions.upload.confirmation.header":
|
|
464
|
+
"ruleImplementations.actions.upload.confirmation.header":
|
|
465
|
+
"Confirm bulk upload",
|
|
460
466
|
"ruleImplementations.header": "Quality Implementations",
|
|
461
467
|
"ruleImplementations.props.business_concept": "Concept",
|
|
462
468
|
"ruleImplementations.props.status": "Status",
|
|
@@ -492,11 +498,20 @@ export default {
|
|
|
492
498
|
"ruleImplementations.summary.headers.implementation": "Rule Implementation",
|
|
493
499
|
"ruleImplementations.summary.headers.population": "Population",
|
|
494
500
|
"ruleImplementations.summary.headers.validations": "Validation",
|
|
495
|
-
"ruleImplementations.upload.success.errors":
|
|
496
|
-
|
|
497
|
-
"ruleImplementations.upload.
|
|
501
|
+
"ruleImplementations.upload.success.errors":
|
|
502
|
+
"Error in {implementation_key} attribute: {key} message: {message} ",
|
|
503
|
+
"ruleImplementations.upload.success.header":
|
|
504
|
+
"Upload success! Loaded {count_ids} omitted {count_errors}:",
|
|
505
|
+
"ruleImplementations.upload.failed.header":
|
|
506
|
+
"Error uploading file. No rules have been created.",
|
|
498
507
|
"ruleImplementations.upload.failed.misssing_required_columns":
|
|
499
508
|
"Faltan columnas obligatorias en el fichero. Esperado [{expected}]. Recibido [{found}].",
|
|
509
|
+
"ruleResults.actions.upload.tooltip": "Upload rule results",
|
|
510
|
+
"ruleResults.actions.upload.confirmation.header": "Upload rule results",
|
|
511
|
+
"ruleResults.upload.success.header": "Upload successful!",
|
|
512
|
+
"ruleResults.upload.failed.header":
|
|
513
|
+
"Error uploading file. No results have been created.",
|
|
514
|
+
"ruleResults.upload.failed.content": "Error in line {row}.",
|
|
500
515
|
"ruleResult.props.header.information": "Information",
|
|
501
516
|
"ruleResult.props.header.details": "Details",
|
|
502
517
|
"ruleResult.props.date": "Date",
|
|
@@ -519,9 +534,12 @@ export default {
|
|
|
519
534
|
"rules.retrieved.results": "{count} rules found",
|
|
520
535
|
"rules.search.placeholder": "Search rules...",
|
|
521
536
|
"rules.searching": "Searching...",
|
|
522
|
-
"rules.upload.success.errors":
|
|
523
|
-
|
|
524
|
-
"rules.upload.
|
|
537
|
+
"rules.upload.success.errors":
|
|
538
|
+
"Error in {rule_name} attribute: {key} message: {message} ",
|
|
539
|
+
"rules.upload.success.header":
|
|
540
|
+
"Upload successful! Loaded {count_ids} omitted {count_errors}:",
|
|
541
|
+
"rules.upload.failed.header":
|
|
542
|
+
"Error uploading file. No rules have been created.",
|
|
525
543
|
"rules.upload.failed.misssing_required_columns":
|
|
526
544
|
"Missing required columns. Expected [{expected}]. Found [{found}].",
|
|
527
545
|
"structureFields.dropdown.label": "Select Field",
|
package/src/messages/es.js
CHANGED
|
@@ -19,13 +19,14 @@ export default {
|
|
|
19
19
|
"createRule.error.domain_id.required": "Dominio es requerido",
|
|
20
20
|
"createRuleImplementation.error.implementation_key.duplicated":
|
|
21
21
|
"Identificador duplicado",
|
|
22
|
-
"createRule.error.rule_name_bc_id.unique_constraint":
|
|
22
|
+
"createRule.error.rule_name_bc_id.unique_constraint":
|
|
23
|
+
"La regla ya existe con ese nombre o concepto asociado",
|
|
23
24
|
"dataset.form.button.add_join.popup":
|
|
24
25
|
"Seleccionar ambos campos para añadir una nueva cláusula",
|
|
25
26
|
"dataset.form.button.add_structure": "Añadir Estructura",
|
|
26
27
|
"datasetForm.implementation_key.tooltip":
|
|
27
28
|
"En caso de no introducir clave de implementación, se autogenerará al guardar la implementación",
|
|
28
|
-
|
|
29
|
+
executionGroup: "Ejecuciones",
|
|
29
30
|
"executions.completed.content": "Se han ejecutado {count} implementaciones.",
|
|
30
31
|
"executions.completed.header": "Ejecuciones finalizadas",
|
|
31
32
|
"executions.pending.content":
|
|
@@ -53,10 +54,15 @@ export default {
|
|
|
53
54
|
"filtersGrid.field.operator": "Operador",
|
|
54
55
|
"filtersGrid.field.value": "Valor",
|
|
55
56
|
"implementations.actions.do_execution": "Ejecutar implementaciones",
|
|
56
|
-
"implementations.actions.download.tooltip": "Descargar en csv",
|
|
57
|
-
"implementations.actions.
|
|
58
|
-
|
|
59
|
-
"implementations.actions.execution.confirmation.
|
|
57
|
+
"implementations.actions.download.tooltip": "Descargar en formato csv",
|
|
58
|
+
"implementations.actions.download.empty":
|
|
59
|
+
"No hay implementaciones para descargar",
|
|
60
|
+
"implementations.actions.execution.confirmation.content":
|
|
61
|
+
"Se va a solicitar la ejecución de {implementations_count} implementaciones. ¿Estás seguro?",
|
|
62
|
+
"implementations.actions.execution.confirmation.header":
|
|
63
|
+
"Solicitar ejecución de implementaciones",
|
|
64
|
+
"implementations.actions.execution.confirmation.legend":
|
|
65
|
+
"Campos de la plantilla",
|
|
60
66
|
"implementations.execute.filtered": "{count} implementaciones a ejecutar",
|
|
61
67
|
"implementations.search.placeholder": "Buscar implementaciones...",
|
|
62
68
|
"navigation.quality.rules": "Reglas",
|
|
@@ -214,7 +220,7 @@ export default {
|
|
|
214
220
|
"rule.type.numeric_format": "Tiene formato numérico",
|
|
215
221
|
"rule.type.unique_values": "Tiene valores únicos",
|
|
216
222
|
"rule.values_list": "Valores de la lista",
|
|
217
|
-
|
|
223
|
+
rule: "Regla de Calidad",
|
|
218
224
|
"ruleImplementation.action.deprecate": "archivada",
|
|
219
225
|
"ruleImplementation.actions.clone": "Clonar implementación",
|
|
220
226
|
"ruleImplementation.actions.delete.confirmation.content":
|
|
@@ -235,7 +241,8 @@ export default {
|
|
|
235
241
|
"Restaurar Implementación",
|
|
236
242
|
"ruleImplementation.actions.restore": "Restaurar Implementación",
|
|
237
243
|
"ruleImplementations.actions.upload.tooltip": "Subir Implementaciones",
|
|
238
|
-
"ruleImplementations.actions.upload.confirmation.header":
|
|
244
|
+
"ruleImplementations.actions.upload.confirmation.header":
|
|
245
|
+
"Subir ficheros de implementaciones",
|
|
239
246
|
"ruleImplementation.column.placeholder": "Seleccionar columna",
|
|
240
247
|
"ruleImplementation.column": "Columna",
|
|
241
248
|
"ruleImplementation.delete.folder": '"Eliminado"',
|
|
@@ -509,13 +516,21 @@ export default {
|
|
|
509
516
|
"Implementación de una Regla",
|
|
510
517
|
"ruleImplementations.summary.headers.population": "Población",
|
|
511
518
|
"ruleImplementations.summary.headers.validations": "Validaciones",
|
|
512
|
-
"ruleImplementations.upload.success.errors":
|
|
513
|
-
|
|
514
|
-
"ruleImplementations.upload.
|
|
519
|
+
"ruleImplementations.upload.success.errors":
|
|
520
|
+
"Error en {name} atributo: {key} mensaje: {message} ",
|
|
521
|
+
"ruleImplementations.upload.success.header":
|
|
522
|
+
"¡Fichero subido correctamente! subidos {count_ids} errores {count_errors}:",
|
|
523
|
+
"ruleImplementations.upload.failed.header":
|
|
524
|
+
"Error al subir el fichero. No se ha realizado ninguna inserción.",
|
|
515
525
|
"ruleImplementations.upload.failed.misssing_required_columns":
|
|
516
526
|
"Faltan columnas obligatorias en el fichero. Esperado [{expected}]. Recibido [{found}].",
|
|
517
|
-
|
|
518
|
-
|
|
527
|
+
"ruleResults.actions.upload.tooltip": "Subir resultados",
|
|
528
|
+
"ruleResults.actions.upload.confirmation.header":
|
|
529
|
+
"Subir resultados de implementaciones",
|
|
530
|
+
"ruleResults.upload.success.header": "¡Fichero subido correctamente!",
|
|
531
|
+
"ruleResults.upload.failed.header":
|
|
532
|
+
"Error al subir fichero. No se ha realizado ninguna inserción.",
|
|
533
|
+
"ruleResults.upload.failed.content": "Error en la línea {row}.",
|
|
519
534
|
"ruleResult.props.date": "Fecha",
|
|
520
535
|
"ruleResult.props.details": "Detalles",
|
|
521
536
|
"ruleResult.props.errors": "Errores",
|
|
@@ -534,9 +549,12 @@ export default {
|
|
|
534
549
|
"rules.retrieved.results": "{count} reglas encontradas",
|
|
535
550
|
"rules.search.placeholder": "Buscar reglas...",
|
|
536
551
|
"rules.searching": "Buscando...",
|
|
537
|
-
"rules.upload.success.errors":
|
|
538
|
-
|
|
539
|
-
"rules.upload.
|
|
552
|
+
"rules.upload.success.errors":
|
|
553
|
+
"Error en {rule_name} atributo: {key} mensaje: {message} ",
|
|
554
|
+
"rules.upload.success.header":
|
|
555
|
+
"¡Fichero subido correctamente! subidos {count_ids} errores {count_errors}:",
|
|
556
|
+
"rules.upload.failed.header":
|
|
557
|
+
"Error al subir el fichero. No se ha realizado ninguna inserción.",
|
|
540
558
|
"rules.upload.failed.misssing_required_columns":
|
|
541
559
|
"Faltan columnas obligatorias en el fichero. Esperado [{expected}]. Recibido [{found}].",
|
|
542
560
|
"ruleSubscription.actions.remove": "Eliminar",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { uploadResults } from "../../routines";
|
|
2
|
+
import { uploadingResults } from "..";
|
|
3
|
+
|
|
4
|
+
const fooState = { foo: "bar" };
|
|
5
|
+
|
|
6
|
+
const initialState = false;
|
|
7
|
+
|
|
8
|
+
describe("reducers: previousRuleImplementationQuery", () => {
|
|
9
|
+
it("should provide the initial state", () => {
|
|
10
|
+
expect(uploadingResults(undefined, {})).toEqual(initialState);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should handle the uploadResults.TRIGGER action", () => {
|
|
14
|
+
expect(
|
|
15
|
+
uploadingResults(fooState, {
|
|
16
|
+
type: uploadResults.TRIGGER,
|
|
17
|
+
})
|
|
18
|
+
).toBeTruthy();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should handle the uploadResults.FULFILL action", () => {
|
|
22
|
+
expect(
|
|
23
|
+
uploadingResults(fooState, {
|
|
24
|
+
type: uploadResults.FULFILL,
|
|
25
|
+
})
|
|
26
|
+
).toBeFalsy();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import { dismissAlert } from "@truedat/core/routines";
|
|
3
|
-
import { uploadRules, uploadImplementations } from "../routines";
|
|
3
|
+
import { uploadRules, uploadImplementations, uploadResults } from "../routines";
|
|
4
4
|
|
|
5
5
|
const initialState = {};
|
|
6
6
|
|
|
@@ -95,6 +95,27 @@ const dqMessage = (state = initialState, { type, payload }) => {
|
|
|
95
95
|
} else {
|
|
96
96
|
return null;
|
|
97
97
|
}
|
|
98
|
+
case uploadResults.SUCCESS:
|
|
99
|
+
return {
|
|
100
|
+
error: false,
|
|
101
|
+
header: "ruleResults.upload.success.header",
|
|
102
|
+
icon: "check",
|
|
103
|
+
color: "green",
|
|
104
|
+
text: "",
|
|
105
|
+
};
|
|
106
|
+
case uploadResults.FAILURE:
|
|
107
|
+
if (payload.status != 500) {
|
|
108
|
+
return {
|
|
109
|
+
error: true,
|
|
110
|
+
header: "ruleResults.upload.failed.header",
|
|
111
|
+
content: `ruleResults.upload.failed.content`,
|
|
112
|
+
icon: "attention",
|
|
113
|
+
text: "",
|
|
114
|
+
fields: { row: _.path("data.row")(payload) },
|
|
115
|
+
};
|
|
116
|
+
} else {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
98
119
|
|
|
99
120
|
default:
|
|
100
121
|
return state;
|
package/src/reducers/index.js
CHANGED
|
@@ -42,6 +42,7 @@ import { uploadRulesFile } from "./uploadRulesFile";
|
|
|
42
42
|
import { userRulePermissions } from "./userRulePermissions";
|
|
43
43
|
import { userRulesPermissions } from "./userRulesPermissions";
|
|
44
44
|
import { userImplementationsPermissions } from "./userImplementationsPermissions";
|
|
45
|
+
import { uploadingResults } from "./uploadingResults";
|
|
45
46
|
|
|
46
47
|
export {
|
|
47
48
|
conceptRules,
|
|
@@ -88,4 +89,5 @@ export {
|
|
|
88
89
|
userRulePermissions,
|
|
89
90
|
userRulesPermissions,
|
|
90
91
|
userImplementationsPermissions,
|
|
92
|
+
uploadingResults,
|
|
91
93
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { uploadResults } from "../routines";
|
|
2
|
+
|
|
3
|
+
const initialState = false;
|
|
4
|
+
|
|
5
|
+
export const uploadingResults = (state = initialState, { type }) => {
|
|
6
|
+
switch (type) {
|
|
7
|
+
case uploadResults.TRIGGER:
|
|
8
|
+
return true;
|
|
9
|
+
case uploadResults.FULFILL:
|
|
10
|
+
return false;
|
|
11
|
+
default:
|
|
12
|
+
return state;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default uploadingResults;
|
package/src/routines.js
CHANGED
|
@@ -89,6 +89,7 @@ export const openImplementationFilter = createRoutine(
|
|
|
89
89
|
export const downloadImplementations = createRoutine(
|
|
90
90
|
"DOWNLOAD_IMPLEMENTATIONS"
|
|
91
91
|
);
|
|
92
|
+
export const uploadResults = createRoutine("UPLOAD_RESULTS");
|
|
92
93
|
export const createExecutionGroup = createRoutine("CREATE_EXECUTION_GROUP");
|
|
93
94
|
export const fetchExecutionGroup = createRoutine("FETCH_EXECUTION_GROUP");
|
|
94
95
|
export const clearExecutionGroup = createRoutine("CLEAR_EXECUTION_GROUP");
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { testSaga } from "redux-saga-test-plan";
|
|
2
|
+
import { apiJsonPost, UPLOAD_JSON_OPTS } from "@truedat/core/services/api";
|
|
3
|
+
import { uploadResultsRequestSaga, uploadResultsSaga } from "../uploadResults";
|
|
4
|
+
import { uploadResults } from "../../routines";
|
|
5
|
+
import { API_RULE_RESULTS } from "../../api";
|
|
6
|
+
|
|
7
|
+
describe("sagas: uploadResultsRequestSaga", () => {
|
|
8
|
+
it("should invoke uploadResultsSaga on trigger", () => {
|
|
9
|
+
expect(() => {
|
|
10
|
+
testSaga(uploadResultsRequestSaga)
|
|
11
|
+
.next()
|
|
12
|
+
.takeLatest(uploadResults.TRIGGER, uploadResultsSaga)
|
|
13
|
+
.finish()
|
|
14
|
+
.isDone();
|
|
15
|
+
}).not.toThrow();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should throw exception if an unhandled action is received", () => {
|
|
19
|
+
expect(() => {
|
|
20
|
+
testSaga(uploadResultsRequestSaga)
|
|
21
|
+
.next()
|
|
22
|
+
.takeLatest("FOO", uploadResultsSaga);
|
|
23
|
+
}).toThrow();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("sagas: uploadResultsSaga", () => {
|
|
28
|
+
const body = { rule_results: "content" };
|
|
29
|
+
const payload = { data: body };
|
|
30
|
+
const data = { message: [1, 2] };
|
|
31
|
+
it("should put a success action when a response is returned", () => {
|
|
32
|
+
expect(() => {
|
|
33
|
+
testSaga(uploadResultsSaga, { payload })
|
|
34
|
+
.next()
|
|
35
|
+
.put(uploadResults.request())
|
|
36
|
+
.next()
|
|
37
|
+
.call(apiJsonPost, API_RULE_RESULTS, body, UPLOAD_JSON_OPTS)
|
|
38
|
+
.next({ data })
|
|
39
|
+
.put(uploadResults.success(data))
|
|
40
|
+
.next()
|
|
41
|
+
.put(uploadResults.fulfill())
|
|
42
|
+
.next()
|
|
43
|
+
.isDone();
|
|
44
|
+
}).not.toThrow();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should put a failure action when the call returns an error", () => {
|
|
48
|
+
const message = "Request failed";
|
|
49
|
+
const error = { message };
|
|
50
|
+
|
|
51
|
+
expect(() => {
|
|
52
|
+
testSaga(uploadResultsSaga, { payload })
|
|
53
|
+
.next()
|
|
54
|
+
.put(uploadResults.request())
|
|
55
|
+
.next()
|
|
56
|
+
.call(apiJsonPost, API_RULE_RESULTS, body, UPLOAD_JSON_OPTS)
|
|
57
|
+
.throw(error)
|
|
58
|
+
.put(uploadResults.failure(message))
|
|
59
|
+
.next()
|
|
60
|
+
.put(uploadResults.fulfill())
|
|
61
|
+
.next()
|
|
62
|
+
.isDone();
|
|
63
|
+
}).not.toThrow();
|
|
64
|
+
});
|
|
65
|
+
});
|
package/src/sagas/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { uploadImplementationsRequestsSaga } from "./uploadImplementations";
|
|
|
18
18
|
import { uploadRulesRequestsSaga } from "./uploadRules";
|
|
19
19
|
import { updateRuleImplementationRequestSaga } from "./updateRuleImplementation";
|
|
20
20
|
import { updateRuleRequestSaga } from "./updateRule";
|
|
21
|
+
import { uploadResultsRequestSaga } from "./uploadResults";
|
|
21
22
|
|
|
22
23
|
export {
|
|
23
24
|
createExecutionGroupRequestSaga,
|
|
@@ -40,6 +41,7 @@ export {
|
|
|
40
41
|
uploadImplementationsRequestsSaga,
|
|
41
42
|
updateRuleImplementationRequestSaga,
|
|
42
43
|
updateRuleRequestSaga,
|
|
44
|
+
uploadResultsRequestSaga,
|
|
43
45
|
};
|
|
44
46
|
|
|
45
47
|
export default [
|
|
@@ -63,4 +65,5 @@ export default [
|
|
|
63
65
|
uploadImplementationsRequestsSaga(),
|
|
64
66
|
updateRuleImplementationRequestSaga(),
|
|
65
67
|
updateRuleRequestSaga(),
|
|
68
|
+
uploadResultsRequestSaga(),
|
|
66
69
|
];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { call, put, takeLatest } from "redux-saga/effects";
|
|
2
|
+
import { apiJsonPost, UPLOAD_JSON_OPTS } from "@truedat/core/services/api";
|
|
3
|
+
import { uploadResults } from "../routines";
|
|
4
|
+
import { API_RULE_RESULTS } from "../api";
|
|
5
|
+
|
|
6
|
+
export function* uploadResultsSaga({ payload }) {
|
|
7
|
+
try {
|
|
8
|
+
const { data: body } = payload;
|
|
9
|
+
yield put(uploadResults.request());
|
|
10
|
+
const { data } = yield call(
|
|
11
|
+
apiJsonPost,
|
|
12
|
+
API_RULE_RESULTS,
|
|
13
|
+
body,
|
|
14
|
+
UPLOAD_JSON_OPTS
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
yield put(uploadResults.success(data));
|
|
18
|
+
} catch (error) {
|
|
19
|
+
if (error.response) {
|
|
20
|
+
const { status, data } = error.response;
|
|
21
|
+
yield put(uploadResults.failure({ status, data }));
|
|
22
|
+
} else {
|
|
23
|
+
yield put(uploadResults.failure(error.message));
|
|
24
|
+
}
|
|
25
|
+
} finally {
|
|
26
|
+
yield put(uploadResults.fulfill());
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function* uploadResultsRequestSaga() {
|
|
31
|
+
yield takeLatest(uploadResults.TRIGGER, uploadResultsSaga);
|
|
32
|
+
}
|