@kiva/kv-components 3.52.0 → 3.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,39 @@
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.53.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.52.1...@kiva/kv-components@3.53.0) (2024-02-26)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * indentation in item component ([30aee02](https://github.com/kiva/kv-ui-elements/commit/30aee02d3c2e58c7c98fe6a58689a9824f56ef60))
12
+ * optional chaining for comment object ([bac9ba1](https://github.com/kiva/kv-ui-elements/commit/bac9ba199970966564bfab7d6a2e64bb92fea286))
13
+ * revert profile image and small fixes ([fc8cf74](https://github.com/kiva/kv-ui-elements/commit/fc8cf7440fb355fbfee0e8acfb2a849dd6513a11))
14
+ * using more accurate data for components ([043f1c2](https://github.com/kiva/kv-ui-elements/commit/043f1c2d47a5d22157785b9d972246823572e4fd))
15
+
16
+
17
+ ### Features
18
+
19
+ * provisional comment list and item components ([642745c](https://github.com/kiva/kv-ui-elements/commit/642745ce1359e5cc9e3d98d122f26728b3dffda0))
20
+
21
+
22
+
23
+
24
+
25
+ ## [3.52.1](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.52.0...@kiva/kv-components@3.52.1) (2024-02-01)
26
+
27
+
28
+ ### Bug Fixes
29
+
30
+ * add back in comments container ([36a8a97](https://github.com/kiva/kv-ui-elements/commit/36a8a979aac47c425e32d87cd13160ad68b913cf))
31
+ * another tweak to how events emitted ([029367a](https://github.com/kiva/kv-ui-elements/commit/029367aeb1f38151a7d36e0a2246b82b14489cb3))
32
+ * minor test fix ([c95c486](https://github.com/kiva/kv-ui-elements/commit/c95c4866d05b2e711e8895868d72ddc6bb5b7a43))
33
+ * remove unneeded comment container ([71365b0](https://github.com/kiva/kv-ui-elements/commit/71365b0f6628d1d280f9fbd2b0adbad8688fd57c))
34
+
35
+
36
+
37
+
38
+
6
39
  # [3.52.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.51.0...@kiva/kv-components@3.52.0) (2024-01-31)
7
40
 
8
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "3.52.0",
3
+ "version": "3.53.0",
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": "185baa28a3a0e9616ca3ef4cf404b9074d19b373"
78
+ "gitHead": "f9f7231aa673a793c38ed14e55977ecb1d9dc89b"
79
79
  }
@@ -0,0 +1,79 @@
1
+ const comments = {
2
+ duration: '6.42ms',
3
+ results: [
4
+ {
5
+ actor: {
6
+ created_at: '2024-02-01T19:48:26.890734Z',
7
+ updated_at: '2024-02-01T19:48:26.890734Z',
8
+ id: '123',
9
+ data: {},
10
+ },
11
+ foreign_id: 'CHALLENGE#test-challenge-id',
12
+ id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
13
+ latest_reactions: {
14
+ comment: [
15
+ {
16
+ created_at: '2024-02-01T20:12:31.398932Z',
17
+ updated_at: '2024-02-01T20:12:31.398932Z',
18
+ id: 'dade3812-6aa0-4c32-90ea-2366dab178a1',
19
+ user_id: '1de650a5-b12f-4d20-b46c-6e15b0722141',
20
+ kind: 'comment',
21
+ activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
22
+ data: {
23
+ text: 'another guest comment',
24
+ },
25
+ parent: '',
26
+ latest_children: {},
27
+ children_counts: {},
28
+ },
29
+ {
30
+ created_at: '2024-02-01T20:11:23.931133Z',
31
+ updated_at: '2024-02-01T20:11:23.931133Z',
32
+ id: '3de615bb-0d48-4a69-9004-141ee26985eb',
33
+ user_id: '1de650a5-b12f-4d20-b46c-6e15b0722141',
34
+ kind: 'comment',
35
+ activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
36
+ data: {
37
+ text: 'test as visitor',
38
+ },
39
+ parent: '',
40
+ latest_children: {},
41
+ children_counts: {},
42
+ },
43
+ {
44
+ created_at: '2024-02-01T20:06:46.651764Z',
45
+ updated_at: '2024-02-01T20:06:46.651764Z',
46
+ id: 'e1db4420-159e-4ba2-aab9-704d1cc56dae',
47
+ user_id: '123',
48
+ user: {
49
+ created_at: '2024-02-01T19:48:26.890734Z',
50
+ updated_at: '2024-02-01T19:48:26.890734Z',
51
+ id: '123',
52
+ data: {},
53
+ },
54
+ kind: 'comment',
55
+ activity_id: 'efb2dbfe-c12a-11ee-9fbc-065afce7d41d',
56
+ data: {
57
+ text: 'asd',
58
+ },
59
+ parent: '',
60
+ latest_children: {},
61
+ children_counts: {},
62
+ },
63
+ ],
64
+ },
65
+ latest_reactions_extra: {
66
+ comment: {
67
+ next: '',
68
+ },
69
+ },
70
+ object: 'test-challenge-id',
71
+ origin: null,
72
+ target: '',
73
+ time: '2024-02-01T17:54:24.932762',
74
+ verb: 'CHALLENGE',
75
+ },
76
+ ],
77
+ };
78
+
79
+ export default comments;
@@ -0,0 +1,39 @@
1
+ import { render } from '@testing-library/vue';
2
+ import userEvent from '@testing-library/user-event';
3
+ import ListComponent from '../../../../vue/KvCommentsList.vue';
4
+ import activityFeed from '../../../fixtures/mockFeedActivityData';
5
+ import { LIKE_COMMENT_EVENT, REPLY_COMMENT_EVENT } from '../../../../vue/KvCommentsListItem.vue';
6
+
7
+ const renderList = (props = {}) => {
8
+ return render(ListComponent, { props });
9
+ };
10
+
11
+ const comments = activityFeed.results[0].latest_reactions;
12
+
13
+ describe('KvCommentsList', () => {
14
+ it('should render comments component', async () => {
15
+ const { container } = renderList({ comments });
16
+
17
+ const { id } = comments.comment[0];
18
+ expect(container.querySelectorAll(`#${id}`).length).toBe(1);
19
+ });
20
+
21
+ it('should emit comment events', async () => {
22
+ const { getAllByRole, emitted } = renderList({ comments });
23
+ const replyButton = getAllByRole('button', { name: 'Reply' })[0];
24
+ const likeButton = getAllByRole('button', { name: 'Like' })[0];
25
+ const firstComment = comments.comment[0];
26
+
27
+ const TEST_OBJ = {
28
+ userId: firstComment.user_id,
29
+ id: firstComment.id,
30
+ isChild: true,
31
+ };
32
+
33
+ await userEvent.click(replyButton);
34
+ expect(emitted()[REPLY_COMMENT_EVENT]).toEqual([[{ ...TEST_OBJ, reaction: REPLY_COMMENT_EVENT }]]);
35
+
36
+ await userEvent.click(likeButton);
37
+ expect(emitted()[LIKE_COMMENT_EVENT]).toEqual([[{ ...TEST_OBJ, reaction: LIKE_COMMENT_EVENT }]]);
38
+ });
39
+ });
@@ -0,0 +1,43 @@
1
+ import { render } from '@testing-library/vue';
2
+ import userEvent from '@testing-library/user-event';
3
+ import KvCommentsListItem from '../../../../vue/KvCommentsListItem.vue';
4
+ import activityFeed from '../../../fixtures/mockFeedActivityData';
5
+
6
+ const comment = activityFeed.results[0].latest_reactions.comment[0];
7
+
8
+ const handleClick = jest.fn();
9
+
10
+ const renderComment = (props = {}) => {
11
+ return render(KvCommentsListItem, { props });
12
+ };
13
+
14
+ describe('KvCommentsListItem', () => {
15
+ it('should render defaults', () => {
16
+ const { getByRole } = renderComment({ comment });
17
+ getByRole('button', { name: 'Reply' });
18
+ getByRole('button', { name: 'Like' });
19
+ });
20
+
21
+ it('should render comment text', () => {
22
+ const { getByText } = renderComment({ comment });
23
+ getByText(comment.data.text);
24
+ });
25
+
26
+ it('should handle like button click', async () => {
27
+ const { getByRole } = renderComment({ comment, handleClick });
28
+ const likeButton = getByRole('button', { name: 'Like' });
29
+
30
+ await userEvent.click(likeButton);
31
+
32
+ expect(handleClick).toHaveBeenCalledTimes(1);
33
+ });
34
+
35
+ it('should handle reply button click', async () => {
36
+ const { getByRole } = renderComment({ comment, handleClick });
37
+ const replyButton = getByRole('button', { name: 'Reply' });
38
+
39
+ await userEvent.click(replyButton);
40
+
41
+ expect(handleClick).toHaveBeenCalledTimes(1);
42
+ });
43
+ });
@@ -1,19 +1,30 @@
1
1
  <template>
2
- <kv-comments-add
3
- :user-image-url="userImageUrl"
4
- :user-display-name="userDisplayName"
5
- @add-comment="comment"
6
- />
2
+ <div>
3
+ <kv-comments-add
4
+ :user-image-url="userImageUrl"
5
+ :user-display-name="userDisplayName"
6
+ @add-comment="comment"
7
+ />
8
+ <kv-comments-list
9
+ v-if="comments"
10
+ :comments="comments"
11
+ @[REPLY_COMMENT_EVENT]="comment"
12
+ @[LIKE_COMMENT_EVENT]="comment"
13
+ />
14
+ </div>
7
15
  </template>
8
16
 
9
17
  <script>
10
18
  import KvCommentsAdd from './KvCommentsAdd.vue';
19
+ import KvCommentsList from './KvCommentsList.vue';
20
+ import { REPLY_COMMENT_EVENT, LIKE_COMMENT_EVENT } from './KvCommentsListItem.vue';
11
21
 
12
22
  export const ADD_COMMENT_EVENT = 'add-comment';
13
23
 
14
24
  export default {
15
25
  components: {
16
26
  KvCommentsAdd,
27
+ KvCommentsList,
17
28
  },
18
29
  props: {
19
30
  /**
@@ -30,14 +41,24 @@ export default {
30
41
  type: String,
31
42
  default: '',
32
43
  },
44
+ /**
45
+ * Activity comments
46
+ */
47
+ comments: {
48
+ type: Object,
49
+ default: () => {},
50
+ },
33
51
  },
34
52
  setup(_props, { emit }) {
35
53
  const comment = (commentValue) => {
36
54
  emit(ADD_COMMENT_EVENT, commentValue);
55
+ emit(REPLY_COMMENT_EVENT, commentValue);
56
+ emit(LIKE_COMMENT_EVENT, commentValue);
37
57
  };
38
-
39
58
  return {
40
59
  comment,
60
+ REPLY_COMMENT_EVENT,
61
+ LIKE_COMMENT_EVENT,
41
62
  };
42
63
  },
43
64
  };
@@ -0,0 +1,37 @@
1
+ <template>
2
+ <div>
3
+ <KvCommentsListItem
4
+ v-for="comment in comments.comment"
5
+ :id="comment.id"
6
+ :key="comment.id"
7
+ :nest-level="1"
8
+ :comment="comment"
9
+ :handle-click="handleClick"
10
+ />
11
+ </div>
12
+ </template>
13
+
14
+ <script>
15
+
16
+ import KvCommentsListItem, { REPLY_COMMENT_EVENT, LIKE_COMMENT_EVENT } from './KvCommentsListItem.vue';
17
+
18
+ export default {
19
+ components: { KvCommentsListItem },
20
+ props: {
21
+ /**
22
+ * Activity comments
23
+ */
24
+ comments: {
25
+ type: Object,
26
+ default: () => {},
27
+ },
28
+ },
29
+ methods: {
30
+ handleClick(payload) {
31
+ if ([REPLY_COMMENT_EVENT, LIKE_COMMENT_EVENT].includes(payload.reaction)) {
32
+ this.$emit(payload.reaction, { ...payload });
33
+ }
34
+ },
35
+ },
36
+ };
37
+ </script>
@@ -0,0 +1,121 @@
1
+ <template>
2
+ <div>
3
+ <div
4
+ class="tw-flex tw-items-center tw-gap-1"
5
+ >
6
+ <img
7
+ v-if="profileImage"
8
+ class="
9
+ data-hj-suppress
10
+ tw-inline-block
11
+ tw-w-3.5
12
+ tw-h-3.5
13
+ tw-rounded-full
14
+ tw-overflow-hidden
15
+ tw-object-fill
16
+ "
17
+ :src="profileImage"
18
+ alt="picture"
19
+ >
20
+ <p>
21
+ {{ text }}
22
+ </p>
23
+ </div>
24
+
25
+ <kv-button
26
+ variant="ghost"
27
+ class="tw-font-medium"
28
+ @click="onClick(REPLY_COMMENT_EVENT)"
29
+ >
30
+ Reply
31
+ </kv-button>
32
+ <kv-button
33
+ variant="ghost"
34
+ class="tw-font-medium"
35
+ @click="onClick(LIKE_COMMENT_EVENT)"
36
+ >
37
+ Like
38
+ </kv-button>
39
+ <div
40
+ v-if="latestChildren"
41
+ class="tw-my-1"
42
+ >
43
+ <p
44
+ v-for="nested_comment in latestChildren"
45
+ :key="nested_comment.id"
46
+ class="tw-ml-3"
47
+ >
48
+ <kv-comments-list-item
49
+ :comment="nested_comment"
50
+ :nest-level="nestLevel + 1"
51
+ :handle-click="handleClick"
52
+ />
53
+ </p>
54
+ </div>
55
+ </div>
56
+ </template>
57
+
58
+ <script>
59
+ import KvButton from './KvButton.vue';
60
+
61
+ export const REPLY_COMMENT_EVENT = 'reply-comment';
62
+ export const LIKE_COMMENT_EVENT = 'like-comment';
63
+
64
+ export default {
65
+ name: 'KvCommentsListItem',
66
+ components: { KvButton },
67
+ props: {
68
+ /**
69
+ * Activity comment
70
+ */
71
+ comment: {
72
+ type: Object,
73
+ default: () => ({}),
74
+ },
75
+ /**
76
+ * The nest level of the comment
77
+ */
78
+ nestLevel: {
79
+ type: Number,
80
+ default: 0,
81
+ },
82
+ /**
83
+ * The function to call when a reaction is clicked
84
+ */
85
+ handleClick: {
86
+ type: Function,
87
+ default: () => ({}),
88
+ },
89
+ },
90
+ setup(props) {
91
+ const onClick = (reaction) => {
92
+ props.handleClick({
93
+ reaction,
94
+ id: props.comment?.id ?? null,
95
+ userId: props.comment?.user_id ?? null,
96
+ isChild: true,
97
+ });
98
+ };
99
+
100
+ return {
101
+ onClick,
102
+ REPLY_COMMENT_EVENT,
103
+ LIKE_COMMENT_EVENT,
104
+ };
105
+ },
106
+ computed: {
107
+ text() {
108
+ return this.comment?.data?.text ?? '';
109
+ },
110
+ userId() {
111
+ return this.comment?.user_id ?? null;
112
+ },
113
+ latestChildren() {
114
+ return this.comment?.latest_children ?? null;
115
+ },
116
+ profileImage() {
117
+ return this.comment?.user_picture ?? '';
118
+ },
119
+ },
120
+ };
121
+ </script>
@@ -1,4 +1,5 @@
1
1
  import KvCommentsContainer from '../KvCommentsContainer.vue';
2
+ import comments from '../../tests/fixtures/mockFeedActivityData';
2
3
 
3
4
  export default {
4
5
  title: 'KvCommentsContainer',
@@ -20,4 +21,4 @@ const story = (args) => {
20
21
  return template;
21
22
  };
22
23
 
23
- export const Default = story({});
24
+ export const Default = story({ comments });
@@ -0,0 +1,24 @@
1
+ import KvCommentsList from '../KvCommentsList.vue';
2
+ import activityFeed from '../../tests/fixtures/mockFeedActivityData';
3
+
4
+ export default {
5
+ title: 'KvCommentsList',
6
+ component: KvCommentsList,
7
+ };
8
+
9
+ const story = (args) => {
10
+ const template = (templateArgs, { argTypes }) => ({
11
+ props: Object.keys(argTypes),
12
+ components: { KvCommentsList },
13
+ setup() { return { args: templateArgs }; },
14
+ template: `
15
+ <KvCommentsList v-bind="args" />
16
+ `,
17
+ });
18
+ template.args = args;
19
+ return template;
20
+ };
21
+
22
+ const comments = activityFeed.results[0].latest_reactions;
23
+
24
+ export const Default = story({ comments });
@@ -0,0 +1,24 @@
1
+ import KvCommentsListItem from '../KvCommentsListItem.vue';
2
+ import activityFeed from '../../tests/fixtures/mockFeedActivityData';
3
+
4
+ export default {
5
+ title: 'KvCommentsListItem',
6
+ component: KvCommentsListItem,
7
+ };
8
+
9
+ const story = (args) => {
10
+ const template = (templateArgs, { argTypes }) => ({
11
+ props: Object.keys(argTypes),
12
+ components: { KvCommentsListItem },
13
+ setup() { return { args: templateArgs }; },
14
+ template: `
15
+ <KvCommentsListItem v-bind="args" />
16
+ `,
17
+ });
18
+ template.args = args;
19
+ return template;
20
+ };
21
+
22
+ const comment = activityFeed.results[0].latest_reactions.comment[0];
23
+
24
+ export const Default = story({ comment });