@truedat/dq 4.44.5 → 4.45.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 +6 -0
- package/package.json +5 -5
- package/src/components/ImplementationsRoutes.js +2 -0
- package/src/components/Rule.js +2 -2
- package/src/components/RuleImplementation.js +5 -0
- package/src/components/RuleSubscriptionLoader.js +5 -3
- package/src/components/{RuleSubscription.js → Subscription.js} +65 -36
- package/src/components/__tests__/{RuleSubscription.spec.js → Subscription.spec.js} +18 -20
- package/src/components/__tests__/__snapshots__/Rule.spec.js.snap +9 -1
- package/src/components/__tests__/__snapshots__/RuleImplementation.spec.js.snap +9 -0
- package/src/components/__tests__/__snapshots__/{RuleSubscription.spec.js.snap → Subscription.spec.js.snap} +3 -3
- package/src/reducers/ruleImplementationRedirect.js +15 -1
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dq",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.45.2",
|
|
4
4
|
"description": "Truedat Web Data Quality Module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@testing-library/jest-dom": "^5.16.4",
|
|
35
35
|
"@testing-library/react": "^12.0.0",
|
|
36
36
|
"@testing-library/user-event": "^13.2.1",
|
|
37
|
-
"@truedat/test": "4.
|
|
37
|
+
"@truedat/test": "4.45.1",
|
|
38
38
|
"babel-jest": "^28.1.0",
|
|
39
39
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
40
40
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
90
|
"@apollo/client": "^3.6.4",
|
|
91
|
-
"@truedat/core": "4.
|
|
92
|
-
"@truedat/df": "4.
|
|
91
|
+
"@truedat/core": "4.45.1",
|
|
92
|
+
"@truedat/df": "4.45.1",
|
|
93
93
|
"axios": "^0.19.2",
|
|
94
94
|
"graphql": "^15.5.3",
|
|
95
95
|
"path-to-regexp": "^1.7.0",
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
"react-dom": ">= 16.8.6 < 17",
|
|
111
111
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
112
112
|
},
|
|
113
|
-
"gitHead": "
|
|
113
|
+
"gitHead": "94be41b427aa71f91b2e98a7af622ab2453b2b97"
|
|
114
114
|
}
|
|
@@ -44,6 +44,7 @@ import RuleImplementationResults from "./RuleImplementationResults";
|
|
|
44
44
|
import RuleResultDetails from "./RuleResultDetails";
|
|
45
45
|
import RuleResultsRoutes from "./RuleResultsRoutes";
|
|
46
46
|
import RuleResultRemediationLoader from "./RuleResultRemediationLoader";
|
|
47
|
+
import RuleSubscriptionLoader from "./RuleSubscriptionLoader";
|
|
47
48
|
|
|
48
49
|
const TemplatesLoader = React.lazy(() =>
|
|
49
50
|
import("@truedat/df/templates/components/TemplatesLoader")
|
|
@@ -131,6 +132,7 @@ const ImplementationsRoutes = ({
|
|
|
131
132
|
render={() => (
|
|
132
133
|
<>
|
|
133
134
|
<RuleImplementationLoader />
|
|
135
|
+
<RuleSubscriptionLoader />
|
|
134
136
|
|
|
135
137
|
<Route
|
|
136
138
|
exact
|
package/src/components/Rule.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Header, Icon, Grid } from "semantic-ui-react";
|
|
|
5
5
|
import { connect } from "react-redux";
|
|
6
6
|
import RuleTabs from "./RuleTabs";
|
|
7
7
|
import RuleActions from "./RuleActions";
|
|
8
|
-
import
|
|
8
|
+
import Subscription from "./Subscription";
|
|
9
9
|
import RuleSummary from "./RuleSummary";
|
|
10
10
|
|
|
11
11
|
export const Rule = ({ rule, userRulePermissions, implementations }) => {
|
|
@@ -22,7 +22,7 @@ export const Rule = ({ rule, userRulePermissions, implementations }) => {
|
|
|
22
22
|
</Header>
|
|
23
23
|
</Grid.Column>
|
|
24
24
|
<Grid.Column width={8} textAlign="right">
|
|
25
|
-
<
|
|
25
|
+
<Subscription resource={rule} resourceType="rule" />
|
|
26
26
|
{_.prop("manage_quality_rules")(userRulePermissions) && (
|
|
27
27
|
<RuleActions />
|
|
28
28
|
)}
|
|
@@ -12,6 +12,7 @@ import { createExecutionGroup, setRuleImplementationStatus } from "../routines";
|
|
|
12
12
|
import RuleImplementationTabs from "./RuleImplementationTabs";
|
|
13
13
|
import ImplementationResultBar from "./ImplementationResultBar";
|
|
14
14
|
import ExecutionPopup from "./ExecutionPopup";
|
|
15
|
+
import Subscription from "./Subscription";
|
|
15
16
|
|
|
16
17
|
const getAvailableActions = (props, formatMessage) => {
|
|
17
18
|
const contentActions = _.isEmpty(props?.ruleImplementation)
|
|
@@ -202,6 +203,10 @@ export const RuleImplementation = ({
|
|
|
202
203
|
{canExecute && ruleImplementation.executable ? (
|
|
203
204
|
<ExecutionPopup onSubmit={handleSubmit} count={1} />
|
|
204
205
|
) : null}
|
|
206
|
+
<Subscription
|
|
207
|
+
resource={ruleImplementation}
|
|
208
|
+
resourceType="implementation"
|
|
209
|
+
/>
|
|
205
210
|
{deletedAt && (
|
|
206
211
|
<Label
|
|
207
212
|
className="alert warning"
|
|
@@ -12,13 +12,15 @@ export const RuleSubscriptionLoader = ({
|
|
|
12
12
|
clearSubscriptionsSearch,
|
|
13
13
|
searchSubscriptions,
|
|
14
14
|
}) => {
|
|
15
|
-
const { id } = useParams();
|
|
15
|
+
const { id, implementation_id } = useParams();
|
|
16
|
+
|
|
16
17
|
useEffect(() => {
|
|
17
18
|
const payload = {
|
|
18
|
-
resource_id: _.toInteger(id),
|
|
19
|
+
resource_id: _.toInteger(id || implementation_id),
|
|
19
20
|
events: ["rule_result_created"],
|
|
20
|
-
resource_type: "rule",
|
|
21
|
+
resource_type: id ? "rule" : implementation_id ? "implementation" : "",
|
|
21
22
|
};
|
|
23
|
+
|
|
22
24
|
searchSubscriptions(payload);
|
|
23
25
|
return () => {
|
|
24
26
|
clearSubscriptionsSearch();
|
|
@@ -7,19 +7,19 @@ import { FormattedMessage, useIntl } from "react-intl";
|
|
|
7
7
|
import {
|
|
8
8
|
createSubscription,
|
|
9
9
|
deleteSubscription,
|
|
10
|
-
updateSubscription
|
|
10
|
+
updateSubscription,
|
|
11
11
|
} from "@truedat/core/routines";
|
|
12
12
|
|
|
13
13
|
const SubscriptionWatchForm = React.lazy(() =>
|
|
14
14
|
import("@truedat/audit/components/SubscriptionWatchForm")
|
|
15
15
|
);
|
|
16
16
|
|
|
17
|
-
export const
|
|
17
|
+
export const SubscriptionContent = ({ subscription, setSubscription }) => {
|
|
18
18
|
const statuses = _.path("scope.status")(subscription) || [];
|
|
19
19
|
|
|
20
20
|
const handleEventTypeChange = (_e, { name }) => {
|
|
21
21
|
const statuses_m = _.includes(name)(statuses)
|
|
22
|
-
? _.reject(event => event == name)(statuses)
|
|
22
|
+
? _.reject((event) => event == name)(statuses)
|
|
23
23
|
: _.concat([name])(statuses);
|
|
24
24
|
setSubscription({ ...subscription, scope: { status: statuses_m } });
|
|
25
25
|
};
|
|
@@ -67,25 +67,31 @@ export const RuleSubscriptionContent = ({ subscription, setSubscription }) => {
|
|
|
67
67
|
);
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
SubscriptionContent.propTypes = {
|
|
71
71
|
subscription: PropTypes.object,
|
|
72
|
-
setSubscription: PropTypes.func
|
|
72
|
+
setSubscription: PropTypes.func,
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
-
export const
|
|
76
|
-
|
|
75
|
+
export const Subscription = ({
|
|
76
|
+
resource,
|
|
77
|
+
resourceType,
|
|
77
78
|
searchSubscription,
|
|
78
79
|
createSubscription,
|
|
79
80
|
updateSubscription,
|
|
80
81
|
deleteSubscription,
|
|
81
|
-
subscriptionUpdating
|
|
82
|
+
subscriptionUpdating,
|
|
82
83
|
}) => {
|
|
83
84
|
const [subscriptionField, setSubscription] = useState(searchSubscription);
|
|
85
|
+
const [resourceTypeId, setResourceTypeId] = useState();
|
|
84
86
|
|
|
85
87
|
useEffect(() => {
|
|
86
88
|
setSubscription(searchSubscription);
|
|
87
89
|
}, [searchSubscription]);
|
|
88
90
|
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
setResourceTypeId(getResourceTypeId(resource, resourceType));
|
|
93
|
+
}, [resource, resourceType]);
|
|
94
|
+
|
|
89
95
|
const { formatMessage } = useIntl();
|
|
90
96
|
const subscribed = !_.isEmpty(searchSubscription);
|
|
91
97
|
|
|
@@ -97,28 +103,53 @@ export const RuleSubscription = ({
|
|
|
97
103
|
|
|
98
104
|
const handleSubmit = () => {
|
|
99
105
|
const payload = {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
...{
|
|
107
|
+
subscription: {
|
|
108
|
+
...subscriptionField,
|
|
109
|
+
scope: {
|
|
110
|
+
resource_id: _.prop("id")(resource),
|
|
111
|
+
resource_name: resourceName(resource, resourceType), // implementation?.implementation_key,
|
|
112
|
+
resource_type: resourceType,
|
|
113
|
+
events: ["rule_result_created"],
|
|
114
|
+
status: _.path("scope.status")(subscriptionField),
|
|
115
|
+
},
|
|
116
|
+
},
|
|
108
117
|
},
|
|
109
|
-
|
|
118
|
+
...resourceTypeId,
|
|
110
119
|
};
|
|
111
120
|
|
|
112
121
|
_.prop("id")(subscriptionField)
|
|
113
122
|
? updateSubscription(payload)
|
|
114
123
|
: createSubscription(payload);
|
|
115
124
|
};
|
|
125
|
+
|
|
126
|
+
const resourceName = (resource, resourceType) => {
|
|
127
|
+
switch (resourceType) {
|
|
128
|
+
case "implementation":
|
|
129
|
+
return resource.implementation_key;
|
|
130
|
+
case "rule":
|
|
131
|
+
return resource.name;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const getResourceTypeId = (resource, resourceType) => {
|
|
136
|
+
const id = _.prop("id")(resource);
|
|
137
|
+
switch (resourceType) {
|
|
138
|
+
case "implementation":
|
|
139
|
+
return { implementation_id: id };
|
|
140
|
+
case "rule":
|
|
141
|
+
return { rule_id: id };
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
116
145
|
const handleDelete = () => {
|
|
117
146
|
const payload = {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
147
|
+
...{
|
|
148
|
+
subscription: subscriptionField,
|
|
149
|
+
resource_id: _.prop("id")(resource),
|
|
150
|
+
resource_type: resourceType,
|
|
151
|
+
},
|
|
152
|
+
...resourceTypeId,
|
|
122
153
|
};
|
|
123
154
|
_.prop("id")(subscriptionField) && deleteSubscription(payload);
|
|
124
155
|
};
|
|
@@ -156,7 +187,7 @@ export const RuleSubscription = ({
|
|
|
156
187
|
handleDelete={handleDelete}
|
|
157
188
|
subscriptionUpdating={subscriptionUpdating}
|
|
158
189
|
>
|
|
159
|
-
<
|
|
190
|
+
<SubscriptionContent
|
|
160
191
|
subscription={subscriptionField}
|
|
161
192
|
setSubscription={setSubscription}
|
|
162
193
|
/>
|
|
@@ -166,29 +197,27 @@ export const RuleSubscription = ({
|
|
|
166
197
|
);
|
|
167
198
|
};
|
|
168
199
|
|
|
169
|
-
|
|
200
|
+
Subscription.propTypes = {
|
|
170
201
|
createSubscription: PropTypes.func,
|
|
171
202
|
updateSubscription: PropTypes.func,
|
|
172
203
|
deleteSubscription: PropTypes.func,
|
|
173
204
|
searchSubscription: PropTypes.object,
|
|
174
|
-
|
|
175
|
-
|
|
205
|
+
resource: PropTypes.object,
|
|
206
|
+
resourceType: PropTypes.string,
|
|
207
|
+
subscriptionUpdating: PropTypes.bool,
|
|
176
208
|
};
|
|
177
209
|
|
|
178
|
-
export const mapStateToProps = ({
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
searchSubscription,
|
|
185
|
-
subscriptionUpdating
|
|
186
|
-
});
|
|
210
|
+
export const mapStateToProps = (state) => {
|
|
211
|
+
return {
|
|
212
|
+
searchSubscription: state.searchSubscription,
|
|
213
|
+
subscriptionUpdating: state.subscriptionUpdating,
|
|
214
|
+
};
|
|
215
|
+
};
|
|
187
216
|
|
|
188
217
|
const mapDispatchToProps = {
|
|
189
218
|
createSubscription,
|
|
190
219
|
updateSubscription,
|
|
191
|
-
deleteSubscription
|
|
220
|
+
deleteSubscription,
|
|
192
221
|
};
|
|
193
222
|
|
|
194
|
-
export default connect(mapStateToProps, mapDispatchToProps)(
|
|
223
|
+
export default connect(mapStateToProps, mapDispatchToProps)(Subscription);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { intl } from "@truedat/test/intl-stub";
|
|
3
3
|
import { shallow } from "enzyme";
|
|
4
|
-
import {
|
|
4
|
+
import { Subscription, SubscriptionContent } from "../Subscription";
|
|
5
5
|
|
|
6
6
|
// workaround for enzyme issue with React.useContext
|
|
7
7
|
// see https://github.com/airbnb/enzyme/issues/2176#issuecomment-532361526
|
|
8
8
|
jest.spyOn(React, "useContext").mockImplementation(() => intl);
|
|
9
9
|
|
|
10
|
-
describe("<
|
|
10
|
+
describe("<SubscriptionContent />", () => {
|
|
11
11
|
const subscription = {
|
|
12
12
|
id: 2,
|
|
13
13
|
periodicity: "daily",
|
|
@@ -15,22 +15,22 @@ describe("<RuleSubscriptionContent />", () => {
|
|
|
15
15
|
status: ["warn"],
|
|
16
16
|
events: ["rule_result_created"],
|
|
17
17
|
resource_id: 2,
|
|
18
|
-
resource_type: "rule"
|
|
18
|
+
resource_type: "rule",
|
|
19
19
|
},
|
|
20
20
|
subscriber: {
|
|
21
21
|
id: 3,
|
|
22
22
|
identifier: "2",
|
|
23
|
-
type: "user"
|
|
24
|
-
}
|
|
23
|
+
type: "user",
|
|
24
|
+
},
|
|
25
25
|
};
|
|
26
26
|
const setSubscription = jest.fn();
|
|
27
27
|
|
|
28
28
|
it("matches the latest snapshot", () => {
|
|
29
29
|
const props = {
|
|
30
30
|
subscription,
|
|
31
|
-
setSubscription
|
|
31
|
+
setSubscription,
|
|
32
32
|
};
|
|
33
|
-
const wrapper = shallow(<
|
|
33
|
+
const wrapper = shallow(<SubscriptionContent {...props} />);
|
|
34
34
|
expect(wrapper).toMatchSnapshot();
|
|
35
35
|
});
|
|
36
36
|
|
|
@@ -39,18 +39,15 @@ describe("<RuleSubscriptionContent />", () => {
|
|
|
39
39
|
const name = "success";
|
|
40
40
|
const props = {
|
|
41
41
|
subscription,
|
|
42
|
-
setSubscription
|
|
42
|
+
setSubscription,
|
|
43
43
|
};
|
|
44
|
-
const wrapper = shallow(<
|
|
45
|
-
wrapper
|
|
46
|
-
.find("FormCheckbox")
|
|
47
|
-
.at(0)
|
|
48
|
-
.simulate("change", e, { name });
|
|
44
|
+
const wrapper = shallow(<SubscriptionContent {...props} />);
|
|
45
|
+
wrapper.find("FormCheckbox").at(0).simulate("change", e, { name });
|
|
49
46
|
expect(setSubscription.mock.calls.length).toBe(1);
|
|
50
47
|
});
|
|
51
48
|
});
|
|
52
49
|
|
|
53
|
-
describe("<
|
|
50
|
+
describe("<Subscription />", () => {
|
|
54
51
|
const rule = { id: 1 };
|
|
55
52
|
const searchSubscription = {
|
|
56
53
|
id: 2,
|
|
@@ -59,24 +56,25 @@ describe("<RuleSubscription />", () => {
|
|
|
59
56
|
status: ["warn"],
|
|
60
57
|
events: ["rule_result_created"],
|
|
61
58
|
resource_id: 2,
|
|
62
|
-
resource_type: "rule"
|
|
59
|
+
resource_type: "rule",
|
|
63
60
|
},
|
|
64
61
|
subscriber: {
|
|
65
62
|
id: 3,
|
|
66
63
|
identifier: "2",
|
|
67
|
-
type: "user"
|
|
68
|
-
}
|
|
64
|
+
type: "user",
|
|
65
|
+
},
|
|
69
66
|
};
|
|
70
67
|
const subscriptionUpdating = false;
|
|
71
68
|
|
|
72
69
|
const props = {
|
|
73
|
-
rule,
|
|
70
|
+
resource: rule,
|
|
71
|
+
resourceType: "rule",
|
|
74
72
|
searchSubscription,
|
|
75
|
-
subscriptionUpdating
|
|
73
|
+
subscriptionUpdating,
|
|
76
74
|
};
|
|
77
75
|
|
|
78
76
|
it("matches the latest snapshot", () => {
|
|
79
|
-
const wrapper = shallow(<
|
|
77
|
+
const wrapper = shallow(<Subscription {...props} />);
|
|
80
78
|
expect(wrapper).toMatchSnapshot();
|
|
81
79
|
});
|
|
82
80
|
});
|
|
@@ -33,7 +33,15 @@ exports[`<Rule /> matches the latest snapshot 1`] = `
|
|
|
33
33
|
textAlign="right"
|
|
34
34
|
width={8}
|
|
35
35
|
>
|
|
36
|
-
<Connect(
|
|
36
|
+
<Connect(Subscription)
|
|
37
|
+
resource={
|
|
38
|
+
Object {
|
|
39
|
+
"id": 1,
|
|
40
|
+
"name": "foo",
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
resourceType="rule"
|
|
44
|
+
/>
|
|
37
45
|
<Connect(RuleActions) />
|
|
38
46
|
</GridColumn>
|
|
39
47
|
</Grid>
|
|
@@ -50,6 +50,15 @@ exports[`<RuleImplementation /> matches the latest snapshot 1`] = `
|
|
|
50
50
|
>
|
|
51
51
|
Execute implementation
|
|
52
52
|
</button>
|
|
53
|
+
<button
|
|
54
|
+
class="ui basic icon button button icon group-actions"
|
|
55
|
+
data-tooltip="Subscribe"
|
|
56
|
+
>
|
|
57
|
+
<i
|
|
58
|
+
aria-hidden="true"
|
|
59
|
+
class="eye icon"
|
|
60
|
+
/>
|
|
61
|
+
</button>
|
|
53
62
|
<div
|
|
54
63
|
aria-expanded="false"
|
|
55
64
|
class="ui floating dropdown button icon group-actions"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
-
exports[`<
|
|
3
|
+
exports[`<Subscription /> matches the latest snapshot 1`] = `
|
|
4
4
|
<Popup
|
|
5
5
|
basic={true}
|
|
6
6
|
disabled={false}
|
|
@@ -61,7 +61,7 @@ exports[`<RuleSubscription /> matches the latest snapshot 1`] = `
|
|
|
61
61
|
}
|
|
62
62
|
subscriptionUpdating={false}
|
|
63
63
|
>
|
|
64
|
-
<
|
|
64
|
+
<SubscriptionContent
|
|
65
65
|
setSubscription={[Function]}
|
|
66
66
|
subscription={
|
|
67
67
|
Object {
|
|
@@ -90,7 +90,7 @@ exports[`<RuleSubscription /> matches the latest snapshot 1`] = `
|
|
|
90
90
|
</Popup>
|
|
91
91
|
`;
|
|
92
92
|
|
|
93
|
-
exports[`<
|
|
93
|
+
exports[`<SubscriptionContent /> matches the latest snapshot 1`] = `
|
|
94
94
|
<FormField>
|
|
95
95
|
<FormField>
|
|
96
96
|
<label>
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
1
2
|
import { IMPLEMENTATIONS, linkTo } from "@truedat/core/routes";
|
|
2
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
clearRedirect,
|
|
5
|
+
createSubscription,
|
|
6
|
+
deleteSubscription,
|
|
7
|
+
updateSubscription,
|
|
8
|
+
} from "@truedat/core/routines";
|
|
3
9
|
import {
|
|
4
10
|
createExecutionGroup,
|
|
5
11
|
createImplementationStructure,
|
|
@@ -43,6 +49,14 @@ export const ruleImplementationRedirect = (
|
|
|
43
49
|
const { rule_implementation_id: implementation_id } = payload;
|
|
44
50
|
return linkTo.IMPLEMENTATION_RESULTS({ implementation_id });
|
|
45
51
|
}
|
|
52
|
+
case createSubscription.SUCCESS:
|
|
53
|
+
case deleteSubscription.SUCCESS:
|
|
54
|
+
case updateSubscription.SUCCESS: {
|
|
55
|
+
const { implementation_id } = payload;
|
|
56
|
+
return _.isNil(implementation_id)
|
|
57
|
+
? state
|
|
58
|
+
: linkTo.IMPLEMENTATION({ implementation_id });
|
|
59
|
+
}
|
|
46
60
|
default:
|
|
47
61
|
return state;
|
|
48
62
|
}
|