@truedat/dq 4.45.1 → 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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.45.2] 2022-05-31
4
+
5
+ ### Added
6
+
7
+ - [TD-3633] Add subscribe button (eye icon button) to implementations
8
+
3
9
  ## [4.44.5] 2022-05-20
4
10
 
5
11
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dq",
3
- "version": "4.45.1",
3
+ "version": "4.45.2",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -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": "c13f37ee357bf4a5e8c8c99eb6bd0c798f468c49"
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
@@ -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 RuleSubscription from "./RuleSubscription";
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
- <RuleSubscription />
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 RuleSubscriptionContent = ({ subscription, setSubscription }) => {
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
- RuleSubscriptionContent.propTypes = {
70
+ SubscriptionContent.propTypes = {
71
71
  subscription: PropTypes.object,
72
- setSubscription: PropTypes.func
72
+ setSubscription: PropTypes.func,
73
73
  };
74
74
 
75
- export const RuleSubscription = ({
76
- rule,
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
- subscription: {
101
- ...subscriptionField,
102
- scope: {
103
- resource_id: _.prop("id")(rule),
104
- resource_type: "rule",
105
- events: ["rule_result_created"],
106
- status: _.path("scope.status")(subscriptionField)
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
- rule_id: _.prop("id")(rule)
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
- subscription: subscriptionField,
119
- resource_id: _.prop("id")(rule),
120
- resource_type: "rule",
121
- rule_id: _.prop("id")(rule)
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
- <RuleSubscriptionContent
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
- RuleSubscription.propTypes = {
200
+ Subscription.propTypes = {
170
201
  createSubscription: PropTypes.func,
171
202
  updateSubscription: PropTypes.func,
172
203
  deleteSubscription: PropTypes.func,
173
204
  searchSubscription: PropTypes.object,
174
- rule: PropTypes.object,
175
- subscriptionUpdating: PropTypes.bool
205
+ resource: PropTypes.object,
206
+ resourceType: PropTypes.string,
207
+ subscriptionUpdating: PropTypes.bool,
176
208
  };
177
209
 
178
- export const mapStateToProps = ({
179
- rule,
180
- searchSubscription,
181
- subscriptionUpdating
182
- }) => ({
183
- rule,
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)(RuleSubscription);
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 { RuleSubscription, RuleSubscriptionContent } from "../RuleSubscription";
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("<RuleSubscriptionContent />", () => {
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(<RuleSubscriptionContent {...props} />);
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(<RuleSubscriptionContent {...props} />);
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("<RuleSubscription />", () => {
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(<RuleSubscription {...props} />);
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(RuleSubscription) />
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[`<RuleSubscription /> matches the latest snapshot 1`] = `
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
- <RuleSubscriptionContent
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[`<RuleSubscriptionContent /> matches the latest snapshot 1`] = `
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 { clearRedirect } from "@truedat/core/routines";
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
  }