mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
Merge remote-tracking branch 'origin/fix-category-filter-buttons' into merge-all-events
This commit is contained in:
commit
e0b93ae796
5
webapp/assets/_new/icons/svgs/book.svg
Normal file
5
webapp/assets/_new/icons/svgs/book.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<title>book</title>
|
||||
<path d="M10 5c2.92 0 5.482 0.981 6 1.188 0.518-0.206 3.080-1.188 6-1.188 3.227 0 6.375 1.313 6.375 1.313l0.625 0.281v20.406h-11.281c-0.346 0.597-0.979 1-1.719 1s-1.373-0.403-1.719-1h-11.281v-20.406l0.625-0.281s3.148-1.313 6.375-1.313zM10 7c-2.199 0-4.232 0.69-5 0.969v16.125c1.188-0.392 2.897-0.875 5-0.875 2.057 0 3.888 0.506 5 0.875v-16.125c-1-0.343-3.067-0.969-5-0.969zM22 7c-1.933 0-4 0.626-5 0.969v16.125c1.112-0.369 2.943-0.875 5-0.875 2.103 0 3.813 0.483 5 0.875v-16.125c-0.768-0.279-2.801-0.969-5-0.969z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 680 B |
5
webapp/assets/_new/icons/svgs/calendar.svg
Normal file
5
webapp/assets/_new/icons/svgs/calendar.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<!-- Generated by IcoMoon.io -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<title>calendar</title>
|
||||
<path d="M9 4h2v1h10v-1h2v1h4v22h-22v-22h4v-1zM7 7v2h18v-2h-2v1h-2v-1h-10v1h-2v-1h-2zM7 11v14h18v-14h-18zM13 13h2v2h-2v-2zM17 13h2v2h-2v-2zM21 13h2v2h-2v-2zM9 17h2v2h-2v-2zM13 17h2v2h-2v-2zM17 17h2v2h-2v-2zM21 17h2v2h-2v-2zM9 21h2v2h-2v-2zM13 21h2v2h-2v-2zM17 21h2v2h-2v-2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 445 B |
@ -17,18 +17,22 @@
|
||||
</template>
|
||||
|
||||
<template #filter-list>
|
||||
<li v-for="category in categories" :key="category.id" class="item item-category">
|
||||
<labeled-button
|
||||
:icon="category.icon"
|
||||
:filled="filteredCategoryIds.includes(category.id)"
|
||||
:label="$t(`contribution.category.name.${category.slug}`)"
|
||||
<div class="category-filter-list">
|
||||
<base-button
|
||||
v-for="category in categories"
|
||||
:key="category.id"
|
||||
@click="toggleCategory(category.id)"
|
||||
:filled="filteredCategoryIds.includes(category.id)"
|
||||
:icon="category.icon"
|
||||
size="small"
|
||||
v-tooltip="{
|
||||
content: $t(`contribution.category.description.${category.slug}`),
|
||||
placement: 'bottom-start',
|
||||
}"
|
||||
/>
|
||||
</li>
|
||||
>
|
||||
{{ $t(`contribution.category.name.${category.slug}`) }}
|
||||
</base-button>
|
||||
</div>
|
||||
</template>
|
||||
</filter-menu-section>
|
||||
</template>
|
||||
@ -95,3 +99,13 @@ export default {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.category-filter-list {
|
||||
margin-left: $space-xx-large;
|
||||
|
||||
> .base-button {
|
||||
margin-right: $space-xx-small;
|
||||
margin-bottom: $space-xx-small;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
<div class="filter-menu-options">
|
||||
<h2 class="title">{{ $t('filter-menu.filter-by') }}</h2>
|
||||
<following-filter />
|
||||
<post-type-filter />
|
||||
<categories-filter v-if="categoriesActive" @showFilterMenu="$emit('showFilterMenu')" />
|
||||
</div>
|
||||
<div class="filter-menu-options">
|
||||
@ -13,6 +14,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PostTypeFilter from './PostTypeFilter'
|
||||
import FollowingFilter from './FollowingFilter'
|
||||
import OrderByFilter from './OrderByFilter'
|
||||
import CategoriesFilter from './CategoriesFilter'
|
||||
@ -22,6 +24,7 @@ export default {
|
||||
FollowingFilter,
|
||||
OrderByFilter,
|
||||
CategoriesFilter,
|
||||
PostTypeFilter,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
59
webapp/components/FilterMenu/PostTypeFilter.vue
Normal file
59
webapp/components/FilterMenu/PostTypeFilter.vue
Normal file
@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<filter-menu-section
|
||||
:title="$t('filter-menu.post-type')"
|
||||
:divider="false"
|
||||
class="following-filter"
|
||||
>
|
||||
<template #filter-follower>
|
||||
<li class="item article-item">
|
||||
<labeled-button
|
||||
icon="book"
|
||||
:label="$t('filter-menu.article')"
|
||||
:filled="articleSet"
|
||||
:title="$t('filter-menu.article')"
|
||||
@click="toggleFilterPostType('Article')"
|
||||
/>
|
||||
</li>
|
||||
<li class="item event-item">
|
||||
<labeled-button
|
||||
icon="calendar"
|
||||
:label="$t('filter-menu.events')"
|
||||
:filled="eventSet"
|
||||
:title="$t('filter-menu.events')"
|
||||
@click="toggleFilterPostType('Event')"
|
||||
/>
|
||||
</li>
|
||||
</template>
|
||||
</filter-menu-section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
|
||||
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
|
||||
|
||||
export default {
|
||||
name: 'PostTypeFilter',
|
||||
components: {
|
||||
FilterMenuSection,
|
||||
LabeledButton,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
filteredPostTypes: 'posts/filteredPostTypes',
|
||||
currentUser: 'auth/user',
|
||||
}),
|
||||
articleSet() {
|
||||
return this.filteredPostTypes.includes('Article')
|
||||
},
|
||||
eventSet() {
|
||||
return this.filteredPostTypes.includes('Event')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
toggleFilterPostType: 'posts/TOGGLE_POST_TYPE',
|
||||
}),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -378,9 +378,11 @@
|
||||
},
|
||||
"filter-menu": {
|
||||
"all": "Alle",
|
||||
"article": "Artikel",
|
||||
"categories": "Themen",
|
||||
"deleteFilter": "Filter löschen",
|
||||
"emotions": "Emotionen",
|
||||
"events": "Veranstaltungen",
|
||||
"filter-by": "Filtern nach ...",
|
||||
"following": "Nutzer denen ich folge",
|
||||
"languages": "Sprachen",
|
||||
@ -396,6 +398,7 @@
|
||||
}
|
||||
},
|
||||
"order-by": "Sortieren nach ...",
|
||||
"post-type": "Beitrags-Typ",
|
||||
"save": {
|
||||
"error": "Themen konnten nicht gespeichert werden!",
|
||||
"success": "Themen gespeichert!"
|
||||
|
||||
@ -378,9 +378,11 @@
|
||||
},
|
||||
"filter-menu": {
|
||||
"all": "All",
|
||||
"article": "Article",
|
||||
"categories": "Topics",
|
||||
"deleteFilter": "Delete filter",
|
||||
"emotions": "Emotions",
|
||||
"events": "Events",
|
||||
"filter-by": "Filter by ...",
|
||||
"following": "Users I follow",
|
||||
"languages": "Languages",
|
||||
@ -396,6 +398,7 @@
|
||||
}
|
||||
},
|
||||
"order-by": "Order by ...",
|
||||
"post-type": "Post type",
|
||||
"save": {
|
||||
"error": "Failed saving topic settings!",
|
||||
"success": "Topics saved!"
|
||||
|
||||
@ -63,6 +63,12 @@ export const mutations = {
|
||||
if (isEmpty(get(filter, 'categories_some.id_in'))) delete filter.categories_some
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_POST_TYPE(state, postType) {
|
||||
const filter = clone(state.filter)
|
||||
update(filter, 'postType_in', (postTypes) => xor(postTypes, [postType]))
|
||||
if (isEmpty(get(filter, 'postType_in'))) delete filter.postType_in
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_LANGUAGE(state, languageCode) {
|
||||
const filter = clone(state.filter)
|
||||
update(filter, 'language_in', (languageCodes) => xor(languageCodes, [languageCode]))
|
||||
@ -90,6 +96,9 @@ export const getters = {
|
||||
filteredCategoryIds(state) {
|
||||
return get(state.filter, 'categories_some.id_in') || []
|
||||
},
|
||||
filteredPostTypes(state) {
|
||||
return get(state.filter, 'postType_in') || []
|
||||
},
|
||||
filteredLanguageCodes(state) {
|
||||
return get(state.filter, 'language_in') || []
|
||||
},
|
||||
|
||||
@ -25,6 +25,18 @@ describe('getters', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('filteredPostTypes', () => {
|
||||
it('returns post types if filter is set', () => {
|
||||
state = { filter: { postType_in: ['Article', 'Event'] } }
|
||||
expect(getters.filteredPostTypes(state)).toEqual(['Article', 'Event'])
|
||||
})
|
||||
|
||||
it('returns empty array if post type filter is not set', () => {
|
||||
state = { filter: { author: { followedBy_some: { id: 7 } } } }
|
||||
expect(getters.filteredPostTypes(state)).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('filteredLanguageCodes', () => {
|
||||
it('returns category ids if filter is set', () => {
|
||||
state = { filter: { language_in: ['en', 'de', 'pt'] } }
|
||||
@ -213,6 +225,46 @@ describe('mutations', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('TOGGLE_POST_TYPE', () => {
|
||||
beforeEach(() => {
|
||||
testMutation = (postType) => {
|
||||
mutations.TOGGLE_POST_TYPE(state, postType)
|
||||
return getters.filter(state)
|
||||
}
|
||||
})
|
||||
|
||||
it('creates post type filter if empty', () => {
|
||||
state = { filter: {} }
|
||||
expect(testMutation('Event')).toEqual({ postType_in: ['Event'] })
|
||||
})
|
||||
|
||||
it('adds post type not present', () => {
|
||||
state = { filter: { postType_in: ['Event'] } }
|
||||
expect(testMutation('Article')).toEqual({ postType_in: ['Event', 'Article'] })
|
||||
})
|
||||
|
||||
it('removes category id if present', () => {
|
||||
state = { filter: { postType_in: ['Event', 'Article'] } }
|
||||
const result = testMutation('Event')
|
||||
expect(result).toEqual({ postType_in: ['Article'] })
|
||||
})
|
||||
|
||||
it('removes category filter if empty', () => {
|
||||
state = { filter: { postType_in: ['Event'] } }
|
||||
expect(testMutation('Event')).toEqual({})
|
||||
})
|
||||
|
||||
it('does not get in the way of other filters', () => {
|
||||
state = {
|
||||
filter: {
|
||||
author: { followedBy_some: { id: 7 } },
|
||||
postType_in: ['Event'],
|
||||
},
|
||||
}
|
||||
expect(testMutation('Event')).toEqual({ author: { followedBy_some: { id: 7 } } })
|
||||
})
|
||||
})
|
||||
|
||||
describe('TOGGLE_FILTER_BY_FOLLOWED', () => {
|
||||
beforeEach(() => {
|
||||
testMutation = (userId) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user