Style categories filter dropdown, get working with multiple categories

This commit is contained in:
Matt Rider 2019-07-08 21:44:47 -03:00
parent 3dc5888364
commit 737d1f839a
4 changed files with 273 additions and 46 deletions

View File

@ -4,24 +4,191 @@
<ds-icon style="margin: 5px 0px 0px 10px;" name="filter" size="large" /> <ds-icon style="margin: 5px 0px 0px 10px;" name="filter" size="large" />
<ds-icon style="margin-left: 2px" size="xx-small" name="angle-down" /> <ds-icon style="margin-left: 2px" size="xx-small" name="angle-down" />
</a> </a>
<ds-menu slot="popover" slot-scope="{ toggleMenu }" :routes="routes"> <template slot="popover">
<ds-menu-item <ds-container>
slot="menuitem" <ds-space />
slot-scope="item" <ds-flex>
:route="item.route"
@click.stop.prevent="filterPosts(item.route.name, toggleMenu)"
class="categories-menu"
>
<ds-flex class="categories-list">
<ds-flex-item width="20%"> <ds-flex-item width="20%">
<ds-button :icon="item.route.icon" primary /> <ds-space margin-bottom="x-small" />
<ds-flex>
<ds-heading tag="h4">{{ $t('filter-posts.header') }}</ds-heading>
<ds-flex-item width="10%" />
<ds-flex-item width="100%" style="text-align:center;">
<ds-button
icon="check"
@click.stop.prevent="toggleCategory()"
:primary="allCategories"
/>
<ds-flex-item>
<label>{{ $t('filter-posts.all') }}</label>
</ds-flex-item> </ds-flex-item>
<ds-flex-item width="80%"> <ds-space />
<ds-flex>{{ item.route.name }}</ds-flex>
</ds-flex-item> </ds-flex-item>
</ds-flex> </ds-flex>
</ds-menu-item> </ds-flex-item>
</ds-menu> <ds-flex-item width="10%">
<ds-flex v-for="category in firstGroup" :key="category.id" class="categories-list">
<ds-flex>
<ds-flex-item width="100%">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex>
<ds-flex-item>
<label>{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
<ds-flex-item width="10%">
<ds-flex v-for="category in secondGroup" :key="category.id" class="categories-list">
<ds-flex>
<ds-flex-item width="100%">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex class="categories-list">
<ds-flex-item>
<label>{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
<ds-flex-item width="10%">
<ds-flex v-for="category in thirdGroup" :key="category.id" class="categories-list">
<ds-flex>
<ds-flex-item width="100%">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex>
<ds-flex-item>
<label>{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
<ds-flex-item width="10%">
<ds-flex v-for="category in fourthGroup" :key="category.id" class="categories-list">
<ds-flex>
<ds-flex-item width="100%">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex>
<ds-flex-item>
<label>{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
<ds-flex-item width="10%">
<ds-flex v-for="category in fifthGroup" :key="category.id" class="categories-list">
<ds-flex>
<ds-flex-item width="100%">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex>
<ds-flex-item>
<label>{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
<ds-flex-item width="10%">
<ds-flex v-for="category in sixthGroup" :key="category.id" class="categories-list">
<ds-flex>
<ds-flex-item width="100%">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex>
<ds-flex-item>
<label>{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
<ds-flex-item width="10%">
<ds-flex v-for="category in seventhGroup" :key="category.id" class="categories-list">
<ds-flex>
<ds-flex-item width="100%">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex>
<ds-flex-item>
<label>{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
<ds-flex-item width="10%">
<ds-flex v-for="category in eigthGroup" :key="category.id" class="categories-list">
<ds-flex>
<ds-flex-item width="100%">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex>
<ds-flex-item>
<label>{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
</ds-flex>
</ds-container>
</template>
</dropdown> </dropdown>
</template> </template>
<script> <script>
@ -41,31 +208,60 @@ export default {
data() { data() {
return { return {
pageSize: 12, pageSize: 12,
firstGroup: [],
secondGroup: [],
thirdGroup: [],
fourthGroup: [],
fifthGroup: [],
sixthGroup: [],
seventhGroup: [],
eigthGroup: [],
selectedCategoryIds: [],
allCategories: true,
} }
}, },
computed: { computed: {
routes() { chunk() {
let routes = this.categories.map(category => { const groupedCategories = []
return { for (let i = 0; i < this.categories.length; i++) {
name: category.name, const last = groupedCategories[groupedCategories.length - 1]
id: category.id, if (!last || last.length === 2) {
icon: category.icon, groupedCategories.push([this.categories[i]])
} else {
last.push(this.categories[i])
} }
}) }
return routes return groupedCategories
}, },
}, },
mounted() {
this.groupCategories()
},
methods: { methods: {
...mapMutations({ ...mapMutations({
setPosts: 'posts/SET_POSTS', setPosts: 'posts/SET_POSTS',
}), }),
filterPosts(name) { groupCategories() {
this.filter = { categories_some: { name } } const groupedCategories = this.chunk
this.firstGroup = groupedCategories[0]
this.secondGroup = groupedCategories[1]
this.thirdGroup = groupedCategories[2]
this.fourthGroup = groupedCategories[3]
this.fifthGroup = groupedCategories[4]
this.sixthGroup = groupedCategories[5]
this.seventhGroup = groupedCategories[6]
this.eigthGroup = groupedCategories[7]
},
filterPosts(categoryIds) {
const filter = categoryIds.length
? { categories_in: { id_in: this.selectedCategoryIds } }
: {}
filter.categories_in ? (this.allCategories = false) : (this.allCategories = true)
this.$apollo this.$apollo
.query({ .query({
query: filterPosts(this.$i18n), query: filterPosts(this.$i18n),
variables: { variables: {
filter: this.filter, filter: filter,
first: this.pageSize, first: this.pageSize,
offset: 0, offset: 0,
}, },
@ -75,20 +271,28 @@ export default {
}) })
.catch(error => this.$toast.error(error.message)) .catch(error => this.$toast.error(error.message))
}, },
isActive(id) {
const index = this.selectedCategoryIds.indexOf(id)
if (index > -1) {
return true
}
return false
},
toggleCategory(id) {
const index = this.selectedCategoryIds.indexOf(id)
if (index > -1) {
this.selectedCategoryIds.splice(index, 1)
} else {
this.selectedCategoryIds.push(id)
}
if (!id) this.selectedCategoryIds = []
this.filterPosts(this.selectedCategoryIds)
},
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.categories-menu {
width: 300px;
}
.category-menu-item {
text-align: center;
padding-bottom: 20px;
}
.categories-list { .categories-list {
display: flex; text-align: center;
align-items: baseline;
} }
</style> </style>

View File

@ -6,7 +6,7 @@
<ds-flex class="main-navigation-flex"> <ds-flex class="main-navigation-flex">
<ds-flex-item :width="{ lg: '5%' }" /> <ds-flex-item :width="{ lg: '5%' }" />
<ds-flex-item :width="{ base: '80%', sm: '80%', md: '80%', lg: '15%' }"> <ds-flex-item :width="{ base: '80%', sm: '80%', md: '80%', lg: '15%' }">
<a @click="$router.go('/')"> <a @click="$router.push('/').go('/')">
<ds-logo /> <ds-logo />
</a> </a>
</ds-flex-item> </ds-flex-item>
@ -37,7 +37,7 @@
:class="{ 'hide-mobile-menu': !toggleMobileMenu }" :class="{ 'hide-mobile-menu': !toggleMobileMenu }"
> >
<no-ssr> <no-ssr>
<filter-posts placement="bottom" offset="23" :categories="categories" /> <filter-posts placement="bottom-end" offset="23" :categories="getCategories" />
</no-ssr> </no-ssr>
</ds-flex-item> </ds-flex-item>
<ds-flex-item <ds-flex-item
@ -129,7 +129,8 @@
</template> </template>
<script> <script>
import { mapGetters, mapActions } from 'vuex' import gql from 'graphql-tag'
import { mapGetters, mapActions, mapMutations } from 'vuex'
import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch' import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch'
import SearchInput from '~/components/SearchInput.vue' import SearchInput from '~/components/SearchInput.vue'
import Modal from '~/components/Modal' import Modal from '~/components/Modal'
@ -164,7 +165,7 @@ export default {
isAdmin: 'auth/isAdmin', isAdmin: 'auth/isAdmin',
quickSearchResults: 'search/quickResults', quickSearchResults: 'search/quickResults',
quickSearchPending: 'search/quickPending', quickSearchPending: 'search/quickPending',
categories: 'categories/categories', getCategories: 'categories/categories',
}), }),
userName() { userName() {
const { name } = this.user || {} const { name } = this.user || {}
@ -203,14 +204,13 @@ export default {
return routes return routes
}, },
}, },
mounted() {
this.fetchCategories()
},
methods: { methods: {
...mapActions({ ...mapActions({
quickSearchClear: 'search/quickClear', quickSearchClear: 'search/quickClear',
quickSearch: 'search/quickSearch', quickSearch: 'search/quickSearch',
fetchCategories: 'categories/fetchCategories', }),
...mapMutations({
setCategories: 'categories/SET_CATEGORIES',
}), }),
goToPost(item) { goToPost(item) {
this.$nextTick(() => { this.$nextTick(() => {
@ -237,6 +237,23 @@ export default {
this.toggleMobileMenu = !this.toggleMobileMenu this.toggleMobileMenu = !this.toggleMobileMenu
}, },
}, },
apollo: {
Category: {
query() {
return gql(`{
Category {
id
name
icon
}
}`)
},
result(result) {
this.setCategories(result.data.Category)
},
fetchPolicy: 'cache-and-network',
},
},
} }
</script> </script>
<style> <style>

View File

@ -1,6 +1,10 @@
{ {
"filter-menu": { "filter-menu": {
"title": "Deine Filterblase" "title": "Deine Filterblase",
"all": "Alle"
},
"filter-posts": {
"header": "Themenkategorien"
}, },
"login": { "login": {
"copy": "Wenn Du bereits ein Konto bei Human Connection hast, melde Dich bitte hier an.", "copy": "Wenn Du bereits ein Konto bei Human Connection hast, melde Dich bitte hier an.",
@ -344,5 +348,4 @@
"infoSelectedNoOfMaxCategories": "{chosen} von {max} Kategorien ausgewählt" "infoSelectedNoOfMaxCategories": "{chosen} von {max} Kategorien ausgewählt"
} }
} }
} }

View File

@ -2,6 +2,10 @@
"filter-menu": { "filter-menu": {
"title": "Your filter bubble" "title": "Your filter bubble"
}, },
"filter-posts": {
"header": "Categories of Content",
"all": "All"
},
"login": { "login": {
"copy": "If you already have a human-connection account, login here.", "copy": "If you already have a human-connection account, login here.",
"login": "Login", "login": "Login",
@ -195,7 +199,6 @@
"more": "show more", "more": "show more",
"less": "show less" "less": "show less"
} }
}, },
"quotes": { "quotes": {
"african": { "african": {