@kiva/kv-components 3.54.0 → 3.55.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/CHANGELOG.md +26 -0
- package/package.json +2 -2
- package/tests/fixtures/mockFeedActivityData.js +136 -9
- package/tests/unit/specs/components/KvCommentsAdd.spec.js +39 -5
- package/tests/unit/specs/components/KvCommentsContainer.spec.js +8 -3
- package/tests/unit/specs/components/KvCommentsHeartButton.spec.js +1 -1
- package/tests/unit/specs/components/KvCommentsList.spec.js +29 -6
- package/tests/unit/specs/components/KvCommentsListItem.spec.js +44 -12
- package/tests/unit/specs/components/KvCommentsReplyButton.spec.js +23 -0
- package/vue/KvCommentsAdd.vue +25 -3
- package/vue/KvCommentsContainer.vue +29 -11
- package/vue/KvCommentsHeartButton.vue +3 -7
- package/vue/KvCommentsList.vue +38 -8
- package/vue/KvCommentsListItem.vue +133 -68
- package/vue/KvCommentsReplyButton.vue +34 -0
- package/vue/stories/KvCommentsContainer.stories.js +12 -1
- package/vue/stories/KvCommentsList.stories.js +9 -0
- package/vue/stories/KvCommentsListItem.stories.js +13 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,32 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [3.55.1](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.55.0...@kiva/kv-components@3.55.1) (2024-02-29)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @kiva/kv-components
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [3.55.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.54.0...@kiva/kv-components@3.55.0) (2024-02-29)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* input width ([2489339](https://github.com/kiva/kv-ui-elements/commit/2489339c622ac45739bcc1eefc0a69837f90b841))
|
|
20
|
+
* when to send hide event and test not recognizing vue3 ([c3941a7](https://github.com/kiva/kv-ui-elements/commit/c3941a7a73a439846e6abf16b6dd0b29fa0e36f7))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* adding input for comment reply ([b18edf0](https://github.com/kiva/kv-ui-elements/commit/b18edf0ecd300f622379d160237fd750cf117fa1))
|
|
26
|
+
* update tests and remove handleClick for emits ([fc3c586](https://github.com/kiva/kv-ui-elements/commit/fc3c58667248fb4e44bb0a7558f6c88f97f299b1))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
6
32
|
# [3.54.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.53.0...@kiva/kv-components@3.54.0) (2024-02-28)
|
|
7
33
|
|
|
8
34
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kiva/kv-components",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.55.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"optional": true
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "c8fdabba600d0e9b03143a90a2d8681abde09adb"
|
|
79
79
|
}
|
|
@@ -16,26 +16,151 @@ const comments = {
|
|
|
16
16
|
created_at: '2024-02-01T20:12:31.398932Z',
|
|
17
17
|
updated_at: '2024-02-01T20:12:31.398932Z',
|
|
18
18
|
id: 'dade3812-6aa0-4c32-90ea-2366dab178a1',
|
|
19
|
-
user_id: '1de650a5-b12f-4d20-b46c-6e15b0722141',
|
|
20
19
|
kind: 'comment',
|
|
21
20
|
activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
|
|
22
21
|
data: {
|
|
23
22
|
text: 'another guest comment',
|
|
24
23
|
},
|
|
24
|
+
user: {
|
|
25
|
+
data: {
|
|
26
|
+
publicLenderId: 'Nathan2352',
|
|
27
|
+
name: 'Nathan',
|
|
28
|
+
image: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg', // eslint-disable-line max-len
|
|
29
|
+
},
|
|
30
|
+
},
|
|
25
31
|
parent: '',
|
|
26
|
-
latest_children: {
|
|
32
|
+
latest_children: {
|
|
33
|
+
like: [
|
|
34
|
+
{
|
|
35
|
+
created_at: '2024-02-28T20:04:21.445272Z',
|
|
36
|
+
updated_at: '2024-02-28T20:04:21.445272Z',
|
|
37
|
+
id: '290a6c07-143a-416e-b016-ac0d9ac8ad91',
|
|
38
|
+
user: {
|
|
39
|
+
created_at: '2024-02-28T19:09:54.093757Z',
|
|
40
|
+
updated_at: '2024-02-28T19:09:54.093757Z',
|
|
41
|
+
data: {
|
|
42
|
+
publicLenderId: 'Jess1234',
|
|
43
|
+
name: 'Jess',
|
|
44
|
+
image: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg', // eslint-disable-line max-len
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
kind: 'like',
|
|
48
|
+
activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
|
|
49
|
+
data: {},
|
|
50
|
+
parent: '6384df77-d7c4-4ea9-b1b9-ef1c76a054a2',
|
|
51
|
+
latest_children: {},
|
|
52
|
+
children_counts: {},
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
comment: [
|
|
56
|
+
{
|
|
57
|
+
created_at: '2024-02-28T20:04:21.445272Z',
|
|
58
|
+
updated_at: '2024-02-28T20:04:21.445272Z',
|
|
59
|
+
id: '290a6c07-143a-416e-b016-ac0d9ac8ad92',
|
|
60
|
+
user: {
|
|
61
|
+
data: {
|
|
62
|
+
publicLenderId: 'Casey1234',
|
|
63
|
+
name: 'Casey',
|
|
64
|
+
image: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg', // eslint-disable-line max-len
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
kind: 'comment',
|
|
68
|
+
activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
|
|
69
|
+
data: {
|
|
70
|
+
text: 'child comment',
|
|
71
|
+
},
|
|
72
|
+
parent: '6384df77-d7c4-4ea9-b1b9-ef1c76a054a2',
|
|
73
|
+
latest_children: {
|
|
74
|
+
comment: [
|
|
75
|
+
{
|
|
76
|
+
created_at: '2024-02-28T20:04:21.445272Z',
|
|
77
|
+
updated_at: '2024-02-28T20:04:21.445272Z',
|
|
78
|
+
id: '290a6c07-143a-416e-b016-ac0d9ac8ad93',
|
|
79
|
+
user: {
|
|
80
|
+
data: {
|
|
81
|
+
publicLenderId: 'Sarah1234',
|
|
82
|
+
name: 'Sarah',
|
|
83
|
+
image: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg', // eslint-disable-line max-len
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
kind: 'comment',
|
|
87
|
+
activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
|
|
88
|
+
data: {
|
|
89
|
+
text: 'child comment reply',
|
|
90
|
+
},
|
|
91
|
+
parent: '6384df77-d7c4-4ea9-b1b9-ef1c76a054a2',
|
|
92
|
+
latest_children: {},
|
|
93
|
+
children_counts: {},
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
children_counts: {},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
created_at: '2024-02-28T20:04:21.445272Z',
|
|
101
|
+
updated_at: '2024-02-28T20:04:21.445272Z',
|
|
102
|
+
id: '290a6c07-143a-416e-b016-ac0d9ac8ad90',
|
|
103
|
+
user: {
|
|
104
|
+
data: {
|
|
105
|
+
publicLenderId: 'Sophie1234',
|
|
106
|
+
name: 'Sophie',
|
|
107
|
+
image: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg', // eslint-disable-line max-len
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
kind: 'comment',
|
|
111
|
+
activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
|
|
112
|
+
data: {
|
|
113
|
+
text: 'second child comment',
|
|
114
|
+
},
|
|
115
|
+
parent: '6384df77-d7c4-4ea9-b1b9-ef1c76a054a2',
|
|
116
|
+
latest_children: {
|
|
117
|
+
like: [
|
|
118
|
+
{
|
|
119
|
+
created_at: '2024-02-28T20:04:21.445272Z',
|
|
120
|
+
updated_at: '2024-02-28T20:04:21.445272Z',
|
|
121
|
+
id: '290a6c07-143a-416e-b016-ac0d9ac8ad99',
|
|
122
|
+
user: {
|
|
123
|
+
created_at: '2024-02-28T19:09:54.093757Z',
|
|
124
|
+
updated_at: '2024-02-28T19:09:54.093757Z',
|
|
125
|
+
data: {
|
|
126
|
+
publicLenderId: 'Jess1234',
|
|
127
|
+
name: 'Jess',
|
|
128
|
+
image: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg', // eslint-disable-line max-len
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
kind: 'like',
|
|
132
|
+
activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
|
|
133
|
+
data: {},
|
|
134
|
+
parent: '6384df77-d7c4-4ea9-b1b9-ef1c76a054a2',
|
|
135
|
+
latest_children: {},
|
|
136
|
+
children_counts: {},
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
children_counts: {},
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
},
|
|
27
144
|
children_counts: {},
|
|
28
145
|
},
|
|
29
146
|
{
|
|
30
147
|
created_at: '2024-02-01T20:11:23.931133Z',
|
|
31
148
|
updated_at: '2024-02-01T20:11:23.931133Z',
|
|
32
149
|
id: '3de615bb-0d48-4a69-9004-141ee26985eb',
|
|
33
|
-
user_id: '1de650a5-b12f-4d20-b46c-6e15b0722141',
|
|
34
150
|
kind: 'comment',
|
|
35
151
|
activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
|
|
36
152
|
data: {
|
|
37
153
|
text: 'test as visitor',
|
|
38
154
|
},
|
|
155
|
+
user: {
|
|
156
|
+
created_at: '2024-02-28T19:09:54.093757Z',
|
|
157
|
+
updated_at: '2024-02-28T19:09:54.093757Z',
|
|
158
|
+
data: {
|
|
159
|
+
publicLenderId: 'Lauren1234',
|
|
160
|
+
name: '',
|
|
161
|
+
image: '',
|
|
162
|
+
},
|
|
163
|
+
},
|
|
39
164
|
parent: '',
|
|
40
165
|
latest_children: {},
|
|
41
166
|
children_counts: {},
|
|
@@ -45,17 +170,19 @@ const comments = {
|
|
|
45
170
|
created_at: '2024-02-01T20:06:46.651764Z',
|
|
46
171
|
updated_at: '2024-02-01T20:06:46.651764Z',
|
|
47
172
|
id: 'e1db4420-159e-4ba2-aab9-704d1cc56dae',
|
|
48
|
-
user_id: '123',
|
|
49
173
|
user: {
|
|
50
|
-
created_at: '2024-02-
|
|
51
|
-
updated_at: '2024-02-
|
|
52
|
-
|
|
53
|
-
|
|
174
|
+
created_at: '2024-02-28T19:09:54.093757Z',
|
|
175
|
+
updated_at: '2024-02-28T19:09:54.093757Z',
|
|
176
|
+
data: {
|
|
177
|
+
publicLenderId: 'Todd1234',
|
|
178
|
+
name: 'Todd',
|
|
179
|
+
image: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg', // eslint-disable-line max-len
|
|
180
|
+
},
|
|
54
181
|
},
|
|
55
182
|
kind: 'comment',
|
|
56
183
|
activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
|
|
57
184
|
data: {
|
|
58
|
-
text: '
|
|
185
|
+
text: 'comment test forever!',
|
|
59
186
|
},
|
|
60
187
|
parent: '',
|
|
61
188
|
latest_children: {},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { render } from '@testing-library/vue';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
|
-
import CommentsAdd, { ADD_COMMENT_EVENT } from '../../../../vue/KvCommentsAdd.vue';
|
|
3
|
+
import CommentsAdd, { ADD_COMMENT_EVENT, HIDE_INPUT_EVENT } from '../../../../vue/KvCommentsAdd.vue';
|
|
4
4
|
|
|
5
5
|
const renderCommentsAdd = (props = {}) => {
|
|
6
6
|
return render(CommentsAdd, { props });
|
|
@@ -9,7 +9,7 @@ const renderCommentsAdd = (props = {}) => {
|
|
|
9
9
|
describe('KvCommentsAdd', () => {
|
|
10
10
|
it('should render defaults', () => {
|
|
11
11
|
const { getByPlaceholderText, getByRole } = renderCommentsAdd();
|
|
12
|
-
getByPlaceholderText('Add a comment
|
|
12
|
+
getByPlaceholderText('Add a comment...');
|
|
13
13
|
getByRole('button', { name: 'Cancel' });
|
|
14
14
|
getByRole('button', { name: 'Comment' });
|
|
15
15
|
});
|
|
@@ -25,7 +25,7 @@ describe('KvCommentsAdd', () => {
|
|
|
25
25
|
|
|
26
26
|
it('should enable comment button when text entered', async () => {
|
|
27
27
|
const { getByPlaceholderText, getByRole } = renderCommentsAdd();
|
|
28
|
-
const textInput = getByPlaceholderText('Add a comment
|
|
28
|
+
const textInput = getByPlaceholderText('Add a comment...');
|
|
29
29
|
const commentButton = getByRole('button', { name: 'Comment' });
|
|
30
30
|
|
|
31
31
|
expect(commentButton.disabled).toBeTruthy();
|
|
@@ -41,7 +41,7 @@ describe('KvCommentsAdd', () => {
|
|
|
41
41
|
|
|
42
42
|
it('should clear text when cancel clicked', async () => {
|
|
43
43
|
const { getByPlaceholderText, getByRole } = renderCommentsAdd();
|
|
44
|
-
const textInput = getByPlaceholderText('Add a comment
|
|
44
|
+
const textInput = getByPlaceholderText('Add a comment...');
|
|
45
45
|
const cancelButton = getByRole('button', { name: 'Cancel' });
|
|
46
46
|
|
|
47
47
|
await userEvent.type(textInput, 'test');
|
|
@@ -52,7 +52,7 @@ describe('KvCommentsAdd', () => {
|
|
|
52
52
|
|
|
53
53
|
it('should emit value when comment clicked', async () => {
|
|
54
54
|
const { getByPlaceholderText, getByRole, emitted } = renderCommentsAdd();
|
|
55
|
-
const textInput = getByPlaceholderText('Add a comment
|
|
55
|
+
const textInput = getByPlaceholderText('Add a comment...');
|
|
56
56
|
const commentButton = getByRole('button', { name: 'Comment' });
|
|
57
57
|
const TEST_INPUT = 'test test';
|
|
58
58
|
|
|
@@ -63,6 +63,18 @@ describe('KvCommentsAdd', () => {
|
|
|
63
63
|
expect(emitted()[ADD_COMMENT_EVENT]).toEqual([[TEST_INPUT]]);
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
+
it('should emit value when enter key pressed', async () => {
|
|
67
|
+
const { getByPlaceholderText, emitted } = renderCommentsAdd();
|
|
68
|
+
const textInput = getByPlaceholderText('Add a comment...');
|
|
69
|
+
const TEST_INPUT = 'test test';
|
|
70
|
+
|
|
71
|
+
await userEvent.type(textInput, TEST_INPUT);
|
|
72
|
+
|
|
73
|
+
userEvent.keyboard('{enter}');
|
|
74
|
+
|
|
75
|
+
expect(emitted()[ADD_COMMENT_EVENT]).toEqual([[TEST_INPUT]]);
|
|
76
|
+
});
|
|
77
|
+
|
|
66
78
|
it('should not emit empty value when comment clicked', async () => {
|
|
67
79
|
const { getByRole, emitted } = renderCommentsAdd();
|
|
68
80
|
const commentButton = getByRole('button', { name: 'Comment' });
|
|
@@ -71,4 +83,26 @@ describe('KvCommentsAdd', () => {
|
|
|
71
83
|
|
|
72
84
|
expect(emitted()[ADD_COMMENT_EVENT]).toBe(undefined);
|
|
73
85
|
});
|
|
86
|
+
|
|
87
|
+
it('should emit close event when it replies a comment', async () => {
|
|
88
|
+
const { getByRole, emitted, getByPlaceholderText } = renderCommentsAdd({ isReply: true });
|
|
89
|
+
const textInput = getByPlaceholderText('Add a comment...');
|
|
90
|
+
const commentButton = getByRole('button', { name: 'Comment' });
|
|
91
|
+
const TEST_INPUT = 'test test';
|
|
92
|
+
|
|
93
|
+
await userEvent.type(textInput, TEST_INPUT);
|
|
94
|
+
|
|
95
|
+
await userEvent.click(commentButton);
|
|
96
|
+
|
|
97
|
+
expect(emitted()[HIDE_INPUT_EVENT]).toEqual([[]]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should emit close event when it clicks cancel on reply', async () => {
|
|
101
|
+
const { getByRole, emitted } = renderCommentsAdd({ isReply: true });
|
|
102
|
+
const cancelButton = getByRole('button', { name: 'Cancel' });
|
|
103
|
+
|
|
104
|
+
await userEvent.click(cancelButton);
|
|
105
|
+
|
|
106
|
+
expect(emitted()[HIDE_INPUT_EVENT]).toEqual([[]]);
|
|
107
|
+
});
|
|
74
108
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { render } from '@testing-library/vue';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
|
-
import Container from '../../../../vue/KvCommentsContainer.vue';
|
|
3
|
+
import Container, { ADD_REACTION_EVENT } from '../../../../vue/KvCommentsContainer.vue';
|
|
4
4
|
import { ADD_COMMENT_ID, ADD_COMMENT_EVENT } from '../../../../vue/KvCommentsAdd.vue';
|
|
5
5
|
|
|
6
6
|
const renderContainer = (props = {}) => {
|
|
@@ -15,7 +15,7 @@ describe('KvCommentsContainer', () => {
|
|
|
15
15
|
|
|
16
16
|
it('should emit comment', async () => {
|
|
17
17
|
const { getByPlaceholderText, getByRole, emitted } = renderContainer();
|
|
18
|
-
const textInput = getByPlaceholderText('Add a comment
|
|
18
|
+
const textInput = getByPlaceholderText('Add a comment...');
|
|
19
19
|
const commentButton = getByRole('button', { name: 'Comment' });
|
|
20
20
|
const TEST_INPUT = 'test test';
|
|
21
21
|
|
|
@@ -23,6 +23,11 @@ describe('KvCommentsContainer', () => {
|
|
|
23
23
|
|
|
24
24
|
await userEvent.click(commentButton);
|
|
25
25
|
|
|
26
|
-
expect(emitted()[
|
|
26
|
+
expect(emitted()[ADD_REACTION_EVENT]).toEqual([[{
|
|
27
|
+
id: null,
|
|
28
|
+
isChild: false,
|
|
29
|
+
reaction: ADD_COMMENT_EVENT,
|
|
30
|
+
value: TEST_INPUT,
|
|
31
|
+
}]]);
|
|
27
32
|
});
|
|
28
33
|
});
|
|
@@ -4,7 +4,7 @@ import KvCommentsHeartButton from '../../../../vue/KvCommentsHeartButton.vue';
|
|
|
4
4
|
|
|
5
5
|
const CLICK_EVENT = 'click';
|
|
6
6
|
|
|
7
|
-
describe('
|
|
7
|
+
describe('KvCommentsHeartButton', () => {
|
|
8
8
|
it('should render defaults', () => {
|
|
9
9
|
const { getByRole } = render(KvCommentsHeartButton);
|
|
10
10
|
const likeButton = getByRole('button', { name: 'Like' });
|
|
@@ -3,6 +3,7 @@ import userEvent from '@testing-library/user-event';
|
|
|
3
3
|
import ListComponent from '../../../../vue/KvCommentsList.vue';
|
|
4
4
|
import activityFeed from '../../../fixtures/mockFeedActivityData';
|
|
5
5
|
import { LIKE_COMMENT_EVENT, REPLY_COMMENT_EVENT } from '../../../../vue/KvCommentsListItem.vue';
|
|
6
|
+
import { ADD_REACTION_EVENT } from '../../../../vue/KvCommentsContainer.vue';
|
|
6
7
|
|
|
7
8
|
const renderList = (props = {}) => {
|
|
8
9
|
return render(ListComponent, { props });
|
|
@@ -18,22 +19,44 @@ describe('KvCommentsList', () => {
|
|
|
18
19
|
expect(container.querySelectorAll(`#${id}`).length).toBe(1);
|
|
19
20
|
});
|
|
20
21
|
|
|
21
|
-
it('should emit
|
|
22
|
+
it('should emit like reaction events', async () => {
|
|
22
23
|
const { getAllByRole, emitted } = renderList({ comments });
|
|
23
|
-
const replyButton = getAllByRole('button', { name: 'Reply' })[0];
|
|
24
24
|
const likeButton = getAllByRole('button', { name: 'Like' })[0];
|
|
25
25
|
const firstComment = comments.comment[0];
|
|
26
26
|
|
|
27
27
|
const TEST_OBJ = {
|
|
28
|
-
|
|
28
|
+
id: firstComment.id,
|
|
29
|
+
isChild: true,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
await userEvent.click(likeButton);
|
|
33
|
+
expect(emitted()[ADD_REACTION_EVENT]).toEqual([[{ ...TEST_OBJ, reaction: LIKE_COMMENT_EVENT, value: true }]]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should emit reply reaction events', async () => {
|
|
37
|
+
const {
|
|
38
|
+
getAllByRole,
|
|
39
|
+
getByRole,
|
|
40
|
+
getByPlaceholderText,
|
|
41
|
+
emitted,
|
|
42
|
+
} = renderList({ comments });
|
|
43
|
+
const replyButton = getAllByRole('button', { name: 'Reply' })[0];
|
|
44
|
+
const firstComment = comments.comment[0];
|
|
45
|
+
|
|
46
|
+
const TEST_OBJ = {
|
|
29
47
|
id: firstComment.id,
|
|
30
48
|
isChild: true,
|
|
31
49
|
};
|
|
32
50
|
|
|
33
51
|
await userEvent.click(replyButton);
|
|
34
|
-
|
|
52
|
+
const commentButton = getByRole('button', { name: 'Comment' });
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
|
|
54
|
+
const textInput = getByPlaceholderText('Add a comment...');
|
|
55
|
+
const TEST_INPUT = 'test test';
|
|
56
|
+
|
|
57
|
+
await userEvent.type(textInput, TEST_INPUT);
|
|
58
|
+
|
|
59
|
+
await userEvent.click(commentButton);
|
|
60
|
+
expect(emitted()[ADD_REACTION_EVENT]).toEqual([[{ ...TEST_OBJ, reaction: REPLY_COMMENT_EVENT, value: TEST_INPUT }]]);
|
|
38
61
|
});
|
|
39
62
|
});
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { render } from '@testing-library/vue';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
|
-
import KvCommentsListItem from '../../../../vue/KvCommentsListItem.vue';
|
|
3
|
+
import KvCommentsListItem, { LIKE_COMMENT_EVENT, REPLY_COMMENT_EVENT } from '../../../../vue/KvCommentsListItem.vue';
|
|
4
4
|
import activityFeed from '../../../fixtures/mockFeedActivityData';
|
|
5
|
+
import { ADD_REACTION_EVENT } from '../../../../vue/KvCommentsContainer.vue';
|
|
5
6
|
|
|
6
7
|
const comment = activityFeed.results[0].latest_reactions.comment[0];
|
|
7
8
|
|
|
8
|
-
const handleClick = jest.fn();
|
|
9
|
-
|
|
10
9
|
const renderComment = (props = {}) => {
|
|
11
10
|
return render(KvCommentsListItem, { props });
|
|
12
11
|
};
|
|
13
12
|
|
|
14
13
|
describe('KvCommentsListItem', () => {
|
|
15
14
|
it('should render defaults', () => {
|
|
16
|
-
const {
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const { getAllByRole } = renderComment({ comment });
|
|
16
|
+
const replyButton = getAllByRole('button', { name: 'Reply' })[0];
|
|
17
|
+
const likeButton = getAllByRole('button', { name: 'Like' })[0];
|
|
18
|
+
|
|
19
|
+
expect(likeButton).toBeDefined();
|
|
20
|
+
expect(replyButton).toBeDefined();
|
|
19
21
|
});
|
|
20
22
|
|
|
21
23
|
it('should render comment text', () => {
|
|
@@ -24,20 +26,50 @@ describe('KvCommentsListItem', () => {
|
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
it('should handle like button click', async () => {
|
|
27
|
-
const {
|
|
28
|
-
const likeButton =
|
|
29
|
+
const { getAllByRole, emitted } = renderComment({ comment });
|
|
30
|
+
const likeButton = getAllByRole('button', { name: 'Like' })[0];
|
|
29
31
|
|
|
30
32
|
await userEvent.click(likeButton);
|
|
31
33
|
|
|
32
|
-
expect(
|
|
34
|
+
expect(emitted()[ADD_REACTION_EVENT]).toEqual([[{
|
|
35
|
+
id: comment.id,
|
|
36
|
+
isChild: true,
|
|
37
|
+
reaction: LIKE_COMMENT_EVENT,
|
|
38
|
+
value: true,
|
|
39
|
+
}]]);
|
|
33
40
|
});
|
|
34
41
|
|
|
35
42
|
it('should handle reply button click', async () => {
|
|
36
|
-
const { getByRole } = renderComment({ comment
|
|
37
|
-
const replyButton =
|
|
43
|
+
const { getAllByRole, getByRole } = renderComment({ comment });
|
|
44
|
+
const replyButton = getAllByRole('button', { name: 'Reply' })[0];
|
|
38
45
|
|
|
39
46
|
await userEvent.click(replyButton);
|
|
47
|
+
getByRole('button', { name: 'Comment' });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should emit reply reaction events', async () => {
|
|
51
|
+
const {
|
|
52
|
+
getAllByRole,
|
|
53
|
+
getByRole,
|
|
54
|
+
getByPlaceholderText,
|
|
55
|
+
emitted,
|
|
56
|
+
} = renderComment({ comment });
|
|
57
|
+
const replyButton = getAllByRole('button', { name: 'Reply' })[0];
|
|
58
|
+
|
|
59
|
+
const TEST_OBJ = {
|
|
60
|
+
id: comment.id,
|
|
61
|
+
isChild: true,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
await userEvent.click(replyButton);
|
|
65
|
+
const commentButton = getByRole('button', { name: 'Comment' });
|
|
66
|
+
|
|
67
|
+
const textInput = getByPlaceholderText('Add a comment...');
|
|
68
|
+
const TEST_INPUT = 'test test';
|
|
69
|
+
|
|
70
|
+
await userEvent.type(textInput, TEST_INPUT);
|
|
40
71
|
|
|
41
|
-
|
|
72
|
+
await userEvent.click(commentButton);
|
|
73
|
+
expect(emitted()[ADD_REACTION_EVENT]).toEqual([[{ ...TEST_OBJ, reaction: REPLY_COMMENT_EVENT, value: TEST_INPUT }]]);
|
|
42
74
|
});
|
|
43
75
|
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { render } from '@testing-library/vue';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import KvCommentsReplyButton from '../../../../vue/KvCommentsReplyButton.vue';
|
|
4
|
+
|
|
5
|
+
const CLICK_EVENT = 'click';
|
|
6
|
+
|
|
7
|
+
describe('KvCommentsReplyButton', () => {
|
|
8
|
+
it('should render defaults', () => {
|
|
9
|
+
const { getByRole } = render(KvCommentsReplyButton);
|
|
10
|
+
const replyButton = getByRole('button', { name: 'Reply' });
|
|
11
|
+
|
|
12
|
+
expect(replyButton).toBeDefined();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should emit click event when clicked', async () => {
|
|
16
|
+
const { getByRole, emitted } = render(KvCommentsReplyButton);
|
|
17
|
+
const replyButton = getByRole('button', { name: 'Reply' });
|
|
18
|
+
|
|
19
|
+
await userEvent.click(replyButton);
|
|
20
|
+
|
|
21
|
+
expect(emitted()[CLICK_EVENT]).toEqual([[]]);
|
|
22
|
+
});
|
|
23
|
+
});
|
package/vue/KvCommentsAdd.vue
CHANGED
|
@@ -22,9 +22,11 @@
|
|
|
22
22
|
</div>
|
|
23
23
|
<kv-text-input
|
|
24
24
|
:id="ADD_COMMENT_ID"
|
|
25
|
+
ref="input"
|
|
25
26
|
v-model="addCommentValue"
|
|
26
|
-
placeholder="Add a comment
|
|
27
|
+
placeholder="Add a comment..."
|
|
27
28
|
class="data-hj-suppress tw-grow"
|
|
29
|
+
@keyup.enter="comment"
|
|
28
30
|
/>
|
|
29
31
|
</div>
|
|
30
32
|
<div class="tw-flex tw-py-0.5 tw-gap-0.5">
|
|
@@ -53,8 +55,10 @@ import KvTextInput from './KvTextInput.vue';
|
|
|
53
55
|
|
|
54
56
|
export const ADD_COMMENT_ID = 'add-comment-value';
|
|
55
57
|
export const ADD_COMMENT_EVENT = 'add-comment';
|
|
58
|
+
export const HIDE_INPUT_EVENT = 'hide-input';
|
|
56
59
|
|
|
57
60
|
export default {
|
|
61
|
+
name: 'KvCommentsAdd',
|
|
58
62
|
components: {
|
|
59
63
|
KvButton,
|
|
60
64
|
KvTextInput,
|
|
@@ -74,27 +78,45 @@ export default {
|
|
|
74
78
|
type: String,
|
|
75
79
|
default: '',
|
|
76
80
|
},
|
|
81
|
+
/**
|
|
82
|
+
* Whether or not the comment is a reply
|
|
83
|
+
*/
|
|
84
|
+
isReply: {
|
|
85
|
+
type: Boolean,
|
|
86
|
+
default: false,
|
|
87
|
+
},
|
|
77
88
|
},
|
|
78
|
-
emits: [ADD_COMMENT_EVENT],
|
|
79
|
-
setup(
|
|
89
|
+
emits: [ADD_COMMENT_EVENT, HIDE_INPUT_EVENT],
|
|
90
|
+
setup(props, { emit }) {
|
|
80
91
|
const addCommentValue = ref('');
|
|
92
|
+
const input = ref(null);
|
|
81
93
|
|
|
82
94
|
const commentButtonState = computed(() => (addCommentValue.value ? '' : 'disabled'));
|
|
83
95
|
|
|
84
96
|
const cancel = () => {
|
|
85
97
|
addCommentValue.value = '';
|
|
98
|
+
if (props.isReply) {
|
|
99
|
+
emit(HIDE_INPUT_EVENT);
|
|
100
|
+
}
|
|
86
101
|
};
|
|
87
102
|
|
|
88
103
|
const comment = () => {
|
|
89
104
|
emit(ADD_COMMENT_EVENT, addCommentValue.value);
|
|
105
|
+
addCommentValue.value = '';
|
|
106
|
+
if (props.isReply) {
|
|
107
|
+
emit(HIDE_INPUT_EVENT);
|
|
108
|
+
}
|
|
90
109
|
};
|
|
91
110
|
|
|
111
|
+
const focus = () => input.value.focus();
|
|
112
|
+
|
|
92
113
|
return {
|
|
93
114
|
ADD_COMMENT_ID,
|
|
94
115
|
addCommentValue,
|
|
95
116
|
commentButtonState,
|
|
96
117
|
cancel,
|
|
97
118
|
comment,
|
|
119
|
+
focus,
|
|
98
120
|
};
|
|
99
121
|
},
|
|
100
122
|
};
|
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
<kv-comments-add
|
|
4
4
|
:user-image-url="userImageUrl"
|
|
5
5
|
:user-display-name="userDisplayName"
|
|
6
|
-
@add-comment="
|
|
6
|
+
@add-comment="handleReaction"
|
|
7
7
|
/>
|
|
8
8
|
<kv-comments-list
|
|
9
9
|
v-if="comments"
|
|
10
|
+
:user-image-url="userImageUrl"
|
|
11
|
+
:user-display-name="userDisplayName"
|
|
12
|
+
:user-public-id="userPublicId"
|
|
10
13
|
:comments="comments"
|
|
11
|
-
@
|
|
12
|
-
@[LIKE_COMMENT_EVENT]="comment"
|
|
14
|
+
@add-reaction="handleReaction"
|
|
13
15
|
/>
|
|
14
16
|
</div>
|
|
15
17
|
</template>
|
|
@@ -17,11 +19,12 @@
|
|
|
17
19
|
<script>
|
|
18
20
|
import KvCommentsAdd from './KvCommentsAdd.vue';
|
|
19
21
|
import KvCommentsList from './KvCommentsList.vue';
|
|
20
|
-
import { REPLY_COMMENT_EVENT, LIKE_COMMENT_EVENT } from './KvCommentsListItem.vue';
|
|
21
22
|
|
|
22
23
|
export const ADD_COMMENT_EVENT = 'add-comment';
|
|
24
|
+
export const ADD_REACTION_EVENT = 'add-reaction';
|
|
23
25
|
|
|
24
26
|
export default {
|
|
27
|
+
name: 'KvCommentsContainer',
|
|
25
28
|
components: {
|
|
26
29
|
KvCommentsAdd,
|
|
27
30
|
KvCommentsList,
|
|
@@ -41,6 +44,13 @@ export default {
|
|
|
41
44
|
type: String,
|
|
42
45
|
default: '',
|
|
43
46
|
},
|
|
47
|
+
/**
|
|
48
|
+
* The ID for the user
|
|
49
|
+
*/
|
|
50
|
+
userPublicId: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: '',
|
|
53
|
+
},
|
|
44
54
|
/**
|
|
45
55
|
* Activity comments
|
|
46
56
|
*/
|
|
@@ -49,16 +59,24 @@ export default {
|
|
|
49
59
|
default: () => {},
|
|
50
60
|
},
|
|
51
61
|
},
|
|
62
|
+
emits: [ADD_REACTION_EVENT],
|
|
52
63
|
setup(_props, { emit }) {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
const handleReaction = (reactionPayload) => {
|
|
65
|
+
let payload;
|
|
66
|
+
if (reactionPayload.value === undefined) {
|
|
67
|
+
payload = {
|
|
68
|
+
reaction: ADD_COMMENT_EVENT,
|
|
69
|
+
id: null,
|
|
70
|
+
isChild: false,
|
|
71
|
+
value: reactionPayload,
|
|
72
|
+
};
|
|
73
|
+
} else {
|
|
74
|
+
payload = reactionPayload;
|
|
75
|
+
}
|
|
76
|
+
emit(ADD_REACTION_EVENT, payload);
|
|
57
77
|
};
|
|
58
78
|
return {
|
|
59
|
-
|
|
60
|
-
REPLY_COMMENT_EVENT,
|
|
61
|
-
LIKE_COMMENT_EVENT,
|
|
79
|
+
handleReaction,
|
|
62
80
|
};
|
|
63
81
|
},
|
|
64
82
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<button
|
|
3
3
|
aria-label="Like"
|
|
4
|
-
|
|
4
|
+
class="tw-flex tw-flex-col tw-justify-center"
|
|
5
|
+
@click="$emit('click', !isLiked);"
|
|
5
6
|
>
|
|
6
7
|
<kv-material-icon
|
|
7
8
|
:icon="icon"
|
|
@@ -39,7 +40,7 @@ export default {
|
|
|
39
40
|
emits: [
|
|
40
41
|
'click',
|
|
41
42
|
],
|
|
42
|
-
setup(props
|
|
43
|
+
setup(props) {
|
|
43
44
|
const {
|
|
44
45
|
isSmall,
|
|
45
46
|
isLiked,
|
|
@@ -54,14 +55,9 @@ export default {
|
|
|
54
55
|
return className;
|
|
55
56
|
});
|
|
56
57
|
|
|
57
|
-
const changeState = () => {
|
|
58
|
-
emit('click', !isLiked.value);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
58
|
return {
|
|
62
59
|
icon,
|
|
63
60
|
classState,
|
|
64
|
-
changeState,
|
|
65
61
|
};
|
|
66
62
|
},
|
|
67
63
|
};
|
package/vue/KvCommentsList.vue
CHANGED
|
@@ -6,19 +6,46 @@
|
|
|
6
6
|
:key="comment.id"
|
|
7
7
|
:nest-level="1"
|
|
8
8
|
:comment="comment"
|
|
9
|
+
:user-image-url="userImageUrl"
|
|
10
|
+
:user-display-name="userDisplayName"
|
|
11
|
+
:user-public-id="userPublicId"
|
|
9
12
|
:is-liked="comment.is_liked"
|
|
10
|
-
|
|
13
|
+
class="tw-mb-2"
|
|
14
|
+
@add-reaction="handleReaction"
|
|
11
15
|
/>
|
|
12
16
|
</div>
|
|
13
17
|
</template>
|
|
14
18
|
|
|
15
19
|
<script>
|
|
16
20
|
|
|
17
|
-
import KvCommentsListItem
|
|
21
|
+
import KvCommentsListItem from './KvCommentsListItem.vue';
|
|
22
|
+
import { ADD_REACTION_EVENT } from './KvCommentsContainer.vue';
|
|
18
23
|
|
|
19
24
|
export default {
|
|
25
|
+
name: 'KvCommentsList',
|
|
20
26
|
components: { KvCommentsListItem },
|
|
21
27
|
props: {
|
|
28
|
+
/**
|
|
29
|
+
* The full URL for the user image
|
|
30
|
+
*/
|
|
31
|
+
userImageUrl: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: '',
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* The name to display for the user
|
|
37
|
+
*/
|
|
38
|
+
userDisplayName: {
|
|
39
|
+
type: String,
|
|
40
|
+
default: '',
|
|
41
|
+
},
|
|
42
|
+
/**
|
|
43
|
+
* The ID for the user
|
|
44
|
+
*/
|
|
45
|
+
userPublicId: {
|
|
46
|
+
type: String,
|
|
47
|
+
default: '',
|
|
48
|
+
},
|
|
22
49
|
/**
|
|
23
50
|
* Activity comments
|
|
24
51
|
*/
|
|
@@ -27,12 +54,15 @@ export default {
|
|
|
27
54
|
default: () => {},
|
|
28
55
|
},
|
|
29
56
|
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
57
|
+
emits: [ADD_REACTION_EVENT],
|
|
58
|
+
setup(_props, { emit }) {
|
|
59
|
+
const handleReaction = (payload) => {
|
|
60
|
+
emit(ADD_REACTION_EVENT, payload);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
handleReaction,
|
|
65
|
+
};
|
|
36
66
|
},
|
|
37
67
|
};
|
|
38
68
|
</script>
|
|
@@ -1,54 +1,75 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div
|
|
4
|
-
class="tw-flex tw-items-center tw-gap-1"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
3
|
+
<div>
|
|
4
|
+
<div class="tw-flex tw-items-center tw-gap-1">
|
|
5
|
+
<img
|
|
6
|
+
v-if="authorImage"
|
|
7
|
+
class="
|
|
8
|
+
data-hj-suppress
|
|
9
|
+
tw-inline-block
|
|
10
|
+
tw-w-3.5
|
|
11
|
+
tw-h-3.5
|
|
12
|
+
tw-rounded-full
|
|
13
|
+
tw-overflow-hidden
|
|
14
|
+
tw-object-fill
|
|
15
|
+
"
|
|
16
|
+
:src="authorImage"
|
|
17
|
+
alt="picture"
|
|
18
|
+
>
|
|
19
|
+
<p
|
|
20
|
+
v-if="authorName"
|
|
21
|
+
class="tw-font-medium"
|
|
22
|
+
>
|
|
23
|
+
{{ authorName }}
|
|
24
|
+
</p>
|
|
25
|
+
</div>
|
|
20
26
|
<p>
|
|
21
|
-
{{
|
|
27
|
+
{{ commentText }}
|
|
22
28
|
</p>
|
|
23
29
|
</div>
|
|
24
|
-
<div
|
|
30
|
+
<div
|
|
31
|
+
v-if="nestLevel < 3"
|
|
32
|
+
class="tw-flex tw-items-center tw-gap-x-2"
|
|
33
|
+
>
|
|
25
34
|
<kv-comments-heart-button
|
|
26
35
|
:is-small="true"
|
|
27
36
|
:is-liked="isLiked"
|
|
28
|
-
@click="
|
|
37
|
+
@click="addReaction(LIKE_COMMENT_EVENT, $event)"
|
|
38
|
+
/>
|
|
39
|
+
<kv-comments-reply-button
|
|
40
|
+
@click="replyClick"
|
|
29
41
|
/>
|
|
30
|
-
<kv-button
|
|
31
|
-
variant="ghost"
|
|
32
|
-
class="tw-font-medium"
|
|
33
|
-
@click="onClick(REPLY_COMMENT_EVENT)"
|
|
34
|
-
>
|
|
35
|
-
Reply
|
|
36
|
-
</kv-button>
|
|
37
42
|
</div>
|
|
38
43
|
<div
|
|
39
|
-
v-if="
|
|
44
|
+
v-if="showInput"
|
|
45
|
+
class="tw-w-full"
|
|
46
|
+
>
|
|
47
|
+
<kv-comments-add
|
|
48
|
+
ref="commentsAddRef"
|
|
49
|
+
:user-image-url="userImageUrl"
|
|
50
|
+
:user-display-name="userDisplayName"
|
|
51
|
+
:is-reply="true"
|
|
52
|
+
class="tw-ml-3"
|
|
53
|
+
@add-comment="addReaction(REPLY_COMMENT_EVENT, $event)"
|
|
54
|
+
@hide-input="hideInput"
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
<div
|
|
58
|
+
v-if="childComments"
|
|
40
59
|
class="tw-my-1"
|
|
41
60
|
>
|
|
42
61
|
<p
|
|
43
|
-
v-for="nested_comment in
|
|
62
|
+
v-for="nested_comment in childComments"
|
|
44
63
|
:key="nested_comment.id"
|
|
45
64
|
class="tw-ml-3"
|
|
46
65
|
>
|
|
47
66
|
<kv-comments-list-item
|
|
67
|
+
:user-image-url="userImageUrl"
|
|
68
|
+
:user-display-name="userDisplayName"
|
|
69
|
+
:user-public-id="userPublicId"
|
|
48
70
|
:comment="nested_comment"
|
|
49
|
-
:is-liked="nested_comment.is_liked"
|
|
50
71
|
:nest-level="nestLevel + 1"
|
|
51
|
-
|
|
72
|
+
@add-reaction="$emit(ADD_REACTION_EVENT, $event);"
|
|
52
73
|
/>
|
|
53
74
|
</p>
|
|
54
75
|
</div>
|
|
@@ -56,8 +77,16 @@
|
|
|
56
77
|
</template>
|
|
57
78
|
|
|
58
79
|
<script>
|
|
59
|
-
import
|
|
80
|
+
import {
|
|
81
|
+
ref,
|
|
82
|
+
nextTick,
|
|
83
|
+
computed,
|
|
84
|
+
toRefs,
|
|
85
|
+
} from 'vue-demi';
|
|
86
|
+
import KvCommentsReplyButton from './KvCommentsReplyButton.vue';
|
|
60
87
|
import KvCommentsHeartButton from './KvCommentsHeartButton.vue';
|
|
88
|
+
import KvCommentsAdd from './KvCommentsAdd.vue';
|
|
89
|
+
import { ADD_REACTION_EVENT } from './KvCommentsContainer.vue';
|
|
61
90
|
|
|
62
91
|
export const REPLY_COMMENT_EVENT = 'reply-comment';
|
|
63
92
|
export const LIKE_COMMENT_EVENT = 'like-comment';
|
|
@@ -65,10 +94,32 @@ export const LIKE_COMMENT_EVENT = 'like-comment';
|
|
|
65
94
|
export default {
|
|
66
95
|
name: 'KvCommentsListItem',
|
|
67
96
|
components: {
|
|
68
|
-
|
|
97
|
+
KvCommentsReplyButton,
|
|
69
98
|
KvCommentsHeartButton,
|
|
99
|
+
KvCommentsAdd,
|
|
70
100
|
},
|
|
71
101
|
props: {
|
|
102
|
+
/**
|
|
103
|
+
* The full URL for the user image
|
|
104
|
+
*/
|
|
105
|
+
userImageUrl: {
|
|
106
|
+
type: String,
|
|
107
|
+
default: '',
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* The name to display for the user
|
|
111
|
+
*/
|
|
112
|
+
userDisplayName: {
|
|
113
|
+
type: String,
|
|
114
|
+
default: '',
|
|
115
|
+
},
|
|
116
|
+
/**
|
|
117
|
+
* The ID for the user
|
|
118
|
+
*/
|
|
119
|
+
userPublicId: {
|
|
120
|
+
type: String,
|
|
121
|
+
default: '',
|
|
122
|
+
},
|
|
72
123
|
/**
|
|
73
124
|
* Activity comment
|
|
74
125
|
*/
|
|
@@ -83,51 +134,65 @@ export default {
|
|
|
83
134
|
type: Number,
|
|
84
135
|
default: 0,
|
|
85
136
|
},
|
|
86
|
-
/**
|
|
87
|
-
* Comment is liked by current user
|
|
88
|
-
*/
|
|
89
|
-
isLiked: {
|
|
90
|
-
type: Boolean,
|
|
91
|
-
default: false,
|
|
92
|
-
},
|
|
93
|
-
/**
|
|
94
|
-
* The function to call when a reaction is clicked
|
|
95
|
-
*/
|
|
96
|
-
handleClick: {
|
|
97
|
-
type: Function,
|
|
98
|
-
default: () => ({}),
|
|
99
|
-
},
|
|
100
137
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
138
|
+
emits: [
|
|
139
|
+
ADD_REACTION_EVENT,
|
|
140
|
+
],
|
|
141
|
+
setup(props, { emit }) {
|
|
142
|
+
const {
|
|
143
|
+
comment,
|
|
144
|
+
userPublicId,
|
|
145
|
+
} = toRefs(props);
|
|
146
|
+
|
|
147
|
+
const showInput = ref(false);
|
|
148
|
+
const commentsAddRef = ref(null);
|
|
149
|
+
|
|
150
|
+
const commentText = computed(() => comment?.value?.data?.text ?? '');
|
|
151
|
+
const authorImage = computed(() => comment?.value?.user?.data?.image ?? '');
|
|
152
|
+
const authorName = computed(() => comment?.value?.user?.data?.name ?? '');
|
|
153
|
+
const childComments = computed(() => comment?.value?.latest_children?.comment ?? null);
|
|
154
|
+
const childLikes = computed(() => comment?.value?.latest_children?.like ?? []);
|
|
155
|
+
const likedObject = computed(() => childLikes.value.find((child) => child.user.data.publicLenderId === userPublicId.value)); // eslint-disable-line max-len
|
|
156
|
+
const isLiked = computed(() => likedObject.value !== undefined);
|
|
157
|
+
|
|
158
|
+
const replyClick = () => {
|
|
159
|
+
showInput.value = !showInput.value;
|
|
160
|
+
nextTick(() => {
|
|
161
|
+
if (showInput.value) commentsAddRef.value.$refs.input.focus();
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const addReaction = (reaction, value) => {
|
|
166
|
+
const payload = {
|
|
104
167
|
reaction,
|
|
105
|
-
id:
|
|
106
|
-
userId: props.comment?.user_id ?? null,
|
|
168
|
+
id: comment?.value?.id ?? null,
|
|
107
169
|
isChild: true,
|
|
108
170
|
value,
|
|
109
|
-
}
|
|
171
|
+
};
|
|
172
|
+
if (reaction === LIKE_COMMENT_EVENT && !value) {
|
|
173
|
+
payload.id = likedObject.value.id;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
emit(ADD_REACTION_EVENT, payload);
|
|
110
177
|
};
|
|
111
178
|
|
|
179
|
+
const hideInput = () => { showInput.value = false; };
|
|
180
|
+
|
|
112
181
|
return {
|
|
113
|
-
|
|
182
|
+
hideInput,
|
|
183
|
+
showInput,
|
|
184
|
+
commentsAddRef,
|
|
185
|
+
replyClick,
|
|
186
|
+
addReaction,
|
|
114
187
|
REPLY_COMMENT_EVENT,
|
|
115
188
|
LIKE_COMMENT_EVENT,
|
|
189
|
+
ADD_REACTION_EVENT,
|
|
190
|
+
commentText,
|
|
191
|
+
authorImage,
|
|
192
|
+
authorName,
|
|
193
|
+
childComments,
|
|
194
|
+
isLiked,
|
|
116
195
|
};
|
|
117
196
|
},
|
|
118
|
-
computed: {
|
|
119
|
-
text() {
|
|
120
|
-
return this.comment?.data?.text ?? '';
|
|
121
|
-
},
|
|
122
|
-
userId() {
|
|
123
|
-
return this.comment?.user_id ?? null;
|
|
124
|
-
},
|
|
125
|
-
latestChildren() {
|
|
126
|
-
return this.comment?.latest_children ?? null;
|
|
127
|
-
},
|
|
128
|
-
profileImage() {
|
|
129
|
-
return this.comment?.user_picture ?? '';
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
197
|
};
|
|
133
198
|
</script>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!-- eslint-disable max-len -->
|
|
2
|
+
<template>
|
|
3
|
+
<button
|
|
4
|
+
aria-label="Reply"
|
|
5
|
+
class="tw-font-medium tw-flex tw-items-center tw-gap-x-0.5"
|
|
6
|
+
@click="$emit('click')"
|
|
7
|
+
>
|
|
8
|
+
<svg
|
|
9
|
+
width="14"
|
|
10
|
+
height="11"
|
|
11
|
+
viewBox="0 0 14 11"
|
|
12
|
+
fill="none"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
>
|
|
15
|
+
<path
|
|
16
|
+
d="M2.87502 5.12499L4.91669 7.16666C5.06946 7.31943 5.14585 7.49652 5.14585 7.69791C5.14585 7.8993 5.06946 8.0797 4.91669 8.23911C4.76391 8.38525 4.58683 8.45832 4.38544 8.45832C4.18405 8.45832 4.00696 8.38193 3.85419 8.22916L0.520854 4.89582C0.368076 4.7481 0.291687 4.57575 0.291687 4.37878C0.291687 4.18181 0.368076 4.00693 0.520854 3.85416L3.85419 0.520823C4.00696 0.368045 4.18521 0.291656 4.38892 0.291656C4.59261 0.291656 4.76853 0.368045 4.91669 0.520823C5.06946 0.668976 5.14585 0.8449 5.14585 1.04859C5.14585 1.2523 5.06946 1.43055 4.91669 1.58332L2.87502 3.62499H10C11.1067 3.62499 12.05 4.01499 12.83 4.79499C13.61 5.57499 14 6.51832 14 7.62499V9.87499C14 10.0875 13.9286 10.2656 13.7857 10.4094C13.6427 10.5531 13.4657 10.625 13.2544 10.625C13.0432 10.625 12.8646 10.5531 12.7188 10.4094C12.5729 10.2656 12.5 10.0875 12.5 9.87499V7.62499C12.5 6.93055 12.257 6.34027 11.7709 5.85416C11.2847 5.36805 10.6945 5.12499 10 5.12499H2.87502Z"
|
|
17
|
+
fill="#1C1B1F"
|
|
18
|
+
/>
|
|
19
|
+
</svg>
|
|
20
|
+
|
|
21
|
+
<span>
|
|
22
|
+
Reply
|
|
23
|
+
</span>
|
|
24
|
+
</button>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script>
|
|
28
|
+
export default {
|
|
29
|
+
name: 'KvCommentsReplyButton',
|
|
30
|
+
emits: [
|
|
31
|
+
'click',
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import KvCommentsContainer from '../KvCommentsContainer.vue';
|
|
2
|
-
import
|
|
2
|
+
import activityFeed from '../../tests/fixtures/mockFeedActivityData';
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
5
|
title: 'KvCommentsContainer',
|
|
@@ -21,4 +21,15 @@ const story = (args) => {
|
|
|
21
21
|
return template;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
const comments = activityFeed.results[0].latest_reactions;
|
|
25
|
+
|
|
24
26
|
export const Default = story({ comments });
|
|
27
|
+
|
|
28
|
+
export const UserData = story(
|
|
29
|
+
{
|
|
30
|
+
comments,
|
|
31
|
+
userDisplayName: 'Jess',
|
|
32
|
+
userImageUrl: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg',
|
|
33
|
+
userPublicId: 'Jess1234',
|
|
34
|
+
},
|
|
35
|
+
);
|
|
@@ -22,3 +22,12 @@ const story = (args) => {
|
|
|
22
22
|
const comments = activityFeed.results[0].latest_reactions;
|
|
23
23
|
|
|
24
24
|
export const Default = story({ comments });
|
|
25
|
+
|
|
26
|
+
export const UserData = story(
|
|
27
|
+
{
|
|
28
|
+
comments,
|
|
29
|
+
userDisplayName: 'Jess',
|
|
30
|
+
userImageUrl: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg',
|
|
31
|
+
userPublicId: 'Jess1234',
|
|
32
|
+
},
|
|
33
|
+
);
|
|
@@ -19,6 +19,18 @@ const story = (args) => {
|
|
|
19
19
|
return template;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const comment = activityFeed.results[0].latest_reactions.comment[
|
|
22
|
+
const comment = activityFeed.results[0].latest_reactions.comment[1];
|
|
23
|
+
const childComments = activityFeed.results[0].latest_reactions.comment[0];
|
|
23
24
|
|
|
24
25
|
export const Default = story({ comment });
|
|
26
|
+
|
|
27
|
+
export const ChildComments = story({ comment: childComments });
|
|
28
|
+
|
|
29
|
+
export const UserData = story(
|
|
30
|
+
{
|
|
31
|
+
comment: childComments,
|
|
32
|
+
userDisplayName: 'Jess',
|
|
33
|
+
userImageUrl: 'https://www-0.development.kiva.org/img/s100/6b1a24092be3aaa22216874e644a4acf.jpg',
|
|
34
|
+
userPublicId: 'Jess1234',
|
|
35
|
+
},
|
|
36
|
+
);
|