feat(webui): display library navigation within toolbar

use bottom navigation only for XS screens

closes #234
This commit is contained in:
Gauthier Roebroeck 2021-04-27 21:32:26 +08:00
parent 4c6b3f5e5e
commit a6252ff2e8
5 changed files with 129 additions and 57 deletions

View file

@ -1,35 +1,78 @@
<template> <template>
<v-bottom-navigation <div>
grow color="primary" <v-bottom-navigation
:fixed="$vuetify.breakpoint.name === 'xs'" v-if="show && bottomNavigation"
> grow color="primary"
<v-btn :to="{name: 'browse-libraries', params: {libraryId: libraryId}}"> :fixed="$vuetify.breakpoint.name === 'xs'"
<span>{{ $t('library_navigation.browse') }}</span>
<v-icon>mdi-bookshelf</v-icon>
</v-btn>
<v-btn :to="{name: 'recommended-libraries', params: {libraryId: libraryId}}">
<span>{{ $t('library_navigation.recommended') }}</span>
<v-icon>mdi-view-dashboard</v-icon>
</v-btn>
<v-btn
v-if="collectionsCount > 0"
:to="{name: 'browse-collections', params: {libraryId: libraryId}}"
> >
<span>{{ $t('library_navigation.collections') }}</span> <v-btn v-if="showRecommended"
<v-icon>mdi-layers-triple</v-icon> :to="{name: 'recommended-libraries', params: {libraryId: libraryId}}"
</v-btn> >
<span>{{ $t('library_navigation.recommended') }}</span>
<v-icon>mdi-star</v-icon>
</v-btn>
<v-btn <v-btn :to="{name: 'browse-libraries', params: {libraryId: libraryId}}">
v-if="readListsCount > 0" <span>{{ $t('library_navigation.browse') }}</span>
:to="{name: 'browse-readlists', params: {libraryId: libraryId}}" <v-icon>mdi-bookshelf</v-icon>
</v-btn>
<v-btn
v-if="collectionsCount > 0"
:to="{name: 'browse-collections', params: {libraryId: libraryId}}"
>
<span>{{ $t('library_navigation.collections') }}</span>
<v-icon>mdi-layers-triple</v-icon>
</v-btn>
<v-btn
v-if="readListsCount > 0"
:to="{name: 'browse-readlists', params: {libraryId: libraryId}}"
>
<span>{{ $t('library_navigation.readlists') }}</span>
<v-icon>mdi-book-multiple</v-icon>
</v-btn>
</v-bottom-navigation>
<template
v-if="show && !bottomNavigation"
> >
<span>{{ $t('library_navigation.readlists') }}</span> <v-btn v-if="showRecommended"
<v-icon>mdi-book-multiple</v-icon> :to="{name: 'recommended-libraries', params: {libraryId: libraryId}}"
</v-btn> text
class="mx-1"
>
{{ $t('library_navigation.recommended') }}
</v-btn>
</v-bottom-navigation> <v-btn :to="{name: 'browse-libraries', params: {libraryId: libraryId}}"
text
class="mx-1"
>
{{ $t('library_navigation.browse') }}
</v-btn>
<v-btn
v-if="collectionsCount > 0"
:to="{name: 'browse-collections', params: {libraryId: libraryId}}"
text
class="mx-1"
>
{{ $t('library_navigation.collections') }}
</v-btn>
<v-btn
v-if="readListsCount > 0"
:to="{name: 'browse-readlists', params: {libraryId: libraryId}}"
text
class="mx-1"
>
{{ $t('library_navigation.readlists') }}
</v-btn>
</template>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -50,31 +93,43 @@ export default Vue.extend({
type: String, type: String,
required: true, required: true,
}, },
bottomNavigation: {
type: Boolean,
default: false,
},
}, },
watch: { watch: {
libraryId: { libraryId: {
handler (val) { handler(val) {
this.loadCounts(val) this.loadCounts(val)
}, },
immediate: true, immediate: true,
}, },
}, },
created () { created() {
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCounts) this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCounts)
this.$eventHub.$on(READLIST_CHANGED, this.reloadCounts) this.$eventHub.$on(READLIST_CHANGED, this.reloadCounts)
}, },
beforeDestroy () { beforeDestroy() {
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCounts) this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCounts)
this.$eventHub.$off(READLIST_CHANGED, this.reloadCounts) this.$eventHub.$off(READLIST_CHANGED, this.reloadCounts)
}, },
computed: {
showRecommended(): boolean {
return this.libraryId !== LIBRARIES_ALL
},
show(): boolean {
return this.collectionsCount > 0 || this.readListsCount > 0 || this.showRecommended
},
},
methods: { methods: {
reloadCounts () { reloadCounts() {
this.loadCounts(this.libraryId) this.loadCounts(this.libraryId)
}, },
async loadCounts (libraryId: string) { async loadCounts(libraryId: string) {
const lib = libraryId !== LIBRARIES_ALL ? [libraryId] : undefined const lib = libraryId !== LIBRARIES_ALL ? [libraryId] : undefined
this.collectionsCount = (await this.$komgaCollections.getCollections(lib, { size: 1 })).totalElements this.collectionsCount = (await this.$komgaCollections.getCollections(lib, {size: 1})).totalElements
this.readListsCount = (await this.$komgaReadLists.getReadLists(lib, { size: 1 })).totalElements this.readListsCount = (await this.$komgaReadLists.getReadLists(lib, {size: 1})).totalElements
}, },
}, },
}) })

View file

@ -14,10 +14,14 @@
<v-spacer/> <v-spacer/>
<library-navigation v-if="$vuetify.breakpoint.name !== 'xs'" :libraryId="libraryId"/>
<v-spacer/>
<page-size-select v-model="pageSize"/> <page-size-select v-model="pageSize"/>
</toolbar-sticky> </toolbar-sticky>
<library-navigation :libraryId="libraryId"/> <library-navigation v-if="$vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
<v-container fluid> <v-container fluid>
<v-pagination <v-pagination
@ -82,12 +86,12 @@ export default Vue.extend({
default: LIBRARIES_ALL, default: LIBRARIES_ALL,
}, },
}, },
created () { created() {
this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections) this.$eventHub.$on(COLLECTION_CHANGED, this.reloadCollections)
this.$eventHub.$on(COLLECTION_DELETED, this.reloadCollections) this.$eventHub.$on(COLLECTION_DELETED, this.reloadCollections)
this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary) this.$eventHub.$on(LIBRARY_CHANGED, this.reloadLibrary)
}, },
beforeDestroy () { beforeDestroy() {
this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections) this.$eventHub.$off(COLLECTION_CHANGED, this.reloadCollections)
this.$eventHub.$off(COLLECTION_DELETED, this.reloadCollections) this.$eventHub.$off(COLLECTION_DELETED, this.reloadCollections)
this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary) this.$eventHub.$off(LIBRARY_CHANGED, this.reloadLibrary)
@ -103,7 +107,7 @@ export default Vue.extend({
this.setWatches() this.setWatches()
}, },
beforeRouteUpdate (to, from, next) { beforeRouteUpdate(to, from, next) {
if (to.params.libraryId !== from.params.libraryId) { if (to.params.libraryId !== from.params.libraryId) {
// reset // reset
this.page = 1 this.page = 1
@ -117,10 +121,10 @@ export default Vue.extend({
next() next()
}, },
computed: { computed: {
isAdmin (): boolean { isAdmin(): boolean {
return this.$store.getters.meAdmin return this.$store.getters.meAdmin
}, },
paginationVisible (): number { paginationVisible(): number {
switch (this.$vuetify.breakpoint.name) { switch (this.$vuetify.breakpoint.name) {
case 'xs': case 'xs':
return 5 return 5
@ -135,7 +139,7 @@ export default Vue.extend({
}, },
}, },
methods: { methods: {
setWatches () { setWatches() {
this.pageSizeUnwatch = this.$watch('pageSize', (val) => { this.pageSizeUnwatch = this.$watch('pageSize', (val) => {
this.$store.commit('setBrowsingPageSize', val) this.$store.commit('setBrowsingPageSize', val)
this.updateRouteAndReload() this.updateRouteAndReload()
@ -146,11 +150,11 @@ export default Vue.extend({
this.loadPage(this.libraryId, val) this.loadPage(this.libraryId, val)
}) })
}, },
unsetWatches () { unsetWatches() {
this.pageUnwatch() this.pageUnwatch()
this.pageSizeUnwatch() this.pageSizeUnwatch()
}, },
updateRouteAndReload () { updateRouteAndReload() {
this.unsetWatches() this.unsetWatches()
this.page = 1 this.page = 1
@ -160,10 +164,10 @@ export default Vue.extend({
this.setWatches() this.setWatches()
}, },
updateRoute () { updateRoute() {
this.$router.replace({ this.$router.replace({
name: this.$route.name, name: this.$route.name,
params: { libraryId: this.$route.params.libraryId }, params: {libraryId: this.$route.params.libraryId},
query: { query: {
page: `${this.page}`, page: `${this.page}`,
pageSize: `${this.pageSize}`, pageSize: `${this.pageSize}`,
@ -171,23 +175,23 @@ export default Vue.extend({
} as Location).catch((_: any) => { } as Location).catch((_: any) => {
}) })
}, },
reloadCollections () { reloadCollections() {
this.loadLibrary(this.libraryId) this.loadLibrary(this.libraryId)
}, },
reloadLibrary (event: EventLibraryChanged) { reloadLibrary(event: EventLibraryChanged) {
if (event.id === this.libraryId) { if (event.id === this.libraryId) {
this.loadLibrary(this.libraryId) this.loadLibrary(this.libraryId)
} }
}, },
async loadLibrary (libraryId: string) { async loadLibrary(libraryId: string) {
this.library = this.getLibraryLazy(libraryId) this.library = this.getLibraryLazy(libraryId)
await this.loadPage(libraryId, this.page) await this.loadPage(libraryId, this.page)
if (this.totalElements === 0) { if (this.totalElements === 0) {
await this.$router.push({ name: 'browse-libraries', params: { libraryId: libraryId.toString() } }) await this.$router.push({name: 'browse-libraries', params: {libraryId: libraryId.toString()}})
} }
}, },
async loadPage (libraryId: string, page: number) { async loadPage(libraryId: string, page: number) {
const pageRequest = { const pageRequest = {
page: page - 1, page: page - 1,
size: this.pageSize, size: this.pageSize,
@ -200,14 +204,14 @@ export default Vue.extend({
this.totalElements = collectionsPage.totalElements this.totalElements = collectionsPage.totalElements
this.collections = collectionsPage.content this.collections = collectionsPage.content
}, },
getLibraryLazy (libraryId: string): LibraryDto | undefined { getLibraryLazy(libraryId: string): LibraryDto | undefined {
if (libraryId !== LIBRARIES_ALL) { if (libraryId !== LIBRARIES_ALL) {
return this.$store.getters.getLibraryById(libraryId) return this.$store.getters.getLibraryById(libraryId)
} else { } else {
return undefined return undefined
} }
}, },
editSingleCollection (collection: CollectionDto) { editSingleCollection(collection: CollectionDto) {
this.$store.dispatch('dialogEditCollection', collection) this.$store.dispatch('dialogEditCollection', collection)
}, },
}, },

View file

@ -14,6 +14,10 @@
<v-spacer/> <v-spacer/>
<library-navigation v-if="$vuetify.breakpoint.name !== 'xs'" :libraryId="libraryId"/>
<v-spacer/>
<page-size-select v-model="pageSize"/> <page-size-select v-model="pageSize"/>
<v-btn icon @click="drawer = !drawer"> <v-btn icon @click="drawer = !drawer">
@ -30,7 +34,7 @@
@edit="editMultipleSeries" @edit="editMultipleSeries"
/> />
<library-navigation :libraryId="libraryId"/> <library-navigation v-if="$vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
<filter-drawer v-model="drawer"> <filter-drawer v-model="drawer">
<template v-slot:default> <template v-slot:default>

View file

@ -14,10 +14,14 @@
<v-spacer/> <v-spacer/>
<library-navigation v-if="$vuetify.breakpoint.name !== 'xs'" :libraryId="libraryId"/>
<v-spacer/>
<page-size-select v-model="pageSize"/> <page-size-select v-model="pageSize"/>
</toolbar-sticky> </toolbar-sticky>
<library-navigation :libraryId="libraryId"/> <library-navigation v-if="$vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
<v-container fluid> <v-container fluid>
<v-pagination <v-pagination

View file

@ -9,10 +9,15 @@
<span>{{ library ? library.name : $t('common.all_libraries') }}</span> <span>{{ library ? library.name : $t('common.all_libraries') }}</span>
</v-toolbar-title> </v-toolbar-title>
</toolbar-sticky> <v-spacer/>
<library-navigation :libraryId="libraryId"/> <library-navigation v-if="showLibraryBar && $vuetify.breakpoint.name !== 'xs'" :libraryId="libraryId"/>
</div>
<v-spacer/>
</toolbar-sticky>
<library-navigation v-if="showLibraryBar && $vuetify.breakpoint.name === 'xs'" :libraryId="libraryId" bottom-navigation/>
<series-multi-select-bar <series-multi-select-bar
v-model="selectedSeries" v-model="selectedSeries"