add a layout option to the authors page Cards|Table

This commit is contained in:
Shaun 2024-08-26 14:59:05 +10:00
parent c72eac9987
commit 9246e46423
4 changed files with 113 additions and 6 deletions

View file

@ -98,6 +98,7 @@
<!-- author sort select -->
<controls-sort-select v-if="authors?.length" v-model="settings.authorSortBy" :descending.sync="settings.authorSortDesc" :items="authorSortItems" class="w-36 sm:w-44 md:w-48 h-7.5 ml-1 sm:ml-4" @change="updateAuthorSort" />
<controls-layout-select v-if="authors?.length" v-model="settings.authorPageLayout" :items="layoutSelectItems" class="w-24 sm:w-44 md:w-48 h-7.5 ml-1 sm:ml-4" @change="updateAuthorLayout" />
</template>
<!-- home page -->
<template v-else-if="isHome">
@ -195,6 +196,18 @@ export default {
}
]
},
layoutSelectItems() {
return [
{
text: 'Cards',
value: 'cards'
},
{
text: 'Table',
value: 'table'
}
]
},
authorSortItems() {
return [
{
@ -593,6 +606,9 @@ export default {
updateAuthorSort() {
this.saveSettings()
},
updateAuthorLayout() {
this.saveSettings()
},
saveSettings() {
this.$store.dispatch('user/updateUserSettings', this.settings)
},

View file

@ -0,0 +1,66 @@
<template>
<div ref="wrapper" class="relative" v-click-outside="clickOutside">
<button type="button" class="relative w-full h-full border border-gray-500 hover:border-gray-400 rounded shadow-sm pl-3 pr-3 py-0 text-left focus:outline-none cursor-pointer" aria-haspopup="listbox" aria-expanded="true" aria-labelledby="listbox-label" @click.prevent="showMenu = !showMenu">
<span class="flex items-center justify-between">
<span class="block truncate text-xs" :class="!selectedText ? 'text-gray-300' : ''">{{ selectedText }}</span>
</span>
</button>
<ul v-show="showMenu" class="absolute z-10 mt-1 w-full bg-bg border border-black-200 shadow-lg max-h-80 rounded-md py-1 ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none text-sm" role="listbox" aria-labelledby="listbox-label">
<template v-for="item in items">
<li :key="item.value" class="select-none relative py-2 pr-9 cursor-pointer hover:bg-white/5" :class="item.value === selected ? 'bg-white/5 text-yellow-400' : 'text-gray-200 hover:text-white'" role="option" @click="clickedOption(item.value)">
<div class="flex items-center">
<span class="font-normal ml-3 block truncate">{{ item.text }}</span>
</div>
</li>
</template>
</ul>
</div>
</template>
<script>
export default {
props: {
value: String,
items: {
type: Array,
default: () => []
}
},
data() {
return {
showMenu: false
}
},
computed: {
selected: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
},
selectedText() {
var _selected = this.selected
if (!_selected) return ''
var _sel = this.items.find((i) => i.value === _selected)
if (!_sel) return ''
return _sel.text
}
},
methods: {
clickOutside() {
this.showMenu = false
},
clickedOption(val) {
if (this.selected === val) {
} else {
this.selected = val
}
this.showMenu = false
this.$nextTick(() => this.$emit('change', val))
}
}
}
</script>

View file

@ -2,12 +2,33 @@
<div class="page" :class="streamLibraryItem ? 'streaming' : ''">
<app-book-shelf-toolbar page="authors" is-home :authors="authors" />
<div id="bookshelf" class="w-full h-full p-8e overflow-y-auto" :style="{ fontSize: sizeMultiplier + 'rem' }">
<!-- Cover size widget -->
<widgets-cover-size-widget class="fixed right-4 z-50" :style="{ bottom: streamLibraryItem ? '181px' : '16px' }" />
<div class="flex flex-wrap justify-center">
<template v-for="author in authorsSorted">
<cards-author-card :key="author.id" :author="author" class="p-3e" @edit="editAuthor" />
</template>
<div v-if="authorLayoutType === 'cards'">
<!-- Cover size widget -->
<widgets-cover-size-widget class="fixed right-4 z-50" :style="{ bottom: streamLibraryItem ? '181px' : '16px' }" />
<div class="flex flex-wrap justify-center">
<template v-for="author in authorsSorted">
<cards-author-card :key="author.id" :author="author" class="p-3e" @edit="editAuthor" />
</template>
</div>
</div>
<div v-if="authorLayoutType === 'table'">
<table class="tracksTable max-w-2xl mx-auto">
<tr>
<th class="text-left">{{ $strings.LabelName }}</th>
<th class="text-center w-24">{{ $strings.LabelBooks }}</th>
</tr>
<tr v-for="author in authorsSorted" :key="author.id">
<td>
<nuxt-link :to="`/author/${author.id}`">
<p class="text-sm md:text-base text-gray-100">{{ author.name }}</p>
</nuxt-link>
</td>
<td class="text-center w-24 h-12">
<nuxt-link :to="`/library/${currentLibraryId}/bookshelf?filter=authors.${$encode(author.id)}`" class="hover:underline">{{ author.numBooks }}</nuxt-link>
</td>
</tr>
</table>
</div>
</div>
</div>
@ -53,6 +74,9 @@ export default {
authorSortBy() {
return this.$store.getters['user/getUserSetting']('authorSortBy') || 'name'
},
authorLayoutType() {
return this.$store.getters['user/getUserSetting']('authorPageLayout') || 'cards'
},
authorSortDesc() {
return !!this.$store.getters['user/getUserSetting']('authorSortDesc')
},

View file

@ -1,6 +1,7 @@
export const state = () => ({
user: null,
settings: {
authorPageLayout: 'cards',
orderBy: 'media.metadata.title',
orderDesc: false,
filterBy: 'all',