@truedat/bg 7.12.6 → 7.13.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/concepts/components/EventRow.js +14 -10
- package/src/concepts/components/__tests__/Events.spec.js +26 -0
- package/src/concepts/components/__tests__/__snapshots__/Events.spec.js.snap +77 -11
- package/src/concepts/relations/components/ConceptLinkActions.js +14 -9
- package/src/concepts/relations/components/__tests__/ConceptLinkActions.spec.js +116 -0
- package/src/concepts/relations/components/__tests__/__snapshots__/ConceptLinkActions.spec.js.snap +23 -0
- package/src/concepts/selectors/__tests__/getParsedEvents.spec.js +892 -2
- package/src/concepts/selectors/getParsedEvents.js +127 -63
- package/src/concepts/styles/conceptAuditEventVia.less +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/bg",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.13.1",
|
|
4
4
|
"description": "Truedat Web Business Glossary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@testing-library/jest-dom": "^6.6.3",
|
|
49
49
|
"@testing-library/react": "^16.3.0",
|
|
50
50
|
"@testing-library/user-event": "^14.6.1",
|
|
51
|
-
"@truedat/test": "7.
|
|
51
|
+
"@truedat/test": "7.13.1",
|
|
52
52
|
"identity-obj-proxy": "^3.0.0",
|
|
53
53
|
"jest": "^29.7.0",
|
|
54
54
|
"redux-saga-test-plan": "^4.0.6"
|
|
@@ -81,5 +81,5 @@
|
|
|
81
81
|
"semantic-ui-react": "^3.0.0-beta.2",
|
|
82
82
|
"swr": "^2.3.3"
|
|
83
83
|
},
|
|
84
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "17c040e6539b00eab7870d0d82ac91910e85b7ac"
|
|
85
85
|
}
|
|
@@ -7,6 +7,7 @@ import Moment from "react-moment";
|
|
|
7
7
|
export const EventRow = ({ user, user_name, event, ts, payload }) => {
|
|
8
8
|
const { formatMessage, locale } = useIntl();
|
|
9
9
|
const userName = _.propOr(user_name, "user_name")(user);
|
|
10
|
+
const eventVia = payload.length > 0 ? payload[0].msg_via : null;
|
|
10
11
|
|
|
11
12
|
return (
|
|
12
13
|
<Feed.Event>
|
|
@@ -14,20 +15,23 @@ export const EventRow = ({ user, user_name, event, ts, payload }) => {
|
|
|
14
15
|
<Feed.Summary>
|
|
15
16
|
<Feed.User>{userName}</Feed.User>{" "}
|
|
16
17
|
{formatMessage({ id: `concept.events.${event}` })}{" "}
|
|
18
|
+
{eventVia ? <span className="audit-event-via">{formatMessage({ id: `audit.events.via.${eventVia}` })}</span> : null}{" "}
|
|
17
19
|
<Feed.Date>
|
|
18
20
|
<Moment locale={locale} date={ts} format="YYYY-MM-DD HH:mm" />
|
|
19
21
|
</Feed.Date>
|
|
20
22
|
</Feed.Summary>
|
|
21
|
-
{payload.map(({ msg_key, msg_params }, i) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
{payload.map(({ msg_key, msg_params }, i) =>
|
|
24
|
+
msg_key ? (
|
|
25
|
+
<Feed.Extra
|
|
26
|
+
key={i}
|
|
27
|
+
text
|
|
28
|
+
content={formatMessage(
|
|
29
|
+
{ id: `concept.events.extra.${msg_key}` },
|
|
30
|
+
msg_params
|
|
31
|
+
)}
|
|
32
|
+
/>
|
|
33
|
+
) : null
|
|
34
|
+
)}
|
|
31
35
|
</Feed.Content>
|
|
32
36
|
</Feed.Event>
|
|
33
37
|
);
|
|
@@ -28,4 +28,30 @@ describe("<Events />", () => {
|
|
|
28
28
|
await waitForLoad(rendered);
|
|
29
29
|
expect(rendered.container).toMatchSnapshot();
|
|
30
30
|
});
|
|
31
|
+
it("matches the latest snapshot using payload with msg_key, msg_params and msg_via", async () => {
|
|
32
|
+
const events = [
|
|
33
|
+
{
|
|
34
|
+
id: 1,
|
|
35
|
+
event: "new_concept_draft",
|
|
36
|
+
service: "My invented service 1",
|
|
37
|
+
resource_id: 2,
|
|
38
|
+
payload: [
|
|
39
|
+
{ msg_key: "created_version", msg_params: ["1"], msg_via: "single_update" },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 2,
|
|
44
|
+
event: "concept_published",
|
|
45
|
+
service: "My invented service 2",
|
|
46
|
+
resource_id: 2,
|
|
47
|
+
payload: [
|
|
48
|
+
{ msg_via: "file" },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
const props = { events };
|
|
53
|
+
const rendered = render(<Events {...props} />);
|
|
54
|
+
await waitForLoad(rendered);
|
|
55
|
+
expect(rendered.container).toMatchSnapshot();
|
|
56
|
+
});
|
|
31
57
|
});
|
|
@@ -23,6 +23,7 @@ exports[`<Events /> matches the latest snapshot 1`] = `
|
|
|
23
23
|
|
|
24
24
|
concept.events.undefined
|
|
25
25
|
|
|
26
|
+
|
|
26
27
|
<div
|
|
27
28
|
class="date"
|
|
28
29
|
>
|
|
@@ -33,18 +34,49 @@ exports[`<Events /> matches the latest snapshot 1`] = `
|
|
|
33
34
|
</time>
|
|
34
35
|
</div>
|
|
35
36
|
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
<div
|
|
40
|
+
class="event"
|
|
41
|
+
>
|
|
42
|
+
<div
|
|
43
|
+
class="content"
|
|
44
|
+
>
|
|
36
45
|
<div
|
|
37
|
-
class="
|
|
38
|
-
>
|
|
39
|
-
concept.events.extra.undefined
|
|
40
|
-
</div>
|
|
41
|
-
<div
|
|
42
|
-
class="text extra"
|
|
46
|
+
class="summary"
|
|
43
47
|
>
|
|
44
|
-
|
|
48
|
+
<a
|
|
49
|
+
class="user"
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
concept.events.undefined
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
<div
|
|
56
|
+
class="date"
|
|
57
|
+
>
|
|
58
|
+
<time
|
|
59
|
+
datetime="1735689600000"
|
|
60
|
+
>
|
|
61
|
+
2025-01-01 00:00
|
|
62
|
+
</time>
|
|
63
|
+
</div>
|
|
45
64
|
</div>
|
|
46
65
|
</div>
|
|
47
66
|
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
exports[`<Events /> matches the latest snapshot using payload with msg_key, msg_params and msg_via 1`] = `
|
|
73
|
+
<div>
|
|
74
|
+
<div
|
|
75
|
+
class="ui bottom attached segment"
|
|
76
|
+
>
|
|
77
|
+
<div
|
|
78
|
+
class="ui small feed"
|
|
79
|
+
>
|
|
48
80
|
<div
|
|
49
81
|
class="event"
|
|
50
82
|
>
|
|
@@ -58,7 +90,13 @@ exports[`<Events /> matches the latest snapshot 1`] = `
|
|
|
58
90
|
class="user"
|
|
59
91
|
/>
|
|
60
92
|
|
|
61
|
-
concept.events.
|
|
93
|
+
concept.events.new_concept_draft
|
|
94
|
+
|
|
95
|
+
<span
|
|
96
|
+
class="audit-event-via"
|
|
97
|
+
>
|
|
98
|
+
audit.events.via.single_update
|
|
99
|
+
</span>
|
|
62
100
|
|
|
63
101
|
<div
|
|
64
102
|
class="date"
|
|
@@ -73,12 +111,40 @@ exports[`<Events /> matches the latest snapshot 1`] = `
|
|
|
73
111
|
<div
|
|
74
112
|
class="text extra"
|
|
75
113
|
>
|
|
76
|
-
concept.events.extra.
|
|
114
|
+
concept.events.extra.created_version
|
|
77
115
|
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
<div
|
|
119
|
+
class="event"
|
|
120
|
+
>
|
|
121
|
+
<div
|
|
122
|
+
class="content"
|
|
123
|
+
>
|
|
78
124
|
<div
|
|
79
|
-
class="
|
|
125
|
+
class="summary"
|
|
80
126
|
>
|
|
81
|
-
|
|
127
|
+
<a
|
|
128
|
+
class="user"
|
|
129
|
+
/>
|
|
130
|
+
|
|
131
|
+
concept.events.concept_published
|
|
132
|
+
|
|
133
|
+
<span
|
|
134
|
+
class="audit-event-via"
|
|
135
|
+
>
|
|
136
|
+
audit.events.via.file
|
|
137
|
+
</span>
|
|
138
|
+
|
|
139
|
+
<div
|
|
140
|
+
class="date"
|
|
141
|
+
>
|
|
142
|
+
<time
|
|
143
|
+
datetime="1735689600000"
|
|
144
|
+
>
|
|
145
|
+
2025-01-01 00:00
|
|
146
|
+
</time>
|
|
147
|
+
</div>
|
|
82
148
|
</div>
|
|
83
149
|
</div>
|
|
84
150
|
</div>
|
|
@@ -5,11 +5,18 @@ import { connect } from "react-redux";
|
|
|
5
5
|
import { Button, Icon } from "semantic-ui-react";
|
|
6
6
|
import { FormattedMessage } from "react-intl";
|
|
7
7
|
import { ConfirmModal } from "@truedat/core/components";
|
|
8
|
-
import {
|
|
8
|
+
import { deleteRelation } from "@truedat/lm/routines";
|
|
9
9
|
|
|
10
|
-
export const DeleteLink = ({
|
|
10
|
+
export const DeleteLink = ({ deleteRelation, action: { href }, loading }) => {
|
|
11
11
|
const [openModal, setOpenModal] = useState(false);
|
|
12
12
|
|
|
13
|
+
const handleDelete = () => {
|
|
14
|
+
const linkId = href ? parseInt(href.match(/\/links\/(\d+)$/)?.[1]) : null;
|
|
15
|
+
if (linkId) {
|
|
16
|
+
deleteRelation({ id: linkId });
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
13
20
|
return loading ? (
|
|
14
21
|
<Icon loading name="circle notch" color="red" />
|
|
15
22
|
) : (
|
|
@@ -33,7 +40,7 @@ export const DeleteLink = ({ conceptLinkAction, action, loading }) => {
|
|
|
33
40
|
content={
|
|
34
41
|
<FormattedMessage id="relations.actions.data_field.delete.confirmation.content" />
|
|
35
42
|
}
|
|
36
|
-
onConfirm={
|
|
43
|
+
onConfirm={handleDelete}
|
|
37
44
|
onOpen={() => {
|
|
38
45
|
setOpenModal(true);
|
|
39
46
|
}}
|
|
@@ -46,18 +53,16 @@ export const DeleteLink = ({ conceptLinkAction, action, loading }) => {
|
|
|
46
53
|
};
|
|
47
54
|
|
|
48
55
|
DeleteLink.propTypes = {
|
|
49
|
-
|
|
56
|
+
deleteRelation: PropTypes.func,
|
|
50
57
|
action: PropTypes.object,
|
|
51
58
|
loading: PropTypes.bool,
|
|
52
59
|
};
|
|
53
60
|
|
|
54
|
-
const mapStateToProps = ({
|
|
55
|
-
loading: _.pathEq("
|
|
61
|
+
const mapStateToProps = ({ deleteRelationLoading }, { action }) => ({
|
|
62
|
+
loading: _.pathEq("id")(deleteRelationLoading)(action),
|
|
56
63
|
});
|
|
57
64
|
|
|
58
|
-
export const DeleteLinkConnected = connect(mapStateToProps, {
|
|
59
|
-
conceptLinkAction,
|
|
60
|
-
})(DeleteLink);
|
|
65
|
+
export const DeleteLinkConnected = connect(mapStateToProps, { deleteRelation, })(DeleteLink);
|
|
61
66
|
|
|
62
67
|
export const LinkActions = ({ delete: deleteAction }) =>
|
|
63
68
|
deleteAction ? <DeleteLinkConnected action={deleteAction} /> : null;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
4
|
+
import { DeleteLink } from "../ConceptLinkActions";
|
|
5
|
+
|
|
6
|
+
describe("ConceptLinkActions", () => {
|
|
7
|
+
describe("DeleteLink", () => {
|
|
8
|
+
const deleteRelation = jest.fn();
|
|
9
|
+
const user = userEvent.setup({ delay: null });
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
jest.clearAllMocks();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("should render loading icon when loading is true", () => {
|
|
16
|
+
const action = { href: "/api/links/123" };
|
|
17
|
+
const rendered = render(
|
|
18
|
+
<DeleteLink deleteRelation={deleteRelation} action={action} loading={true} />
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
expect(rendered.container.querySelector(".icon.loading")).toBeInTheDocument();
|
|
22
|
+
expect(rendered.container).toMatchSnapshot();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should render delete button when loading is false", async () => {
|
|
26
|
+
const action = { href: "/api/links/123" };
|
|
27
|
+
const rendered = render(
|
|
28
|
+
<DeleteLink deleteRelation={deleteRelation} action={action} loading={false} />
|
|
29
|
+
);
|
|
30
|
+
await waitForLoad(rendered);
|
|
31
|
+
|
|
32
|
+
expect(rendered.getByRole("button")).toBeInTheDocument();
|
|
33
|
+
expect(rendered.container).toMatchSnapshot();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should extract link id from href and call deleteRelation on confirm", async () => {
|
|
37
|
+
const action = { href: "/api/links/456" };
|
|
38
|
+
const rendered = render(
|
|
39
|
+
<DeleteLink deleteRelation={deleteRelation} action={action} loading={false} />
|
|
40
|
+
);
|
|
41
|
+
await waitForLoad(rendered);
|
|
42
|
+
|
|
43
|
+
await user.click(rendered.getByRole("button"));
|
|
44
|
+
|
|
45
|
+
const confirmButton = rendered.getByLabelText("modal-affirmative-action");
|
|
46
|
+
await user.click(confirmButton);
|
|
47
|
+
|
|
48
|
+
expect(deleteRelation).toHaveBeenCalledWith({ id: 456 });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should handle href without link id", async () => {
|
|
52
|
+
const action = { href: "/api/other/endpoint" };
|
|
53
|
+
const rendered = render(
|
|
54
|
+
<DeleteLink deleteRelation={deleteRelation} action={action} loading={false} />
|
|
55
|
+
);
|
|
56
|
+
await waitForLoad(rendered);
|
|
57
|
+
|
|
58
|
+
await user.click(rendered.getByRole("button"));
|
|
59
|
+
|
|
60
|
+
const confirmButton = rendered.getByLabelText("modal-affirmative-action");
|
|
61
|
+
await user.click(confirmButton);
|
|
62
|
+
|
|
63
|
+
expect(deleteRelation).not.toHaveBeenCalled();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should handle null href", async () => {
|
|
67
|
+
const action = { href: null };
|
|
68
|
+
const rendered = render(
|
|
69
|
+
<DeleteLink deleteRelation={deleteRelation} action={action} loading={false} />
|
|
70
|
+
);
|
|
71
|
+
await waitForLoad(rendered);
|
|
72
|
+
|
|
73
|
+
await user.click(rendered.getByRole("button"));
|
|
74
|
+
|
|
75
|
+
const confirmButton = rendered.getByLabelText("modal-affirmative-action");
|
|
76
|
+
await user.click(confirmButton);
|
|
77
|
+
|
|
78
|
+
expect(deleteRelation).not.toHaveBeenCalled();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should handle undefined href", async () => {
|
|
82
|
+
const action = {};
|
|
83
|
+
const rendered = render(
|
|
84
|
+
<DeleteLink deleteRelation={deleteRelation} action={action} loading={false} />
|
|
85
|
+
);
|
|
86
|
+
await waitForLoad(rendered);
|
|
87
|
+
|
|
88
|
+
await user.click(rendered.getByRole("button"));
|
|
89
|
+
|
|
90
|
+
const confirmButton = rendered.getByLabelText("modal-affirmative-action");
|
|
91
|
+
await user.click(confirmButton);
|
|
92
|
+
|
|
93
|
+
expect(deleteRelation).not.toHaveBeenCalled();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("should open and close modal correctly", async () => {
|
|
97
|
+
const action = { href: "/api/links/789" };
|
|
98
|
+
const rendered = render(
|
|
99
|
+
<DeleteLink deleteRelation={deleteRelation} action={action} loading={false} />
|
|
100
|
+
);
|
|
101
|
+
await waitForLoad(rendered);
|
|
102
|
+
|
|
103
|
+
await user.click(rendered.getByRole("button"));
|
|
104
|
+
|
|
105
|
+
const confirmButton = rendered.getByLabelText("modal-affirmative-action");
|
|
106
|
+
expect(confirmButton).toBeInTheDocument();
|
|
107
|
+
|
|
108
|
+
const cancelButton = rendered.getByLabelText("modal-negative-action");
|
|
109
|
+
await user.click(cancelButton);
|
|
110
|
+
|
|
111
|
+
expect(rendered.queryByLabelText("modal-affirmative-action")).not.toBeInTheDocument();
|
|
112
|
+
expect(deleteRelation).not.toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
package/src/concepts/relations/components/__tests__/__snapshots__/ConceptLinkActions.spec.js.snap
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`ConceptLinkActions DeleteLink should render delete button when loading is false 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<button
|
|
6
|
+
class="ui red mini basic icon button"
|
|
7
|
+
>
|
|
8
|
+
<i
|
|
9
|
+
aria-hidden="true"
|
|
10
|
+
class="red trash alternate outline icon"
|
|
11
|
+
/>
|
|
12
|
+
</button>
|
|
13
|
+
</div>
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
exports[`ConceptLinkActions DeleteLink should render loading icon when loading is true 1`] = `
|
|
17
|
+
<div>
|
|
18
|
+
<i
|
|
19
|
+
aria-hidden="true"
|
|
20
|
+
class="red circle notch loading icon"
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
23
|
+
`;
|