@truedat/dq 8.10.7 → 8.11.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dq",
3
- "version": "8.10.7",
3
+ "version": "8.11.0",
4
4
  "description": "Truedat Web Data Quality Module",
5
5
  "sideEffects": false,
6
6
  "module": "src/index.js",
@@ -59,7 +59,7 @@
59
59
  "@testing-library/jest-dom": "^6.6.3",
60
60
  "@testing-library/react": "^16.3.0",
61
61
  "@testing-library/user-event": "^14.6.1",
62
- "@truedat/test": "8.10.7",
62
+ "@truedat/test": "8.11.0",
63
63
  "identity-obj-proxy": "^3.0.0",
64
64
  "jest": "^29.7.0",
65
65
  "redux-saga-test-plan": "^4.0.6"
@@ -92,5 +92,5 @@
92
92
  "semantic-ui-react": "^3.0.0-beta.2",
93
93
  "swr": "^2.3.3"
94
94
  },
95
- "gitHead": "9b9c72e7d3045158547a4ae9fbc4b73a62283ed8"
95
+ "gitHead": "89b12f5fa7ff2d0fb790d88830938ccff9cb3d91"
96
96
  }
@@ -2,7 +2,7 @@ import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { Route, useParams, Routes } from "react-router";
5
- import { connect } from "react-redux";
5
+ import { connect, useSelector } from "react-redux";
6
6
  import { Segment } from "semantic-ui-react";
7
7
  import { ProtectedRoute, Loader } from "@truedat/core/router";
8
8
  // This is only for information purposes
@@ -33,9 +33,11 @@ import RuleSubscriptionLoader from "./RuleSubscriptionLoader";
33
33
  const TemplatesLoader = React.lazy(
34
34
  () => import("@truedat/core/components/TemplatesLoader"),
35
35
  );
36
+
36
37
  const EventsLoader = React.lazy(
37
38
  () => import("@truedat/audit/components/EventsLoader"),
38
39
  );
40
+
39
41
  const ImplementationStructuresLoader = React.lazy(
40
42
  () => import("@truedat/dd/components/ImplementationStructuresLoader"),
41
43
  );
@@ -47,8 +49,16 @@ const ImplementationRelationForm = React.lazy(
47
49
  );
48
50
 
49
51
  const ImplementationEventsLoader = () => {
50
- const { implementation_id: id } = useParams();
51
- return <EventsLoader resource_id={id} resource_type="implementation" />;
52
+ const implementationRef = useSelector(
53
+ (state) => state.ruleImplementation?.implementation_ref,
54
+ );
55
+ if (!implementationRef) return null;
56
+ return (
57
+ <EventsLoader
58
+ resource_id={implementationRef}
59
+ resource_type="implementation_ref"
60
+ />
61
+ );
52
62
  };
53
63
 
54
64
  export const ImplementationsRoutes = ({
@@ -7,34 +7,49 @@ import Moment from "react-moment";
7
7
  export const RuleEventRow = ({ user, user_name, ts, payload }) => {
8
8
  const { formatMessage, locale } = useIntl();
9
9
  const userName = _.propOr(user_name, "user_name")(user);
10
-
10
+ const eventVia = payload.length > 0 ? payload[0].event_via : null;
11
+ const action = payload.length > 0 ? payload[0].action : null;
12
+ const formatValue = (field, value) => {
13
+ if (field === "active" && typeof value === "boolean") {
14
+ return formatMessage({
15
+ id: `rule.props.active.${value}`,
16
+ });
17
+ }
18
+ return _.isObject(value) ? _.get("value", value) : value;
19
+ };
11
20
  return _.isEmpty(payload) ? null : (
12
21
  <Feed.Event>
13
22
  <Feed.Content>
14
23
  <Feed.Summary>
15
24
  <Feed.User>{userName}</Feed.User>{" "}
25
+ {action && (
26
+ <span>
27
+ {formatMessage({ id: `rules.events.action_${action}` })}
28
+ </span>
29
+ )}{" "}
30
+ {eventVia ? (
31
+ <span className="audit-event-via">
32
+ {formatMessage({ id: `audit.events.via.${eventVia}` })}
33
+ </span>
34
+ ) : null}{" "}
16
35
  <Feed.Date>
17
36
  <Moment locale={locale} date={ts} format="YYYY-MM-DD HH:mm" />
18
37
  </Feed.Date>
19
38
  </Feed.Summary>
20
- {payload.map(({ field, action, value }, i) => (
21
- <Feed.Extra
22
- key={i}
23
- text
24
- content={formatMessage(
25
- {
26
- id: `rules.events.action_${action}${
27
- action === "changed" &&
28
- typeof value !== "undefined" &&
29
- !_.isObject(value)
30
- ? "_to"
31
- : ""
32
- }`,
33
- },
34
- [field, JSON.stringify(value)],
35
- )}
36
- />
37
- ))}
39
+ {payload.map(({ field, action_extra, value }, i) =>
40
+ action_extra ? (
41
+ <Feed.Extra
42
+ key={i}
43
+ text
44
+ content={formatMessage(
45
+ {
46
+ id: `rules.events.extra.${action_extra}`,
47
+ },
48
+ [field, formatValue(field, value)],
49
+ )}
50
+ />
51
+ ) : null,
52
+ )}
38
53
  </Feed.Content>
39
54
  </Feed.Event>
40
55
  );
@@ -3,7 +3,6 @@ import PropTypes from "prop-types";
3
3
  import { Feed } from "semantic-ui-react";
4
4
  import { useIntl } from "react-intl";
5
5
  import Moment from "react-moment";
6
-
7
6
  export const RuleImplementationEventRow = ({
8
7
  user,
9
8
  user_name,
@@ -12,26 +11,50 @@ export const RuleImplementationEventRow = ({
12
11
  }) => {
13
12
  const { formatMessage, locale } = useIntl();
14
13
  const userName = _.propOr(user_name, "user_name")(user);
14
+ const eventVia = payload.length > 0 ? payload[0].event_via : null;
15
+ const action = payload.length > 0 ? payload[0].action : null;
16
+ const formatValue = (field, value) => {
17
+ if (field === "executable" && typeof value === "boolean") {
18
+ return formatMessage({
19
+ id: `ruleImplementation.props.executable.${value}`,
20
+ });
21
+ }
22
+ return _.isPlainObject(value) ? _.get("value", value) : value;
23
+ };
15
24
 
16
25
  return _.isEmpty(payload) ? null : (
17
26
  <Feed.Event>
18
27
  <Feed.Content>
19
28
  <Feed.Summary>
20
29
  <Feed.User>{userName}</Feed.User>{" "}
30
+ {action && (
31
+ <span>
32
+ {formatMessage({
33
+ id: `ruleImplementations.events.action_${action}`,
34
+ })}
35
+ </span>
36
+ )}{" "}
37
+ {eventVia ? (
38
+ <span className="audit-event-via">
39
+ {formatMessage({ id: `audit.events.via.${eventVia}` })}
40
+ </span>
41
+ ) : null}{" "}
21
42
  <Feed.Date>
22
43
  <Moment locale={locale} date={ts} format="YYYY-MM-DD HH:mm" />
23
44
  </Feed.Date>
24
45
  </Feed.Summary>
25
- {payload.map(({ field, action, value }, i) => (
26
- <Feed.Extra
27
- key={i}
28
- text
29
- content={formatMessage(
30
- { id: "ruleImplementations.events.action_" + action },
31
- [field, _.isObject(value) ? JSON.stringify(value) : value],
32
- )}
33
- />
34
- ))}
46
+ {payload.map(({ field, action_extra, value }, i) =>
47
+ action_extra ? (
48
+ <Feed.Extra
49
+ key={i}
50
+ text
51
+ content={formatMessage(
52
+ { id: `ruleImplementations.events.extra.${action_extra}` },
53
+ [field, formatValue(field, value)],
54
+ )}
55
+ />
56
+ ) : null,
57
+ )}
35
58
  </Feed.Content>
36
59
  </Feed.Event>
37
60
  );
@@ -130,4 +130,132 @@ describe("<ImplementationsRoutes />", () => {
130
130
  await waitForLoad(rendered);
131
131
  expect(rendered.container).toMatchSnapshot();
132
132
  });
133
+
134
+ it("renders correctly with new basic implementation route", async () => {
135
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
136
+ routes: [IMPLEMENTATION_NEW_BASIC],
137
+ });
138
+ await waitForLoad(rendered);
139
+ expect(rendered.container).toMatchSnapshot();
140
+ });
141
+
142
+ it("renders correctly with new raw implementation route", async () => {
143
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
144
+ routes: [IMPLEMENTATION_NEW_RAW],
145
+ });
146
+ await waitForLoad(rendered);
147
+ expect(rendered.container).toMatchSnapshot();
148
+ });
149
+
150
+ it("renders correctly with implementation events route", async () => {
151
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
152
+ routes: [IMPLEMENTATION_EVENTS.replace(":implementation_id", "123")],
153
+ });
154
+ await waitForLoad(rendered);
155
+ expect(rendered.container).toMatchSnapshot();
156
+ });
157
+
158
+ it("renders correctly with implementation executions route", async () => {
159
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
160
+ routes: [IMPLEMENTATION_EXECUTIONS.replace(":implementation_id", "123")],
161
+ });
162
+ await waitForLoad(rendered);
163
+ expect(rendered.container).toMatchSnapshot();
164
+ });
165
+
166
+ it("renders correctly with implementation results route", async () => {
167
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
168
+ routes: [IMPLEMENTATION_RESULTS.replace(":implementation_id", "123")],
169
+ });
170
+ await waitForLoad(rendered);
171
+ expect(rendered.container).toMatchSnapshot();
172
+ });
173
+
174
+ it("renders correctly with implementation history route", async () => {
175
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
176
+ routes: [IMPLEMENTATION_HISTORY.replace(":implementation_id", "123")],
177
+ });
178
+ await waitForLoad(rendered);
179
+ expect(rendered.container).toMatchSnapshot();
180
+ });
181
+
182
+ it("renders correctly with implementation clone route", async () => {
183
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
184
+ routes: [IMPLEMENTATION_CLONE.replace(":implementation_id", "123")],
185
+ });
186
+ await waitForLoad(rendered);
187
+ expect(rendered.container).toMatchSnapshot();
188
+ });
189
+
190
+ it("renders correctly with implementation edit route", async () => {
191
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
192
+ routes: [IMPLEMENTATION_EDIT.replace(":implementation_id", "123")],
193
+ });
194
+ await waitForLoad(rendered);
195
+ expect(rendered.container).toMatchSnapshot();
196
+ });
197
+
198
+ it("renders correctly with implementation edit as default route", async () => {
199
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
200
+ routes: [
201
+ IMPLEMENTATION_EDIT_AS_DEFAULT.replace(":implementation_id", "123"),
202
+ ],
203
+ });
204
+ await waitForLoad(rendered);
205
+ expect(rendered.container).toMatchSnapshot();
206
+ });
207
+
208
+ it("renders correctly with implementation edit as raw route", async () => {
209
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
210
+ routes: [IMPLEMENTATION_EDIT_AS_RAW.replace(":implementation_id", "123")],
211
+ });
212
+ await waitForLoad(rendered);
213
+ expect(rendered.container).toMatchSnapshot();
214
+ });
215
+
216
+ it("renders correctly with implementation concept links route", async () => {
217
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
218
+ routes: [
219
+ IMPLEMENTATION_CONCEPT_LINKS.replace(":implementation_id", "123"),
220
+ ],
221
+ });
222
+ await waitForLoad(rendered);
223
+ expect(rendered.container).toMatchSnapshot();
224
+ });
225
+
226
+ it("renders correctly with implementation concept links new route", async () => {
227
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
228
+ routes: [
229
+ IMPLEMENTATION_CONCEPT_LINKS_NEW.replace(":implementation_id", "123"),
230
+ ],
231
+ });
232
+ await waitForLoad(rendered);
233
+ expect(rendered.container).toMatchSnapshot();
234
+ });
235
+
236
+ it("renders correctly with implementation structures route", async () => {
237
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
238
+ routes: [IMPLEMENTATION_STRUCTURES.replace(":implementation_id", "123")],
239
+ });
240
+ await waitForLoad(rendered);
241
+ expect(rendered.container).toMatchSnapshot();
242
+ });
243
+
244
+ it("renders correctly with implementation structures new route", async () => {
245
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
246
+ routes: [
247
+ IMPLEMENTATION_STRUCTURES_NEW.replace(":implementation_id", "123"),
248
+ ],
249
+ });
250
+ await waitForLoad(rendered);
251
+ expect(rendered.container).toMatchSnapshot();
252
+ });
253
+
254
+ it("renders correctly with implementation result details route", async () => {
255
+ const rendered = render(<ImplementationsRoutes {...defaultProps} />, {
256
+ routes: ["/implementations/123/results/456/some-path"],
257
+ });
258
+ await waitForLoad(rendered);
259
+ expect(rendered.container).toMatchSnapshot();
260
+ });
133
261
  });
@@ -7,6 +7,8 @@ describe("<RuleEventsRow />", () => {
7
7
  {
8
8
  field: "field1",
9
9
  action: "changed",
10
+ action_extra: "changed",
11
+ event_via: "single_update",
10
12
  value: "new value",
11
13
  },
12
14
  ],
@@ -21,7 +23,12 @@ describe("<RuleEventsRow />", () => {
21
23
  };
22
24
  const renderOpts = {
23
25
  messages: {
24
- en: { "rules.events.action_changed_to": "Field {0} changed to: {1}" },
26
+ en: {
27
+ "audit.events.via.single_update": "via web",
28
+ "rules.events.action_changed": "updated the rule",
29
+ "rules.events.extra.changed": "Field {0} changed to: {1}",
30
+ "rules.events.extra.changed_to": "Field {0} changed to: {1}",
31
+ },
25
32
  },
26
33
  };
27
34
 
@@ -46,10 +46,11 @@ describe("<RuleEvents />", () => {
46
46
  const renderOpts = {
47
47
  messages: {
48
48
  en: {
49
- "rules.events.action_created": "Rule created",
50
- "rules.events.action_changed": "Field {0} changed: {1}",
51
- "rules.events.action_changed_to": "Field {0} changed to: {1}",
52
- "rules.events.action_updated": "Rule updated",
49
+ "rules.events.action_changed": "updated the rule",
50
+ "rules.events.action_created": "created the rule",
51
+ "rules.events.action_updated": "updated the rule",
52
+ "rules.events.extra.domain_updated_with_id":
53
+ "Domain changed to domain id: {0}",
53
54
  },
54
55
  },
55
56
  };
@@ -0,0 +1,54 @@
1
+ import { render } from "@truedat/test/render";
2
+ import { RuleImplementationEventRow } from "../RuleImplementationEventRow";
3
+
4
+ describe("<RuleImplementationEventRow />", () => {
5
+ const props = {
6
+ payload: [
7
+ {
8
+ field: "implementation_key",
9
+ action: "changed",
10
+ action_extra: "implementation_key_updated",
11
+ event_via: "single_update",
12
+ value: "new_key",
13
+ },
14
+ {
15
+ field: "executable",
16
+ action: "changed",
17
+ action_extra: "executable_updated",
18
+ event_via: "single_update",
19
+ value: true,
20
+ },
21
+ ],
22
+ user_name: "some.user@domain.tld",
23
+ user: {
24
+ email: "some.user@domain.tld",
25
+ full_name: "Some User",
26
+ id: 142,
27
+ user_name: "some.user@domain.tld",
28
+ },
29
+ ts: "2021-09-16T07:36:32.848603Z",
30
+ };
31
+ const renderOpts = {
32
+ messages: {
33
+ en: {
34
+ "audit.events.via.single_update": "via web",
35
+ "ruleImplementations.events.action_changed":
36
+ "updated the implementation",
37
+ "ruleImplementations.events.extra.implementation_key_updated":
38
+ "Implementation key updated to: {1}",
39
+ "ruleImplementations.events.extra.executable_updated":
40
+ "Executable switch value updated: {1}",
41
+ "ruleImplementation.props.executable.true": "Executable",
42
+ "ruleImplementation.props.executable.false": "Internal",
43
+ },
44
+ },
45
+ };
46
+
47
+ it("matches the latest snapshot", () => {
48
+ const { container } = render(
49
+ <RuleImplementationEventRow {...props} />,
50
+ renderOpts,
51
+ );
52
+ expect(container).toMatchSnapshot();
53
+ });
54
+ });
@@ -10,8 +10,34 @@ exports[`<ImplementationsRoutes /> renders correctly with default route 1`] = `
10
10
 
11
11
  exports[`<ImplementationsRoutes /> renders correctly with deprecated implementations route 1`] = `<div />`;
12
12
 
13
+ exports[`<ImplementationsRoutes /> renders correctly with implementation clone route 1`] = `<div />`;
14
+
15
+ exports[`<ImplementationsRoutes /> renders correctly with implementation concept links new route 1`] = `<div />`;
16
+
17
+ exports[`<ImplementationsRoutes /> renders correctly with implementation concept links route 1`] = `<div />`;
18
+
13
19
  exports[`<ImplementationsRoutes /> renders correctly with implementation detail route 1`] = `<div />`;
14
20
 
21
+ exports[`<ImplementationsRoutes /> renders correctly with implementation edit as default route 1`] = `<div />`;
22
+
23
+ exports[`<ImplementationsRoutes /> renders correctly with implementation edit as raw route 1`] = `<div />`;
24
+
25
+ exports[`<ImplementationsRoutes /> renders correctly with implementation edit route 1`] = `<div />`;
26
+
27
+ exports[`<ImplementationsRoutes /> renders correctly with implementation events route 1`] = `<div />`;
28
+
29
+ exports[`<ImplementationsRoutes /> renders correctly with implementation executions route 1`] = `<div />`;
30
+
31
+ exports[`<ImplementationsRoutes /> renders correctly with implementation history route 1`] = `<div />`;
32
+
33
+ exports[`<ImplementationsRoutes /> renders correctly with implementation result details route 1`] = `<div />`;
34
+
35
+ exports[`<ImplementationsRoutes /> renders correctly with implementation results route 1`] = `<div />`;
36
+
37
+ exports[`<ImplementationsRoutes /> renders correctly with implementation structures new route 1`] = `<div />`;
38
+
39
+ exports[`<ImplementationsRoutes /> renders correctly with implementation structures route 1`] = `<div />`;
40
+
15
41
  exports[`<ImplementationsRoutes /> renders correctly with implementations route 1`] = `
16
42
  <div>
17
43
  <div>
@@ -30,8 +56,12 @@ exports[`<ImplementationsRoutes /> renders correctly with implementations route
30
56
  </div>
31
57
  `;
32
58
 
59
+ exports[`<ImplementationsRoutes /> renders correctly with new basic implementation route 1`] = `<div />`;
60
+
33
61
  exports[`<ImplementationsRoutes /> renders correctly with new implementation route 1`] = `<div />`;
34
62
 
63
+ exports[`<ImplementationsRoutes /> renders correctly with new raw implementation route 1`] = `<div />`;
64
+
35
65
  exports[`<ImplementationsRoutes /> renders correctly with pending implementations route 1`] = `<div />`;
36
66
 
37
67
  exports[`<ImplementationsRoutes /> renders unauthorized component when not authorized 1`] = `<div />`;
@@ -17,6 +17,16 @@ exports[`<RuleEventsRow /> matches the latest snapshot 1`] = `
17
17
  some.user@domain.tld
18
18
  </a>
19
19
 
20
+ <span>
21
+ updated the rule
22
+ </span>
23
+
24
+ <span
25
+ class="audit-event-via"
26
+ >
27
+ via web
28
+ </span>
29
+
20
30
  <div
21
31
  class="date"
22
32
  >
@@ -30,7 +40,7 @@ exports[`<RuleEventsRow /> matches the latest snapshot 1`] = `
30
40
  <div
31
41
  class="text extra"
32
42
  >
33
- Field field1 changed to: "new value"
43
+ Field field1 changed to: new value
34
44
  </div>
35
45
  </div>
36
46
  </div>
@@ -23,6 +23,11 @@ exports[`<RuleEvents /> matches the latest snapshot 1`] = `
23
23
  some.user@domain.tld
24
24
  </a>
25
25
 
26
+ <span>
27
+ updated the rule
28
+ </span>
29
+
30
+
26
31
  <div
27
32
  class="date"
28
33
  >
@@ -36,7 +41,7 @@ exports[`<RuleEvents /> matches the latest snapshot 1`] = `
36
41
  <div
37
42
  class="text extra"
38
43
  >
39
- Field domain_id changed to: 140
44
+ Domain changed to domain id: 140
40
45
  </div>
41
46
  </div>
42
47
  </div>
@@ -55,6 +60,11 @@ exports[`<RuleEvents /> matches the latest snapshot 1`] = `
55
60
  some.user
56
61
  </a>
57
62
 
63
+ <span>
64
+ updated the rule
65
+ </span>
66
+
67
+
58
68
  <div
59
69
  class="date"
60
70
  >
@@ -68,7 +78,7 @@ exports[`<RuleEvents /> matches the latest snapshot 1`] = `
68
78
  <div
69
79
  class="text extra"
70
80
  >
71
- Field domain_id changed to: 168
81
+ Domain changed to domain id: 168
72
82
  </div>
73
83
  </div>
74
84
  </div>
@@ -0,0 +1,53 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`<RuleImplementationEventRow /> matches the latest snapshot 1`] = `
4
+ <div>
5
+ <div
6
+ class="event"
7
+ >
8
+ <div
9
+ class="content"
10
+ >
11
+ <div
12
+ class="summary"
13
+ >
14
+ <a
15
+ class="user"
16
+ >
17
+ some.user@domain.tld
18
+ </a>
19
+
20
+ <span>
21
+ updated the implementation
22
+ </span>
23
+
24
+ <span
25
+ class="audit-event-via"
26
+ >
27
+ via web
28
+ </span>
29
+
30
+ <div
31
+ class="date"
32
+ >
33
+ <time
34
+ datetime="1631777792848"
35
+ >
36
+ 2021-09-16 07:36
37
+ </time>
38
+ </div>
39
+ </div>
40
+ <div
41
+ class="text extra"
42
+ >
43
+ Implementation key updated to: new_key
44
+ </div>
45
+ <div
46
+ class="text extra"
47
+ >
48
+ Executable switch value updated: Executable
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ `;