From 136e83afc21cd5ae780cbe172f6b2d921a73516b Mon Sep 17 00:00:00 2001 From: Dries Cruyskens Date: Sat, 30 May 2020 03:10:11 +0200 Subject: [PATCH 1/3] Alphabetically sorting tags using compute functions on index and more-info page. Added test checking tags are present and shown alphabetically. --- webapp/pages/post/_id/_slug/index.spec.js | 44 +++++++++++++++++++++++ webapp/pages/post/_id/_slug/index.vue | 13 ++++++- webapp/pages/post/_id/_slug/more-info.vue | 13 ++++++- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/webapp/pages/post/_id/_slug/index.spec.js b/webapp/pages/post/_id/_slug/index.spec.js index 12a84d4a6..176041ecb 100644 --- a/webapp/pages/post/_id/_slug/index.spec.js +++ b/webapp/pages/post/_id/_slug/index.spec.js @@ -3,6 +3,7 @@ import Vuex from 'vuex' import Vue from 'vue' import PostSlug from './index.vue' import CommentList from '~/components/CommentList/CommentList' +import HcHashtag from '~/components/Hashtag/Hashtag' config.stubs['client-only'] = '' config.stubs['nuxt-link'] = '' @@ -143,5 +144,48 @@ describe('PostSlug', () => { }) }) }) + + describe('tags shown in tag cloud', () => { + beforeEach(async () => { + // Create backendData with tags, not alphabetically sorted. + backendData.post.tags = [ + { id: 'c' }, + { id: 'qw' }, + { id: 'BQ' }, + { id: '42' }, + { id: 'Bw' }, + { id: 'a' }, + ] + + wrapper = await Wrapper() + }) + + it('are present', async () => { + // Get length from backendData and compare against number of tags present in component. + expect(wrapper.findAll(HcHashtag).length).toBe(backendData.post.tags.length) + }) + + it('are alphabetically ordered', async () => { + // Get all HcHastag components + let wrappers = wrapper.findAll(HcHashtag).wrappers + // Exctract ID properties (tag names) from component. + let ids = [] + wrappers.forEach((x) => { + ids.push({ + id: x.props().id, + }) + }) + // Compare extracted IDs with solution. + let idsAlphabetically = [ + { id: '42' }, + { id: 'a' }, + { id: 'BQ' }, + { id: 'Bw' }, + { id: 'c' }, + { id: 'qw' }, + ] + expect(ids).toStrictEqual(idsAlphabetically) + }) + }) }) }) diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 9a4a796e1..2082cea0c 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -64,7 +64,7 @@
- +
@@ -179,6 +179,17 @@ export default { if (!author) return false return this.$store.getters['auth/user'].id === author.id }, + sortedTags() { + // Make sure the property is valid. + if (!this.post.tags || !this.post.tags.length) return false + // Sorting actually happens in place but that should not be a problem. + return this.post.tags.sort(function (a, b) { + // Converting to lowercase to make sort case insensitive. + const tagA = a.id.toLowerCase() + const tagB = b.id.toLowerCase() + return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 + }) + }, }, methods: { reply(message) { diff --git a/webapp/pages/post/_id/_slug/more-info.vue b/webapp/pages/post/_id/_slug/more-info.vue index 702de29ed..5dcaf4029 100644 --- a/webapp/pages/post/_id/_slug/more-info.vue +++ b/webapp/pages/post/_id/_slug/more-info.vue @@ -14,7 +14,7 @@

{{ $t('post.moreInfo.titleOfHashtagsSection') }}

- +

{{ $t('post.moreInfo.titleOfRelatedContributionsSection') }}

@@ -62,6 +62,17 @@ export default { post() { return this.Post ? this.Post[0] || {} : {} }, + sortedTags() { + // Make sure the property is valid. + if (!this.post.tags || !this.post.tags.length) return false + // Sorting actually happens in place but that should not be a problem. + return this.post.tags.sort(function (a, b) { + // Converting to lowercase to make sort case insensitive. + const tagA = a.id.toLowerCase() + const tagB = b.id.toLowerCase() + return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 + }) + }, }, methods: { removePostFromList(deletedPost) { From 43a3b57dd9059a79d0063d6537b99716e03657b0 Mon Sep 17 00:00:00 2001 From: Dries Cruyskens Date: Sat, 30 May 2020 03:20:50 +0200 Subject: [PATCH 2/3] Fixed linting issues and comments. --- webapp/pages/post/_id/_slug/index.spec.js | 8 ++++---- webapp/pages/post/_id/_slug/index.vue | 17 ++++++++++------- webapp/pages/post/_id/_slug/more-info.vue | 17 ++++++++++------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/webapp/pages/post/_id/_slug/index.spec.js b/webapp/pages/post/_id/_slug/index.spec.js index 176041ecb..bc54edf53 100644 --- a/webapp/pages/post/_id/_slug/index.spec.js +++ b/webapp/pages/post/_id/_slug/index.spec.js @@ -156,7 +156,7 @@ describe('PostSlug', () => { { id: 'Bw' }, { id: 'a' }, ] - + wrapper = await Wrapper() }) @@ -167,16 +167,16 @@ describe('PostSlug', () => { it('are alphabetically ordered', async () => { // Get all HcHastag components - let wrappers = wrapper.findAll(HcHashtag).wrappers + const wrappers = wrapper.findAll(HcHashtag).wrappers // Exctract ID properties (tag names) from component. - let ids = [] + const ids = [] wrappers.forEach((x) => { ids.push({ id: x.props().id, }) }) // Compare extracted IDs with solution. - let idsAlphabetically = [ + const idsAlphabetically = [ { id: '42' }, { id: 'a' }, { id: 'BQ' }, diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 2082cea0c..e552062f4 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -182,13 +182,16 @@ export default { sortedTags() { // Make sure the property is valid. if (!this.post.tags || !this.post.tags.length) return false - // Sorting actually happens in place but that should not be a problem. - return this.post.tags.sort(function (a, b) { - // Converting to lowercase to make sort case insensitive. - const tagA = a.id.toLowerCase() - const tagB = b.id.toLowerCase() - return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 - }) + /* Using .slice(0) to make a shallow copy. Otherwise a vue/no-side-effects-in-computed-properties error + would be thrown because sort() sorts in place. A shallow copy is fine because only first level objects are + affected by the sort, the original this.post.tags object remains unchanged. + */ + return this.post.tags.slice(0).sort(function (a, b) { + // Converting to lowercase to make sort case insensitive. + const tagA = a.id.toLowerCase() + const tagB = b.id.toLowerCase() + return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 + }) }, }, methods: { diff --git a/webapp/pages/post/_id/_slug/more-info.vue b/webapp/pages/post/_id/_slug/more-info.vue index 5dcaf4029..ac1a6694d 100644 --- a/webapp/pages/post/_id/_slug/more-info.vue +++ b/webapp/pages/post/_id/_slug/more-info.vue @@ -65,13 +65,16 @@ export default { sortedTags() { // Make sure the property is valid. if (!this.post.tags || !this.post.tags.length) return false - // Sorting actually happens in place but that should not be a problem. - return this.post.tags.sort(function (a, b) { - // Converting to lowercase to make sort case insensitive. - const tagA = a.id.toLowerCase() - const tagB = b.id.toLowerCase() - return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 - }) + /* Using .slice(0) to make a shallow copy. Otherwise a vue/no-side-effects-in-computed-properties error + would be thrown because sort() sorts in place. A shallow copy is fine because only first level objects are + affected by the sort, the original this.post.tags object remains unchanged. + */ + return this.post.tags.slice(0).sort(function (a, b) { + // Converting to lowercase to make sort case insensitive. + const tagA = a.id.toLowerCase() + const tagB = b.id.toLowerCase() + return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 + }) }, }, methods: { From 38d7ab9661ad77166576a7a79b53d5358a2b7080 Mon Sep 17 00:00:00 2001 From: Dries Cruyskens Date: Thu, 4 Jun 2020 00:18:51 +0200 Subject: [PATCH 3/3] Moved the sorting function to helper file to prevent duplicate code. --- webapp/components/utils/PostHelpers.js | 15 +++++++++++++++ webapp/pages/post/_id/_slug/index.vue | 19 ++++++------------- webapp/pages/post/_id/_slug/more-info.vue | 14 ++------------ 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/webapp/components/utils/PostHelpers.js b/webapp/components/utils/PostHelpers.js index 5ff912a97..403e49622 100644 --- a/webapp/components/utils/PostHelpers.js +++ b/webapp/components/utils/PostHelpers.js @@ -33,3 +33,18 @@ export function deletePostMutation(postId) { }, } } + +export function sortTagsAlphabetically(tags) { + // Make sure the property is valid. + if (!tags || !tags.length) return false + /* Using .slice(0) to make a shallow copy. Otherwise a vue/no-side-effects-in-computed-properties error + would be thrown because sort() sorts in place. A shallow copy is fine because only first level objects are + affected by the sort, the original tags object remains unchanged. + */ + return tags.slice(0).sort(function (a, b) { + // Converting to lowercase to make sort case insensitive. + const tagA = a.id.toLowerCase() + const tagB = b.id.toLowerCase() + return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 + }) +} diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index e552062f4..e3f82e5ce 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -116,7 +116,11 @@ import UserTeaser from '~/components/UserTeaser/UserTeaser' import HcShoutButton from '~/components/ShoutButton.vue' import CommentForm from '~/components/CommentForm/CommentForm' import CommentList from '~/components/CommentList/CommentList' -import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers' +import { + postMenuModalsData, + deletePostMutation, + sortTagsAlphabetically, +} from '~/components/utils/PostHelpers' import PostQuery from '~/graphql/PostQuery' import HcEmotions from '~/components/Emotions/Emotions' import PostMutations from '~/graphql/PostMutations' @@ -180,18 +184,7 @@ export default { return this.$store.getters['auth/user'].id === author.id }, sortedTags() { - // Make sure the property is valid. - if (!this.post.tags || !this.post.tags.length) return false - /* Using .slice(0) to make a shallow copy. Otherwise a vue/no-side-effects-in-computed-properties error - would be thrown because sort() sorts in place. A shallow copy is fine because only first level objects are - affected by the sort, the original this.post.tags object remains unchanged. - */ - return this.post.tags.slice(0).sort(function (a, b) { - // Converting to lowercase to make sort case insensitive. - const tagA = a.id.toLowerCase() - const tagB = b.id.toLowerCase() - return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 - }) + return sortTagsAlphabetically(this.post.tags) }, }, methods: { diff --git a/webapp/pages/post/_id/_slug/more-info.vue b/webapp/pages/post/_id/_slug/more-info.vue index ac1a6694d..b99552667 100644 --- a/webapp/pages/post/_id/_slug/more-info.vue +++ b/webapp/pages/post/_id/_slug/more-info.vue @@ -44,6 +44,7 @@ import HcHashtag from '~/components/Hashtag/Hashtag' import { relatedContributions } from '~/graphql/PostQuery' import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue' import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue' +import { sortTagsAlphabetically } from '~/components/utils/PostHelpers' export default { transition: { @@ -63,18 +64,7 @@ export default { return this.Post ? this.Post[0] || {} : {} }, sortedTags() { - // Make sure the property is valid. - if (!this.post.tags || !this.post.tags.length) return false - /* Using .slice(0) to make a shallow copy. Otherwise a vue/no-side-effects-in-computed-properties error - would be thrown because sort() sorts in place. A shallow copy is fine because only first level objects are - affected by the sort, the original this.post.tags object remains unchanged. - */ - return this.post.tags.slice(0).sort(function (a, b) { - // Converting to lowercase to make sort case insensitive. - const tagA = a.id.toLowerCase() - const tagB = b.id.toLowerCase() - return tagA < tagB ? -1 : tagA > tagB ? 1 : 0 - }) + return sortTagsAlphabetically(this.post.tags) }, }, methods: {