diff --git a/backend/src/seed/seed-db.js b/backend/src/seed/seed-db.js
index 76fbb4875..40becda2a 100644
--- a/backend/src/seed/seed-db.js
+++ b/backend/src/seed/seed-db.js
@@ -1,10 +1,13 @@
import faker from 'faker'
+import sample from 'lodash/sample'
import { createTestClient } from 'apollo-server-testing'
import createServer from '../server'
import Factory from './factories'
import { neode as getNeode, getDriver } from '../bootstrap/neo4j'
import { gql } from '../jest/helpers'
+const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
+
/* eslint-disable no-multi-spaces */
;(async function() {
let authenticatedUser = null
@@ -341,39 +344,46 @@ import { gql } from '../jest/helpers'
factory.create('Post', {
author: peterLustig,
id: 'p0',
+ language: sample(languages),
image: faker.image.unsplash.food(),
categoryIds: ['cat16'],
}),
factory.create('Post', {
author: bobDerBaumeister,
id: 'p1',
+ language: sample(languages),
image: faker.image.unsplash.technology(),
categoryIds: ['cat1'],
}),
factory.create('Post', {
author: huey,
id: 'p3',
+ language: sample(languages),
categoryIds: ['cat3'],
}),
factory.create('Post', {
author: dewey,
id: 'p4',
+ language: sample(languages),
categoryIds: ['cat4'],
}),
factory.create('Post', {
author: louie,
id: 'p5',
+ language: sample(languages),
categoryIds: ['cat5'],
}),
factory.create('Post', {
authorId: 'u1',
id: 'p6',
+ language: sample(languages),
image: faker.image.unsplash.buildings(),
categoryIds: ['cat6'],
}),
factory.create('Post', {
author: huey,
id: 'p9',
+ language: sample(languages),
categoryIds: ['cat9'],
}),
factory.create('Post', {
@@ -384,23 +394,27 @@ import { gql } from '../jest/helpers'
factory.create('Post', {
author: louie,
id: 'p11',
+ language: sample(languages),
image: faker.image.unsplash.people(),
categoryIds: ['cat11'],
}),
factory.create('Post', {
author: bobDerBaumeister,
id: 'p13',
+ language: sample(languages),
categoryIds: ['cat13'],
}),
factory.create('Post', {
author: jennyRostock,
id: 'p14',
+ language: sample(languages),
image: faker.image.unsplash.objects(),
categoryIds: ['cat14'],
}),
factory.create('Post', {
author: huey,
id: 'p15',
+ language: sample(languages),
categoryIds: ['cat15'],
}),
])
diff --git a/webapp/components/FilterPosts/FilterPosts.spec.js b/webapp/components/FilterPosts/FilterPosts.spec.js
index 1f0ee920d..504112572 100644
--- a/webapp/components/FilterPosts/FilterPosts.spec.js
+++ b/webapp/components/FilterPosts/FilterPosts.spec.js
@@ -3,6 +3,9 @@ import VTooltip from 'v-tooltip'
import Styleguide from '@human-connection/styleguide'
import Vuex from 'vuex'
import FilterPosts from './FilterPosts.vue'
+import locales from '~/locales'
+import orderBy from 'lodash/orderBy'
+
const localVue = createLocalVue()
localVue.use(Styleguide)
@@ -12,6 +15,8 @@ localVue.use(Vuex)
let mutations
let getters
+const languages = orderBy(locales, 'name')
+
describe('FilterPosts.vue', () => {
let mocks
let propsData
@@ -20,6 +25,8 @@ describe('FilterPosts.vue', () => {
let environmentAndNatureButton
let democracyAndPoliticsButton
let happyEmotionButton
+ let englishButton
+ let spanishButton
beforeEach(() => {
mocks = {
@@ -54,6 +61,8 @@ describe('FilterPosts.vue', () => {
'posts/RESET_CATEGORIES': jest.fn(),
'posts/TOGGLE_CATEGORY': jest.fn(),
'posts/TOGGLE_EMOTION': jest.fn(),
+ 'posts/TOGGLE_LANGUAGE': jest.fn(),
+ 'posts/RESET_LANGUAGES': jest.fn(),
}
getters = {
'posts/isActive': () => false,
@@ -64,6 +73,7 @@ describe('FilterPosts.vue', () => {
'posts/filteredCategoryIds': jest.fn(() => []),
'posts/filteredByUsersFollowed': jest.fn(),
'posts/filteredByEmotions': jest.fn(() => []),
+ 'posts/filteredLanguageCodes': jest.fn(() => []),
}
const openFilterPosts = () => {
const store = new Vuex.Store({ mutations, getters })
@@ -97,6 +107,15 @@ describe('FilterPosts.vue', () => {
expect(mutations['posts/TOGGLE_CATEGORY']).toHaveBeenCalledWith({}, 'cat4')
})
+ it('calls TOGGLE_LANGUAGE when clicked', () => {
+ const wrapper = openFilterPosts()
+ englishButton = wrapper
+ .findAll('button.language-buttons')
+ .at(languages.findIndex(l => l.code === 'en'))
+ englishButton.trigger('click')
+ expect(mutations['posts/TOGGLE_LANGUAGE']).toHaveBeenCalledWith({}, 'en')
+ })
+
it('sets category button attribute `primary` when corresponding category is filtered', () => {
getters['posts/filteredCategoryIds'] = jest.fn(() => ['cat9'])
const wrapper = openFilterPosts()
@@ -104,6 +123,15 @@ describe('FilterPosts.vue', () => {
expect(democracyAndPoliticsButton.attributes().class).toContain('ds-button-primary')
})
+ it('sets language button attribute `primary` when corresponding language is filtered', () => {
+ getters['posts/filteredLanguageCodes'] = jest.fn(() => ['es'])
+ const wrapper = openFilterPosts()
+ spanishButton = wrapper
+ .findAll('button.language-buttons')
+ .at(languages.findIndex(l => l.code === 'es'))
+ expect(spanishButton.attributes().class).toContain('ds-button-primary')
+ })
+
it('sets "filter-by-followed-authors-only" button attribute `primary`', () => {
getters['posts/filteredByUsersFollowed'] = jest.fn(() => true)
const wrapper = openFilterPosts()
diff --git a/webapp/components/FilterPosts/FilterPosts.vue b/webapp/components/FilterPosts/FilterPosts.vue
index 58f0794d2..1dd0fa737 100644
--- a/webapp/components/FilterPosts/FilterPosts.vue
+++ b/webapp/components/FilterPosts/FilterPosts.vue
@@ -14,6 +14,7 @@
+
@@ -24,12 +25,14 @@ import Dropdown from '~/components/Dropdown'
import { mapGetters } from 'vuex'
import CategoriesFilterMenuItems from './CategoriesFilterMenuItems'
import GeneralFilterMenuItems from './GeneralFilterMenuItems'
+import LanguageFilterMenuItems from './LanguageFilterMenuItems'
export default {
components: {
Dropdown,
CategoriesFilterMenuItems,
GeneralFilterMenuItems,
+ LanguageFilterMenuItems,
},
props: {
placement: { type: String },
diff --git a/webapp/components/FilterPosts/LanguageFilterMenuItems.vue b/webapp/components/FilterPosts/LanguageFilterMenuItems.vue
new file mode 100644
index 000000000..258b3acdc
--- /dev/null
+++ b/webapp/components/FilterPosts/LanguageFilterMenuItems.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/webapp/locales/de.json b/webapp/locales/de.json
index 67d3b5bbd..34cd948ed 100644
--- a/webapp/locales/de.json
+++ b/webapp/locales/de.json
@@ -86,6 +86,10 @@
},
"followers": {
"label": "Benutzern, denen ich folge"
+ },
+ "language": {
+ "header": "Sprachen",
+ "all": "Alle"
}
},
"site": {
diff --git a/webapp/locales/en.json b/webapp/locales/en.json
index d9321b13b..d3b4e8edc 100644
--- a/webapp/locales/en.json
+++ b/webapp/locales/en.json
@@ -87,6 +87,10 @@
},
"followers": {
"label": "Users I follow"
+ },
+ "language": {
+ "header": "Languages",
+ "all": "All"
}
},
"site": {
diff --git a/webapp/store/posts.js b/webapp/store/posts.js
index 97c0e1245..25a48f0d5 100644
--- a/webapp/store/posts.js
+++ b/webapp/store/posts.js
@@ -48,12 +48,23 @@ export const mutations = {
delete filter.categories_some
state.filter = filter
},
+ RESET_LANGUAGES(state) {
+ const filter = clone(state.filter)
+ delete filter.language_in
+ state.filter = filter
+ },
TOGGLE_CATEGORY(state, categoryId) {
const filter = clone(state.filter)
update(filter, 'categories_some.id_in', categoryIds => xor(categoryIds, [categoryId]))
if (isEmpty(get(filter, 'categories_some.id_in'))) delete filter.categories_some
state.filter = filter
},
+ TOGGLE_LANGUAGE(state, languageCode) {
+ const filter = clone(state.filter)
+ update(filter, 'language_in', languageCodes => xor(languageCodes, [languageCode]))
+ if (isEmpty(get(filter, 'language_in'))) delete filter.language_in
+ state.filter = filter
+ },
TOGGLE_EMOTION(state, emotion) {
const filter = clone(state.filter)
update(filter, 'emotions_some.emotion_in', emotions => xor(emotions, [emotion]))
@@ -75,6 +86,9 @@ export const getters = {
filteredCategoryIds(state) {
return get(state.filter, 'categories_some.id_in') || []
},
+ filteredLanguageCodes(state) {
+ return get(state.filter, 'language_in') || []
+ },
filteredByUsersFollowed(state) {
return !!get(state.filter, 'author.followedBy_some.id')
},
diff --git a/webapp/store/posts.spec.js b/webapp/store/posts.spec.js
index 536c4c924..05cea7b13 100644
--- a/webapp/store/posts.spec.js
+++ b/webapp/store/posts.spec.js
@@ -19,12 +19,24 @@ describe('getters', () => {
expect(getters.filteredCategoryIds(state)).toEqual([24])
})
- it('returns empty array if filter is not set', () => {
+ it('returns empty array if category filter is not set', () => {
state = { filter: { author: { followedBy_some: { id: 7 } } } }
expect(getters.filteredCategoryIds(state)).toEqual([])
})
})
+ describe('filteredLanguageCodes', () => {
+ it('returns category ids if filter is set', () => {
+ state = { filter: { language_in: ['en', 'de', 'pt'] } }
+ expect(getters.filteredLanguageCodes(state)).toEqual(['en', 'de', 'pt'])
+ })
+
+ it('returns empty array if language filter is not set', () => {
+ state = { filter: { author: { followedBy_some: { id: 7 } } } }
+ expect(getters.filteredLanguageCodes(state)).toEqual([])
+ })
+ })
+
describe('filter', () => {
it('returns filter', () => {
state = { filter: { author: { followedBy_some: { id: 7 } } } }
@@ -104,6 +116,19 @@ describe('getters', () => {
})
describe('mutations', () => {
+ describe('RESET_LANGUAGES', () => {
+ it('resets the languages filter', () => {
+ state = {
+ filter: {
+ author: { followedBy_some: { id: 7 } },
+ language_in: ['nl'],
+ },
+ }
+ mutations.RESET_LANGUAGES(state)
+ expect(getters.filter(state)).toEqual({ author: { followedBy_some: { id: 7 } } })
+ })
+ })
+
describe('RESET_CATEGORIES', () => {
beforeEach(() => {
testMutation = categoryId => {
@@ -122,6 +147,45 @@ describe('mutations', () => {
})
})
+ describe('TOGGLE_LANGUAGE', () => {
+ beforeEach(() => {
+ testMutation = languageCode => {
+ mutations.TOGGLE_LANGUAGE(state, languageCode)
+ return getters.filter(state)
+ }
+ })
+
+ it('creates category filter if empty', () => {
+ state = { filter: {} }
+ expect(testMutation('de')).toEqual({ language_in: ['de'] })
+ })
+
+ it('adds language code to existing filter', () => {
+ state = { filter: { language_in: ['de'] } }
+ expect(testMutation('en')).toEqual({ language_in: ['de', 'en'] })
+ })
+
+ it('removes category id if present', () => {
+ state = { filter: { language_in: ['de', 'en'] } }
+ expect(testMutation('de')).toEqual({ language_in: ['en'] })
+ })
+
+ it('removes language filter if empty', () => {
+ state = { filter: { language_in: ['de'] } }
+ expect(testMutation('de')).toEqual({})
+ })
+
+ it('does not get in the way of other filters', () => {
+ state = {
+ filter: {
+ author: { followedBy_some: { id: 7 } },
+ language_in: ['de'],
+ },
+ }
+ expect(testMutation('de')).toEqual({ author: { followedBy_some: { id: 7 } } })
+ })
+ })
+
describe('TOGGLE_CATEGORY', () => {
beforeEach(() => {
testMutation = categoryId => {