mirror of
https://github.com/gotson/komga.git
synced 2026-05-08 12:35:30 +02:00
series page scaffolding
This commit is contained in:
parent
deb49b2242
commit
0b9aa753c5
2 changed files with 125 additions and 4 deletions
|
|
@ -1,10 +1,106 @@
|
|||
<template>
|
||||
SERIES
|
||||
<EmptyStateConstruction />
|
||||
<v-app-bar>
|
||||
<v-spacer />
|
||||
|
||||
<PageSizeSelector
|
||||
v-model="appStore.browsingPageSize"
|
||||
allow-unpaged
|
||||
:sizes="[1, 10, 20]"
|
||||
/>
|
||||
|
||||
<PresentationSelector
|
||||
v-model="presentationMode"
|
||||
:modes="['grid', 'list']"
|
||||
/>
|
||||
</v-app-bar>
|
||||
|
||||
<template v-if="series">
|
||||
<v-data-iterator
|
||||
v-model="selectedItems"
|
||||
return-object
|
||||
:items="series.content"
|
||||
:items-per-page="itemsPerPage"
|
||||
:page="page1"
|
||||
show-select
|
||||
>
|
||||
<template #default="{ items, toggleSelect, isSelected }">
|
||||
<v-container
|
||||
v-if="presentationMode === 'grid'"
|
||||
fluid
|
||||
>
|
||||
<v-row>
|
||||
<v-col
|
||||
v-for="item in items"
|
||||
:key="item.raw.id"
|
||||
cols="2"
|
||||
>
|
||||
<ItemCardSeries
|
||||
:series="item.raw"
|
||||
:selected="isSelected(item)"
|
||||
:pre-select="preSelect"
|
||||
@selection="toggleSelect(item)"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
|
||||
<v-list v-if="presentationMode === 'list'">
|
||||
<v-list-item
|
||||
v-for="item in items"
|
||||
:key="item.raw.id"
|
||||
:title="item.raw.metadata.title"
|
||||
:base-color="isSelected(item) ? 'red' : 'blue'"
|
||||
@click="toggleSelect(item)"
|
||||
/>
|
||||
</v-list>
|
||||
</template>
|
||||
</v-data-iterator>
|
||||
|
||||
<v-pagination
|
||||
v-model="page1"
|
||||
:length="pageCount"
|
||||
></v-pagination>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
//
|
||||
import { useQuery } from '@pinia/colada'
|
||||
import { seriesListQuery } from '@/colada/series'
|
||||
import type { components } from '@/generated/openapi/komga'
|
||||
import { PageRequest } from '@/types/PageRequest'
|
||||
import { useGetLibrariesById } from '@/composables/libraries'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { useItemsPerPage, usePagination } from '@/composables/pagination'
|
||||
import { useSearchConditionLibraries } from '@/composables/search'
|
||||
|
||||
const route = useRoute('/libraries/[id]/series')
|
||||
const libraryId = route.params.id
|
||||
const { libraries } = useGetLibrariesById(libraryId)
|
||||
const { librariesCondition } = useSearchConditionLibraries(libraries)
|
||||
|
||||
const appStore = useAppStore()
|
||||
const presentationMode = appStore.getPresentationMode(`${libraryId}_series`, 'grid')
|
||||
|
||||
const { itemsPerPage } = useItemsPerPage(appStore.browsingPageSize)
|
||||
const { page0, page1, pageCount } = usePagination()
|
||||
|
||||
const selectedItems = ref<components['schemas']['SeriesDto'][]>([])
|
||||
const preSelect = computed(() => selectedItems.value.length > 0)
|
||||
|
||||
const { data: series } = useQuery(seriesListQuery, () => {
|
||||
const search: components['schemas']['SeriesSearch'] = {
|
||||
condition: librariesCondition.value as components['schemas']['AnyOfSeries'],
|
||||
}
|
||||
|
||||
return {
|
||||
search: search,
|
||||
pageRequest: PageRequest.FromPageSize(appStore.browsingPageSize, page0.value),
|
||||
}
|
||||
})
|
||||
|
||||
watch(series, (newSeries) => {
|
||||
if (newSeries) pageCount.value = newSeries.totalPages ?? 0
|
||||
})
|
||||
</script>
|
||||
|
||||
<route lang="yaml">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Utilities
|
||||
import { defineStore } from 'pinia'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import type { PresentationMode } from '@/types/libraries'
|
||||
import type { PageSize } from '@/types/page'
|
||||
|
||||
export const useAppStore = defineStore('app', {
|
||||
state: () => ({
|
||||
|
|
@ -9,12 +11,35 @@ export const useAppStore = defineStore('app', {
|
|||
theme: 'system',
|
||||
rememberMe: false,
|
||||
importBooksPath: '',
|
||||
browsingPageSize: 20 as PageSize,
|
||||
/**
|
||||
* Store the presentation mode per view.
|
||||
* Use the getter to ensure a default value is always set.
|
||||
*/
|
||||
presentationMode: {} as Record<string, PresentationMode>,
|
||||
// transient
|
||||
reorderLibraries: false,
|
||||
}),
|
||||
getters: {
|
||||
getPresentationMode: (state) => (key: string, defaultValue: PresentationMode) => {
|
||||
return computed({
|
||||
get: () => state.presentationMode[key] ?? (state.presentationMode[key] = defaultValue),
|
||||
set: (value) => {
|
||||
state.presentationMode[key] = value
|
||||
},
|
||||
})
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
key: 'komga.nextui.app',
|
||||
// explicitly state which keys are stored
|
||||
pick: ['drawer', 'theme', 'rememberMe', 'importBooksPath'],
|
||||
pick: [
|
||||
'drawer',
|
||||
'theme',
|
||||
'rememberMe',
|
||||
'importBooksPath',
|
||||
'browsingPageSize',
|
||||
'presentationMode',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue