@truedat/qx 7.14.5 → 8.0.1
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 +3 -3
- package/src/components/dataViews/__tests__/DataViewSummary.spec.js +44 -0
- package/src/components/dataViews/__tests__/__snapshots__/DataViewSummary.spec.js.snap +23 -177
- package/src/components/qualityControls/QualityControlEvents.js +102 -0
- package/src/components/qualityControls/QualityControlRoutes.js +3 -1
- package/src/components/qualityControls/QualityControlTabs.js +4 -0
- package/src/components/qualityControls/__tests__/QualityControlEvents.spec.js +118 -0
- package/src/components/qualityControls/__tests__/__snapshots__/QualityControlEvents.spec.js.snap +55 -0
- package/src/components/qualityControls/__tests__/__snapshots__/QualityControlHeader.spec.js.snap +7 -0
- package/src/components/qualityControls/__tests__/__snapshots__/QualityControlTabs.spec.js.snap +7 -0
- package/src/components/qualityControls/events/__tests__/getParsedEvents.spec.js +198 -0
- package/src/components/qualityControls/events/getParsedEvents.js +254 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/qx",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.1",
|
|
4
4
|
"description": "Truedat Web Quality Experience package",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@testing-library/jest-dom": "^6.6.3",
|
|
54
54
|
"@testing-library/react": "^16.3.0",
|
|
55
55
|
"@testing-library/user-event": "^14.6.1",
|
|
56
|
-
"@truedat/test": "
|
|
56
|
+
"@truedat/test": "8.0.1",
|
|
57
57
|
"identity-obj-proxy": "^3.0.0",
|
|
58
58
|
"jest": "^29.7.0",
|
|
59
59
|
"redux-saga-test-plan": "^4.0.6"
|
|
@@ -86,5 +86,5 @@
|
|
|
86
86
|
"semantic-ui-react": "^3.0.0-beta.2",
|
|
87
87
|
"swr": "^2.3.3"
|
|
88
88
|
},
|
|
89
|
-
"gitHead": "
|
|
89
|
+
"gitHead": "1d2fb016733a74a116362b4906f7141ca7b20ff0"
|
|
90
90
|
}
|
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
2
|
import DataViewSummary from "../DataViewSummary";
|
|
3
3
|
|
|
4
|
+
jest.mock("@truedat/qx/hooks/useFunctions", () => {
|
|
5
|
+
const originalModule = jest.requireActual("@truedat/qx/hooks/useFunctions");
|
|
6
|
+
|
|
7
|
+
return {
|
|
8
|
+
__esModule: true,
|
|
9
|
+
...originalModule,
|
|
10
|
+
useFunctions: jest.fn(() => ({
|
|
11
|
+
data: {
|
|
12
|
+
data: [
|
|
13
|
+
{
|
|
14
|
+
name: "eq",
|
|
15
|
+
type: "boolean",
|
|
16
|
+
params: [
|
|
17
|
+
{ name: "arg1", type: "any" },
|
|
18
|
+
{ name: "arg2", type: "any" },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: "gt",
|
|
23
|
+
type: "boolean",
|
|
24
|
+
params: [
|
|
25
|
+
{ name: "arg1", type: "any" },
|
|
26
|
+
{ name: "arg2", type: "any" },
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "sum",
|
|
31
|
+
type: "number",
|
|
32
|
+
params: [{ name: "arg1", type: "any" }],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "count",
|
|
36
|
+
type: "number",
|
|
37
|
+
params: [],
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
loading: false,
|
|
42
|
+
error: null,
|
|
43
|
+
mutate: jest.fn(),
|
|
44
|
+
})),
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
|
|
4
48
|
const messages = {
|
|
5
49
|
"dataViews.form.queryable.from": "FROM",
|
|
6
50
|
"dataViews.form.queryable.join": "JOIN",
|
|
@@ -304,40 +304,23 @@ exports[`<DataViewSummary /> matches snapshot for FROM with JOIN 1`] = `
|
|
|
304
304
|
class="ui segment no-margin text-break-word"
|
|
305
305
|
>
|
|
306
306
|
<div
|
|
307
|
-
class="
|
|
307
|
+
class="condition-function-viewer"
|
|
308
308
|
>
|
|
309
309
|
<div
|
|
310
|
-
class="ui
|
|
311
|
-
title="
|
|
310
|
+
class="ui blue label text-break-word"
|
|
311
|
+
title="users.user_id"
|
|
312
312
|
>
|
|
313
|
-
|
|
313
|
+
users.user_id
|
|
314
314
|
</div>
|
|
315
|
-
|
|
315
|
+
<b
|
|
316
|
+
class="font-big"
|
|
317
|
+
/>
|
|
316
318
|
<div
|
|
317
|
-
class="
|
|
319
|
+
class="ui orange label text-break-word"
|
|
320
|
+
title="orders.user_id"
|
|
318
321
|
>
|
|
319
|
-
|
|
320
|
-
class="display-flex"
|
|
321
|
-
>
|
|
322
|
-
<div
|
|
323
|
-
class="ui blue label text-break-word"
|
|
324
|
-
title="users.user_id"
|
|
325
|
-
>
|
|
326
|
-
users.user_id
|
|
327
|
-
</div>
|
|
328
|
-
</div>
|
|
329
|
-
<div
|
|
330
|
-
class="display-flex"
|
|
331
|
-
>
|
|
332
|
-
<div
|
|
333
|
-
class="ui orange label text-break-word"
|
|
334
|
-
title="orders.user_id"
|
|
335
|
-
>
|
|
336
|
-
orders.user_id
|
|
337
|
-
</div>
|
|
338
|
-
</div>
|
|
322
|
+
orders.user_id
|
|
339
323
|
</div>
|
|
340
|
-
)
|
|
341
324
|
</div>
|
|
342
325
|
</div>
|
|
343
326
|
</div>
|
|
@@ -427,47 +410,7 @@ exports[`<DataViewSummary /> matches snapshot for FROM with WHERE clause 1`] = `
|
|
|
427
410
|
>
|
|
428
411
|
<div
|
|
429
412
|
class="ui basic compact segment text-break-word"
|
|
430
|
-
|
|
431
|
-
<div
|
|
432
|
-
class="ui segment no-margin text-break-word"
|
|
433
|
-
>
|
|
434
|
-
<div
|
|
435
|
-
class="text-align-left"
|
|
436
|
-
>
|
|
437
|
-
<div
|
|
438
|
-
class="ui tiny horizontal label text-break-word"
|
|
439
|
-
title="gt"
|
|
440
|
-
>
|
|
441
|
-
gt
|
|
442
|
-
</div>
|
|
443
|
-
(
|
|
444
|
-
<div
|
|
445
|
-
class="clause-viewer-function"
|
|
446
|
-
>
|
|
447
|
-
<div
|
|
448
|
-
class="display-flex"
|
|
449
|
-
>
|
|
450
|
-
<div
|
|
451
|
-
class="ui blue label text-break-word"
|
|
452
|
-
title="users.age"
|
|
453
|
-
>
|
|
454
|
-
users.age
|
|
455
|
-
</div>
|
|
456
|
-
</div>
|
|
457
|
-
<div
|
|
458
|
-
class="display-flex"
|
|
459
|
-
>
|
|
460
|
-
<div
|
|
461
|
-
class="ui basic label text-break-word"
|
|
462
|
-
>
|
|
463
|
-
18
|
|
464
|
-
</div>
|
|
465
|
-
</div>
|
|
466
|
-
</div>
|
|
467
|
-
)
|
|
468
|
-
</div>
|
|
469
|
-
</div>
|
|
470
|
-
</div>
|
|
413
|
+
/>
|
|
471
414
|
</div>
|
|
472
415
|
</div>
|
|
473
416
|
</div>
|
|
@@ -603,40 +546,23 @@ exports[`<DataViewSummary /> matches snapshot for complete data view with all qu
|
|
|
603
546
|
class="ui segment no-margin text-break-word"
|
|
604
547
|
>
|
|
605
548
|
<div
|
|
606
|
-
class="
|
|
549
|
+
class="condition-function-viewer"
|
|
607
550
|
>
|
|
608
551
|
<div
|
|
609
|
-
class="ui
|
|
610
|
-
title="
|
|
552
|
+
class="ui blue label text-break-word"
|
|
553
|
+
title="users.user_id"
|
|
611
554
|
>
|
|
612
|
-
|
|
555
|
+
users.user_id
|
|
613
556
|
</div>
|
|
614
|
-
|
|
557
|
+
<b
|
|
558
|
+
class="font-big"
|
|
559
|
+
/>
|
|
615
560
|
<div
|
|
616
|
-
class="
|
|
561
|
+
class="ui orange label text-break-word"
|
|
562
|
+
title="orders.user_id"
|
|
617
563
|
>
|
|
618
|
-
|
|
619
|
-
class="display-flex"
|
|
620
|
-
>
|
|
621
|
-
<div
|
|
622
|
-
class="ui blue label text-break-word"
|
|
623
|
-
title="users.user_id"
|
|
624
|
-
>
|
|
625
|
-
users.user_id
|
|
626
|
-
</div>
|
|
627
|
-
</div>
|
|
628
|
-
<div
|
|
629
|
-
class="display-flex"
|
|
630
|
-
>
|
|
631
|
-
<div
|
|
632
|
-
class="ui orange label text-break-word"
|
|
633
|
-
title="orders.user_id"
|
|
634
|
-
>
|
|
635
|
-
orders.user_id
|
|
636
|
-
</div>
|
|
637
|
-
</div>
|
|
564
|
+
orders.user_id
|
|
638
565
|
</div>
|
|
639
|
-
)
|
|
640
566
|
</div>
|
|
641
567
|
</div>
|
|
642
568
|
</div>
|
|
@@ -669,47 +595,7 @@ exports[`<DataViewSummary /> matches snapshot for complete data view with all qu
|
|
|
669
595
|
>
|
|
670
596
|
<div
|
|
671
597
|
class="ui basic compact segment text-break-word"
|
|
672
|
-
|
|
673
|
-
<div
|
|
674
|
-
class="ui segment no-margin text-break-word"
|
|
675
|
-
>
|
|
676
|
-
<div
|
|
677
|
-
class="text-align-left"
|
|
678
|
-
>
|
|
679
|
-
<div
|
|
680
|
-
class="ui tiny horizontal label text-break-word"
|
|
681
|
-
title="gt"
|
|
682
|
-
>
|
|
683
|
-
gt
|
|
684
|
-
</div>
|
|
685
|
-
(
|
|
686
|
-
<div
|
|
687
|
-
class="clause-viewer-function"
|
|
688
|
-
>
|
|
689
|
-
<div
|
|
690
|
-
class="display-flex"
|
|
691
|
-
>
|
|
692
|
-
<div
|
|
693
|
-
class="ui orange label text-break-word"
|
|
694
|
-
title="orders.total"
|
|
695
|
-
>
|
|
696
|
-
orders.total
|
|
697
|
-
</div>
|
|
698
|
-
</div>
|
|
699
|
-
<div
|
|
700
|
-
class="display-flex"
|
|
701
|
-
>
|
|
702
|
-
<div
|
|
703
|
-
class="ui basic label text-break-word"
|
|
704
|
-
>
|
|
705
|
-
100
|
|
706
|
-
</div>
|
|
707
|
-
</div>
|
|
708
|
-
</div>
|
|
709
|
-
)
|
|
710
|
-
</div>
|
|
711
|
-
</div>
|
|
712
|
-
</div>
|
|
598
|
+
/>
|
|
713
599
|
</div>
|
|
714
600
|
</div>
|
|
715
601
|
</div>
|
|
@@ -1304,47 +1190,7 @@ exports[`<DataViewSummary /> matches snapshot with HAVING clause (where after gr
|
|
|
1304
1190
|
>
|
|
1305
1191
|
<div
|
|
1306
1192
|
class="ui basic compact segment text-break-word"
|
|
1307
|
-
|
|
1308
|
-
<div
|
|
1309
|
-
class="ui segment no-margin text-break-word"
|
|
1310
|
-
>
|
|
1311
|
-
<div
|
|
1312
|
-
class="text-align-left"
|
|
1313
|
-
>
|
|
1314
|
-
<div
|
|
1315
|
-
class="ui tiny horizontal label text-break-word"
|
|
1316
|
-
title="gt"
|
|
1317
|
-
>
|
|
1318
|
-
gt
|
|
1319
|
-
</div>
|
|
1320
|
-
(
|
|
1321
|
-
<div
|
|
1322
|
-
class="clause-viewer-function"
|
|
1323
|
-
>
|
|
1324
|
-
<div
|
|
1325
|
-
class="display-flex"
|
|
1326
|
-
>
|
|
1327
|
-
<div
|
|
1328
|
-
class="ui orange label text-break-word"
|
|
1329
|
-
title="Group By.total"
|
|
1330
|
-
>
|
|
1331
|
-
Group By.total
|
|
1332
|
-
</div>
|
|
1333
|
-
</div>
|
|
1334
|
-
<div
|
|
1335
|
-
class="display-flex"
|
|
1336
|
-
>
|
|
1337
|
-
<div
|
|
1338
|
-
class="ui basic label text-break-word"
|
|
1339
|
-
>
|
|
1340
|
-
1000
|
|
1341
|
-
</div>
|
|
1342
|
-
</div>
|
|
1343
|
-
</div>
|
|
1344
|
-
)
|
|
1345
|
-
</div>
|
|
1346
|
-
</div>
|
|
1347
|
-
</div>
|
|
1193
|
+
/>
|
|
1348
1194
|
</div>
|
|
1349
1195
|
</div>
|
|
1350
1196
|
</div>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import { Segment, Feed } from "semantic-ui-react";
|
|
3
|
+
import { useEvents } from "@truedat/audit/hooks/useEvents";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
import { use, useMemo } from "react";
|
|
6
|
+
import QxContext from "../QxContext";
|
|
7
|
+
import { getParsedEvents } from "./events/getParsedEvents";
|
|
8
|
+
import { useIntl } from "react-intl";
|
|
9
|
+
import Moment from "react-moment";
|
|
10
|
+
|
|
11
|
+
const MESSAGE_ID = 0;
|
|
12
|
+
const MESSAGE_PARAMS = 1;
|
|
13
|
+
|
|
14
|
+
const EventRow = ({ user, ts, header, payload }) => {
|
|
15
|
+
const { formatMessage, locale } = useIntl();
|
|
16
|
+
const translateParams = (params) => {
|
|
17
|
+
if (!_.isObject(params)) return params;
|
|
18
|
+
|
|
19
|
+
if (_.has("value.id")(params)) {
|
|
20
|
+
const transformValue = params.lowercase
|
|
21
|
+
? _.flow(formatMessage, _.toLower)
|
|
22
|
+
: formatMessage;
|
|
23
|
+
return {
|
|
24
|
+
...params,
|
|
25
|
+
value: transformValue(params.value),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (_.has("type.id")(params)) {
|
|
30
|
+
const formatParam = ([label, value]) =>
|
|
31
|
+
_.has("id")(label) && _.isString(label.id)
|
|
32
|
+
? `${formatMessage(label)}: ${value}`
|
|
33
|
+
: `${label}: ${value}`;
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
...params,
|
|
37
|
+
type: formatMessage(params.type),
|
|
38
|
+
params: _.isArray(params.params)
|
|
39
|
+
? _.flow(_.map(formatParam), _.join(", "))(params.params)
|
|
40
|
+
: params.params,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return params;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Feed.Event>
|
|
49
|
+
<Feed.Content>
|
|
50
|
+
<Feed.Summary>
|
|
51
|
+
<Feed.User>{user?.user_name}</Feed.User>{" "}
|
|
52
|
+
{formatMessage(
|
|
53
|
+
header[MESSAGE_ID],
|
|
54
|
+
translateParams(header[MESSAGE_PARAMS])
|
|
55
|
+
)}{" "}
|
|
56
|
+
<Feed.Date>
|
|
57
|
+
<Moment locale={locale} date={ts} format="YYYY-MM-DD HH:mm" />
|
|
58
|
+
</Feed.Date>
|
|
59
|
+
</Feed.Summary>
|
|
60
|
+
{payload.map((content, i) => (
|
|
61
|
+
<Feed.Extra
|
|
62
|
+
key={i}
|
|
63
|
+
text
|
|
64
|
+
content={formatMessage(
|
|
65
|
+
content[MESSAGE_ID],
|
|
66
|
+
translateParams(content[MESSAGE_PARAMS])
|
|
67
|
+
)}
|
|
68
|
+
/>
|
|
69
|
+
))}
|
|
70
|
+
</Feed.Content>
|
|
71
|
+
</Feed.Event>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
EventRow.propTypes = {
|
|
76
|
+
user: PropTypes.object.isRequired,
|
|
77
|
+
ts: PropTypes.string.isRequired,
|
|
78
|
+
payload: PropTypes.array.isRequired,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default function QualityControlEvents() {
|
|
82
|
+
const { qualityControl, loading: qualityControlLoading } = use(QxContext);
|
|
83
|
+
const { data, error, loading } = useEvents(
|
|
84
|
+
qualityControl.id,
|
|
85
|
+
"quality_control"
|
|
86
|
+
);
|
|
87
|
+
const events = data?.data || [];
|
|
88
|
+
const parsedEvents = useMemo(() => getParsedEvents(events), [events]);
|
|
89
|
+
return (
|
|
90
|
+
<Segment
|
|
91
|
+
attached="bottom"
|
|
92
|
+
loading={loading || qualityControlLoading}
|
|
93
|
+
error={error}
|
|
94
|
+
>
|
|
95
|
+
<Feed size="small">
|
|
96
|
+
{parsedEvents.map((event, index) => (
|
|
97
|
+
<EventRow key={index} {...event} />
|
|
98
|
+
))}
|
|
99
|
+
</Feed>
|
|
100
|
+
</Segment>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
@@ -26,6 +26,7 @@ import NewQualityControl from "./NewQualityControl";
|
|
|
26
26
|
import EditQualityControl from "./EditQualityControl";
|
|
27
27
|
import NewDraftQualityControl from "./NewDraftQualityControl";
|
|
28
28
|
import { ScoreContextProvider } from "../scores/ScoreContext";
|
|
29
|
+
import QualityControlEvents from "./QualityControlEvents";
|
|
29
30
|
|
|
30
31
|
const LoaderQualityControlScores = () => {
|
|
31
32
|
const { id } = useParams();
|
|
@@ -75,7 +76,7 @@ export default function QualityControlRoutes() {
|
|
|
75
76
|
element={
|
|
76
77
|
<SearchContextProvider
|
|
77
78
|
{...searchProps}
|
|
78
|
-
defaultFilters={{ status: "draft" }}
|
|
79
|
+
defaultFilters={{ status: ["draft", "rejected"] }}
|
|
79
80
|
>
|
|
80
81
|
<QualityControls />
|
|
81
82
|
</SearchContextProvider>
|
|
@@ -95,6 +96,7 @@ export default function QualityControlRoutes() {
|
|
|
95
96
|
<Route index element={<QualityControl />} />
|
|
96
97
|
<Route path="history" element={<QualityControlHistory />} />
|
|
97
98
|
<Route path="scores" element={<LoaderQualityControlScores />} />
|
|
99
|
+
<Route path="events" element={<QualityControlEvents />} />
|
|
98
100
|
</Route>
|
|
99
101
|
</Routes>
|
|
100
102
|
);
|
|
@@ -21,6 +21,10 @@ export default function QualityControlTabs() {
|
|
|
21
21
|
url: linkTo.QUALITY_CONTROL_SCORES(urlParams),
|
|
22
22
|
text: "quality_control.tabs.scores",
|
|
23
23
|
},
|
|
24
|
+
{
|
|
25
|
+
url: linkTo.QUALITY_CONTROL_EVENTS(urlParams),
|
|
26
|
+
text: "quality_control.tabs.events",
|
|
27
|
+
},
|
|
24
28
|
];
|
|
25
29
|
|
|
26
30
|
return (
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
|
+
import { messages as baseMessages } from "@truedat/qx/components/__tests__/__fixtures__/helper";
|
|
4
|
+
import { useEvents } from "@truedat/audit/hooks/useEvents";
|
|
5
|
+
import QxContext from "../../QxContext";
|
|
6
|
+
import QualityControlEvents from "../QualityControlEvents";
|
|
7
|
+
|
|
8
|
+
jest.mock("@truedat/audit/hooks/useEvents", () => ({
|
|
9
|
+
useEvents: jest.fn(),
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
const messages = {
|
|
13
|
+
...baseMessages,
|
|
14
|
+
en: {
|
|
15
|
+
...baseMessages.en,
|
|
16
|
+
"quality_controls.events.action_created":
|
|
17
|
+
"Name: <b>{name}</b>, Version: <b>{field}</b>",
|
|
18
|
+
"quality_controls.events.action_field_changed":
|
|
19
|
+
"<b>{field}</b> changed to {value}",
|
|
20
|
+
"quality_controls.events.action_dynamic_field_changed":
|
|
21
|
+
"<b>{field}</b> updated",
|
|
22
|
+
"quality_controls.events.action_enabled": "Quality control enabled",
|
|
23
|
+
"quality_controls.events.action_disabled": "Quality control disabled",
|
|
24
|
+
"quality_controls.events.action_draft_version_created":
|
|
25
|
+
"Draft version <b>{value}</b> created",
|
|
26
|
+
"quality_controls.events.quality_control_created":
|
|
27
|
+
"created a new draft quality control",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const renderOpts = { messages };
|
|
32
|
+
|
|
33
|
+
afterEach(() => {
|
|
34
|
+
jest.clearAllMocks();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("<QualityControlEvents />", () => {
|
|
38
|
+
it("renders parsed events with highlighted fields", () => {
|
|
39
|
+
useEvents.mockReturnValue({
|
|
40
|
+
data: {
|
|
41
|
+
data: [
|
|
42
|
+
{
|
|
43
|
+
event: "quality_control_created",
|
|
44
|
+
payload: { name: "Sample control", version: "1.0" },
|
|
45
|
+
ts: "2024-01-01T00:00:00Z",
|
|
46
|
+
user: { user_name: "Jane Doe" },
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
error: null,
|
|
51
|
+
loading: false,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const contextValue = {
|
|
55
|
+
qualityControl: { id: "qc-1" },
|
|
56
|
+
loading: false,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const rendered = render(
|
|
60
|
+
<QxContext.Provider value={contextValue}>
|
|
61
|
+
<QualityControlEvents />
|
|
62
|
+
</QxContext.Provider>,
|
|
63
|
+
renderOpts
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
expect(rendered.container).toMatchSnapshot();
|
|
67
|
+
expect(useEvents).toHaveBeenCalledWith("qc-1", "quality_control");
|
|
68
|
+
expect(rendered.getByText(/jane doe/i)).toBeInTheDocument();
|
|
69
|
+
|
|
70
|
+
const boldField = rendered.getByText(/sample control/i);
|
|
71
|
+
expect(boldField.tagName).toBe("B");
|
|
72
|
+
expect(rendered.getByText(/created/i)).toBeInTheDocument();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("shows loading state when events are loading", () => {
|
|
76
|
+
useEvents.mockReturnValue({
|
|
77
|
+
data: null,
|
|
78
|
+
error: null,
|
|
79
|
+
loading: true,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const contextValue = {
|
|
83
|
+
qualityControl: { id: "qc-1" },
|
|
84
|
+
loading: false,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const rendered = render(
|
|
88
|
+
<QxContext.Provider value={contextValue}>
|
|
89
|
+
<QualityControlEvents />
|
|
90
|
+
</QxContext.Provider>,
|
|
91
|
+
renderOpts
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
expect(rendered.container.querySelector(".segment.loading")).toBeTruthy();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("shows loading state when quality control is loading", () => {
|
|
98
|
+
useEvents.mockReturnValue({
|
|
99
|
+
data: { data: [] },
|
|
100
|
+
error: null,
|
|
101
|
+
loading: false,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const contextValue = {
|
|
105
|
+
qualityControl: { id: "qc-1" },
|
|
106
|
+
loading: true,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const rendered = render(
|
|
110
|
+
<QxContext.Provider value={contextValue}>
|
|
111
|
+
<QualityControlEvents />
|
|
112
|
+
</QxContext.Provider>,
|
|
113
|
+
renderOpts
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
expect(rendered.container.querySelector(".segment.loading")).toBeTruthy();
|
|
117
|
+
});
|
|
118
|
+
});
|
package/src/components/qualityControls/__tests__/__snapshots__/QualityControlEvents.spec.js.snap
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`<QualityControlEvents /> renders parsed events with highlighted fields 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
class="ui bottom attached segment"
|
|
7
|
+
>
|
|
8
|
+
<div
|
|
9
|
+
class="ui small feed"
|
|
10
|
+
>
|
|
11
|
+
<div
|
|
12
|
+
class="event"
|
|
13
|
+
>
|
|
14
|
+
<div
|
|
15
|
+
class="content"
|
|
16
|
+
>
|
|
17
|
+
<div
|
|
18
|
+
class="summary"
|
|
19
|
+
>
|
|
20
|
+
<a
|
|
21
|
+
class="user"
|
|
22
|
+
>
|
|
23
|
+
Jane Doe
|
|
24
|
+
</a>
|
|
25
|
+
|
|
26
|
+
created a new draft quality control
|
|
27
|
+
|
|
28
|
+
<div
|
|
29
|
+
class="date"
|
|
30
|
+
>
|
|
31
|
+
<time
|
|
32
|
+
datetime="1704067200000"
|
|
33
|
+
>
|
|
34
|
+
2024-01-01 00:00
|
|
35
|
+
</time>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
<div
|
|
39
|
+
class="text extra"
|
|
40
|
+
>
|
|
41
|
+
Name:
|
|
42
|
+
<b>
|
|
43
|
+
Sample control
|
|
44
|
+
</b>
|
|
45
|
+
, Version:
|
|
46
|
+
<b>
|
|
47
|
+
1.0
|
|
48
|
+
</b>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
`;
|
package/src/components/qualityControls/__tests__/__snapshots__/QualityControlHeader.spec.js.snap
CHANGED
|
@@ -180,6 +180,13 @@ exports[`<QualityControlHeader /> matches the latest snapshot with control quali
|
|
|
180
180
|
>
|
|
181
181
|
quality_control.tabs.scores
|
|
182
182
|
</a>
|
|
183
|
+
<a
|
|
184
|
+
class="item"
|
|
185
|
+
data-discover="true"
|
|
186
|
+
href="/qualityControls/8/version/1/events"
|
|
187
|
+
>
|
|
188
|
+
quality_control.tabs.events
|
|
189
|
+
</a>
|
|
183
190
|
</div>
|
|
184
191
|
</div>
|
|
185
192
|
</div>
|
package/src/components/qualityControls/__tests__/__snapshots__/QualityControlTabs.spec.js.snap
CHANGED
|
@@ -26,6 +26,13 @@ exports[`<QualityControlTabs /> matches the latest snapshot 1`] = `
|
|
|
26
26
|
>
|
|
27
27
|
Scores
|
|
28
28
|
</a>
|
|
29
|
+
<a
|
|
30
|
+
class="item"
|
|
31
|
+
data-discover="true"
|
|
32
|
+
href="/qualityControls/8/version/1/events"
|
|
33
|
+
>
|
|
34
|
+
quality_control.tabs.events
|
|
35
|
+
</a>
|
|
29
36
|
</div>
|
|
30
37
|
</div>
|
|
31
38
|
`;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { getParsedEvents, bold } from "../getParsedEvents";
|
|
2
|
+
const user = { user_name: "Jane" };
|
|
3
|
+
const timestamp = "2024-01-01T00:00:00Z";
|
|
4
|
+
|
|
5
|
+
describe("getParsedEvents", () => {
|
|
6
|
+
it("returns payload for quality_control_created", () => {
|
|
7
|
+
const events = [
|
|
8
|
+
{
|
|
9
|
+
event: "quality_control_created",
|
|
10
|
+
payload: { name: "Control A" },
|
|
11
|
+
ts: timestamp,
|
|
12
|
+
user,
|
|
13
|
+
},
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
expect(getParsedEvents(events)).toEqual([
|
|
17
|
+
{
|
|
18
|
+
ts: timestamp,
|
|
19
|
+
user,
|
|
20
|
+
header: [{ id: "quality_controls.events.quality_control_created" }, {}],
|
|
21
|
+
payload: [
|
|
22
|
+
[
|
|
23
|
+
{ id: "quality_controls.events.action_created" },
|
|
24
|
+
{ name: "Control A", field: undefined, b: bold },
|
|
25
|
+
],
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
]);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("combines payload sections for quality_control_updated", () => {
|
|
32
|
+
const events = [
|
|
33
|
+
{
|
|
34
|
+
event: "quality_control_updated",
|
|
35
|
+
ts: timestamp,
|
|
36
|
+
user,
|
|
37
|
+
payload: {
|
|
38
|
+
changes: {
|
|
39
|
+
active: false,
|
|
40
|
+
name: "New name",
|
|
41
|
+
dynamic_content: {
|
|
42
|
+
threshold: { value: 10 },
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
expect(getParsedEvents(events)).toEqual([
|
|
49
|
+
{
|
|
50
|
+
ts: timestamp,
|
|
51
|
+
user,
|
|
52
|
+
header: [
|
|
53
|
+
{ id: "quality_controls.events.action_disabled" },
|
|
54
|
+
{ b: bold },
|
|
55
|
+
{ id: "quality_controls.events.quality_control_updated" },
|
|
56
|
+
{},
|
|
57
|
+
],
|
|
58
|
+
payload: [
|
|
59
|
+
[
|
|
60
|
+
{ id: "quality_controls.events.action_dynamic_field_changed" },
|
|
61
|
+
{ field: "threshold", value: 10, b: bold },
|
|
62
|
+
],
|
|
63
|
+
[
|
|
64
|
+
{ id: "quality_controls.events.action_field_changed" },
|
|
65
|
+
{ field: "name", value: "New name", b: bold },
|
|
66
|
+
],
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("returns payload for version status update", () => {
|
|
73
|
+
const events = [
|
|
74
|
+
{
|
|
75
|
+
event: "quality_control_version_status_updated",
|
|
76
|
+
payload: { action: "approved", version: "v2", status: "published" },
|
|
77
|
+
ts: timestamp,
|
|
78
|
+
user,
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
expect(getParsedEvents(events)).toEqual([
|
|
83
|
+
{
|
|
84
|
+
ts: timestamp,
|
|
85
|
+
user,
|
|
86
|
+
header: [
|
|
87
|
+
{ id: "quality_controls.events.action_approved" },
|
|
88
|
+
{
|
|
89
|
+
field: "v2",
|
|
90
|
+
lowercase: true,
|
|
91
|
+
value: { id: "quality_control.status.published" },
|
|
92
|
+
b: bold,
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
payload: [],
|
|
96
|
+
},
|
|
97
|
+
]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("returns payload for quality_control_updated with empty changes", () => {
|
|
101
|
+
const events = [
|
|
102
|
+
{
|
|
103
|
+
event: "quality_control_updated",
|
|
104
|
+
ts: timestamp,
|
|
105
|
+
user,
|
|
106
|
+
payload: {
|
|
107
|
+
version: "v1",
|
|
108
|
+
changes: {},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
expect(getParsedEvents(events)).toEqual([
|
|
114
|
+
{
|
|
115
|
+
ts: timestamp,
|
|
116
|
+
user,
|
|
117
|
+
header: [{ id: "quality_controls.events.quality_control_updated" }, {}],
|
|
118
|
+
payload: [
|
|
119
|
+
[
|
|
120
|
+
{ id: "quality_controls.events.action_updated" },
|
|
121
|
+
{ field: "v1", b: bold },
|
|
122
|
+
],
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
]);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("returns payload for quality_control_version_draft_updated with empty changes", () => {
|
|
129
|
+
const events = [
|
|
130
|
+
{
|
|
131
|
+
event: "quality_control_version_draft_updated",
|
|
132
|
+
ts: timestamp,
|
|
133
|
+
user,
|
|
134
|
+
payload: {
|
|
135
|
+
version: "v2",
|
|
136
|
+
changes: {},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
expect(getParsedEvents(events)).toEqual([
|
|
142
|
+
{
|
|
143
|
+
ts: timestamp,
|
|
144
|
+
user,
|
|
145
|
+
header: [{ id: "quality_controls.events.quality_control_updated" }, {}],
|
|
146
|
+
payload: [
|
|
147
|
+
[
|
|
148
|
+
{ id: "quality_controls.events.action_updated" },
|
|
149
|
+
{ field: "v2", b: bold },
|
|
150
|
+
],
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
]);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("returns empty array for quality_control_updated with non-empty changes", () => {
|
|
157
|
+
const events = [
|
|
158
|
+
{
|
|
159
|
+
event: "quality_control_updated",
|
|
160
|
+
ts: timestamp,
|
|
161
|
+
user,
|
|
162
|
+
payload: {
|
|
163
|
+
version: "v1",
|
|
164
|
+
changes: {
|
|
165
|
+
name: "Updated name",
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
expect(getParsedEvents(events)).toEqual([
|
|
172
|
+
{
|
|
173
|
+
ts: timestamp,
|
|
174
|
+
user,
|
|
175
|
+
header: [{ id: "quality_controls.events.quality_control_updated" }, {}],
|
|
176
|
+
payload: [
|
|
177
|
+
[
|
|
178
|
+
{ id: "quality_controls.events.action_field_changed" },
|
|
179
|
+
{ field: "name", value: "Updated name", b: bold },
|
|
180
|
+
],
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
]);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("filters out unsupported events", () => {
|
|
187
|
+
const events = [
|
|
188
|
+
{
|
|
189
|
+
event: "quality_control_deleted",
|
|
190
|
+
ts: timestamp,
|
|
191
|
+
user,
|
|
192
|
+
payload: {},
|
|
193
|
+
},
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
expect(getParsedEvents(events)).toEqual([]);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
|
|
3
|
+
export const bold = (text) => <b>{text}</b>;
|
|
4
|
+
|
|
5
|
+
const normalizeValue = (value) => {
|
|
6
|
+
if (_.isObject(value)) return JSON.stringify(value);
|
|
7
|
+
if (_.isBoolean(value)) return String(value);
|
|
8
|
+
return value;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const getHeaderFromActiveChange = (event) => {
|
|
12
|
+
if (_.has("payload.changes.active")(event)) {
|
|
13
|
+
return _.prop("payload.changes.active")(event)
|
|
14
|
+
? [{ id: "quality_controls.events.action_enabled" }, { b: bold }]
|
|
15
|
+
: [{ id: "quality_controls.events.action_disabled" }, { b: bold }];
|
|
16
|
+
}
|
|
17
|
+
return [];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getHeaderFromRegularFields = (event) => {
|
|
21
|
+
if (_.has("payload.changes")(event)) {
|
|
22
|
+
return [{ id: "quality_controls.events.quality_control_updated" }, {}];
|
|
23
|
+
}
|
|
24
|
+
return [];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const getDomainNames = (path) => (event) =>
|
|
28
|
+
_.flow(_.prop(path), _.defaultTo([]), _.map(_.prop("name")))(event);
|
|
29
|
+
|
|
30
|
+
const getPayloadFromDomainChange = (event) => {
|
|
31
|
+
if (_.has("payload.changes.domains")(event)) {
|
|
32
|
+
const changedDomainNames = _.join(", ")(
|
|
33
|
+
getDomainNames("payload.changes.domains")(event)
|
|
34
|
+
);
|
|
35
|
+
const currentDomainNames = _.join(", ")(
|
|
36
|
+
getDomainNames("payload.current_domains")(event)
|
|
37
|
+
);
|
|
38
|
+
return [
|
|
39
|
+
[
|
|
40
|
+
{ id: "quality_controls.events.action_domain_changed" },
|
|
41
|
+
{ currentDomainNames, changedDomainNames, b: bold },
|
|
42
|
+
],
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
return [];
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const formatScoreCriteriaParams = (type, value) => {
|
|
49
|
+
if (!_.isObject(value) || !type) return [];
|
|
50
|
+
|
|
51
|
+
const paramPairs =
|
|
52
|
+
type === "percentage"
|
|
53
|
+
? [
|
|
54
|
+
value.goal !== undefined && [
|
|
55
|
+
{ id: `quality_control.score_criteria.${type}.goal` },
|
|
56
|
+
value.goal,
|
|
57
|
+
],
|
|
58
|
+
value.minimum !== undefined && [
|
|
59
|
+
{ id: `quality_control.score_criteria.${type}.minimum` },
|
|
60
|
+
value.minimum,
|
|
61
|
+
],
|
|
62
|
+
]
|
|
63
|
+
: [
|
|
64
|
+
value.goal !== undefined && [
|
|
65
|
+
{ id: `quality_control.score_criteria.${type}.goal` },
|
|
66
|
+
value.goal,
|
|
67
|
+
],
|
|
68
|
+
value.maximum !== undefined && [
|
|
69
|
+
{ id: `quality_control.score_criteria.${type}.maximum` },
|
|
70
|
+
value.maximum,
|
|
71
|
+
],
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
return _.compact(paramPairs);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const getPayloadFromScoreCriteriaChange = (event) => {
|
|
78
|
+
if (_.has("payload.changes.score_criteria")(event)) {
|
|
79
|
+
return _.flow(
|
|
80
|
+
_.toPairs,
|
|
81
|
+
_.map(([type, value]) => {
|
|
82
|
+
const params = formatScoreCriteriaParams(type, value);
|
|
83
|
+
return [
|
|
84
|
+
{ id: "quality_controls.events.action_score_criteria_changed" },
|
|
85
|
+
{
|
|
86
|
+
type: { id: `quality_control.control_mode.${type}` },
|
|
87
|
+
params,
|
|
88
|
+
b: bold,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
})
|
|
92
|
+
)(event?.payload?.changes?.score_criteria);
|
|
93
|
+
}
|
|
94
|
+
return [];
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const getPayloadFromControlModeChange = (event) => {
|
|
98
|
+
if (_.has("payload.changes.control_mode")(event)) {
|
|
99
|
+
return [
|
|
100
|
+
[
|
|
101
|
+
{ id: "quality_controls.events.action_control_mode_changed" },
|
|
102
|
+
{
|
|
103
|
+
type: {
|
|
104
|
+
id: `quality_control.control_mode.${event?.payload?.changes?.control_mode}`,
|
|
105
|
+
},
|
|
106
|
+
params: [],
|
|
107
|
+
b: bold,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
return [];
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const getPayloadFromDynamicContentChange = (event) => {
|
|
116
|
+
const content = _.propOr({}, "payload.changes.dynamic_content")(event);
|
|
117
|
+
if (!_.isEmpty(content)) {
|
|
118
|
+
return _.flow(
|
|
119
|
+
_.toPairs,
|
|
120
|
+
_.map(([field, value]) => [
|
|
121
|
+
{ id: "quality_controls.events.action_dynamic_field_changed" },
|
|
122
|
+
{ field, value: normalizeValue(value?.value), b: bold },
|
|
123
|
+
])
|
|
124
|
+
)(content);
|
|
125
|
+
}
|
|
126
|
+
return [];
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const getPayloadFromQualityControlVersionUpdate = (event) => {
|
|
130
|
+
if (_.isEmpty(event?.payload?.changes)) {
|
|
131
|
+
return [
|
|
132
|
+
[
|
|
133
|
+
{ id: "quality_controls.events.action_updated" },
|
|
134
|
+
{ field: event?.payload?.version, b: bold },
|
|
135
|
+
],
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
return [];
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const getPayloadFromRegularFields = (event) => {
|
|
142
|
+
if (_.has("payload.changes")(event)) {
|
|
143
|
+
return _.flow(
|
|
144
|
+
_.omit(["dynamic_content"]),
|
|
145
|
+
_.omit(["domains"]),
|
|
146
|
+
_.omit(["active"]),
|
|
147
|
+
_.omit(["score_criteria"]),
|
|
148
|
+
_.omit(["control_mode"]),
|
|
149
|
+
_.toPairs,
|
|
150
|
+
_.map(([field, value]) => [
|
|
151
|
+
{ id: "quality_controls.events.action_field_changed" },
|
|
152
|
+
{ field, value: normalizeValue(value), b: bold },
|
|
153
|
+
])
|
|
154
|
+
)(event?.payload?.changes);
|
|
155
|
+
}
|
|
156
|
+
return [];
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const getHeaderFromUpdateEvent = (event) => {
|
|
160
|
+
const headerFromActiveChange = getHeaderFromActiveChange(event);
|
|
161
|
+
const headerFromRegularFields = getHeaderFromRegularFields(event);
|
|
162
|
+
|
|
163
|
+
return [...headerFromActiveChange, ...headerFromRegularFields];
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const getPayloadFromUpdateEvent = (event) => {
|
|
167
|
+
const payloadFromRegularFields = getPayloadFromRegularFields(event);
|
|
168
|
+
const payloadFromDomainChange = getPayloadFromDomainChange(event);
|
|
169
|
+
const payloadFromScoreCriteriaChange =
|
|
170
|
+
getPayloadFromScoreCriteriaChange(event);
|
|
171
|
+
const payloadFromControlModeChange = getPayloadFromControlModeChange(event);
|
|
172
|
+
const payloadFromDynamicContentChange =
|
|
173
|
+
getPayloadFromDynamicContentChange(event);
|
|
174
|
+
const playloadFromQualityControlVersionUpdate =
|
|
175
|
+
getPayloadFromQualityControlVersionUpdate(event);
|
|
176
|
+
|
|
177
|
+
return [
|
|
178
|
+
...payloadFromControlModeChange,
|
|
179
|
+
...payloadFromScoreCriteriaChange,
|
|
180
|
+
...payloadFromDomainChange,
|
|
181
|
+
...payloadFromDynamicContentChange,
|
|
182
|
+
...payloadFromRegularFields,
|
|
183
|
+
...playloadFromQualityControlVersionUpdate,
|
|
184
|
+
];
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
const payloadFromEvent = (event) => {
|
|
188
|
+
const eventBase = _.pick(["ts", "user"])(event);
|
|
189
|
+
|
|
190
|
+
switch (event.event) {
|
|
191
|
+
case "quality_control_created":
|
|
192
|
+
return {
|
|
193
|
+
...eventBase,
|
|
194
|
+
header: [{ id: "quality_controls.events.quality_control_created" }, {}],
|
|
195
|
+
payload: [
|
|
196
|
+
[
|
|
197
|
+
{ id: "quality_controls.events.action_created" },
|
|
198
|
+
{
|
|
199
|
+
name: event?.payload?.name,
|
|
200
|
+
field: event?.payload?.version,
|
|
201
|
+
b: bold,
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
],
|
|
205
|
+
};
|
|
206
|
+
case "quality_control_version_status_updated":
|
|
207
|
+
return {
|
|
208
|
+
...eventBase,
|
|
209
|
+
header: [
|
|
210
|
+
{ id: `quality_controls.events.action_${event?.payload?.action}` },
|
|
211
|
+
{
|
|
212
|
+
field: event?.payload?.version,
|
|
213
|
+
value: { id: `quality_control.status.${event?.payload?.status}` },
|
|
214
|
+
lowercase: true,
|
|
215
|
+
b: bold,
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
payload: [],
|
|
219
|
+
};
|
|
220
|
+
case "quality_control_version_draft_created":
|
|
221
|
+
return {
|
|
222
|
+
...eventBase,
|
|
223
|
+
header: [
|
|
224
|
+
{
|
|
225
|
+
id: "quality_controls.events.quality_control_version_draft_created",
|
|
226
|
+
},
|
|
227
|
+
{},
|
|
228
|
+
],
|
|
229
|
+
payload: [
|
|
230
|
+
[
|
|
231
|
+
{ id: "quality_controls.events.action_draft_version_created" },
|
|
232
|
+
{ value: event?.payload?.version, b: bold },
|
|
233
|
+
],
|
|
234
|
+
],
|
|
235
|
+
};
|
|
236
|
+
case "quality_control_updated":
|
|
237
|
+
return {
|
|
238
|
+
...eventBase,
|
|
239
|
+
header: getHeaderFromUpdateEvent(event),
|
|
240
|
+
payload: getPayloadFromUpdateEvent(event),
|
|
241
|
+
};
|
|
242
|
+
case "quality_control_version_draft_updated":
|
|
243
|
+
return {
|
|
244
|
+
...eventBase,
|
|
245
|
+
header: getHeaderFromUpdateEvent(event),
|
|
246
|
+
payload: getPayloadFromUpdateEvent(event),
|
|
247
|
+
};
|
|
248
|
+
default:
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
export const getParsedEvents = (events) => {
|
|
253
|
+
return events.map(payloadFromEvent).filter(Boolean);
|
|
254
|
+
};
|