mirror of
https://github.com/gotson/komga.git
synced 2026-04-21 22:40:48 +02:00
basic selection
This commit is contained in:
parent
4df5b825e5
commit
2f99782a8e
8 changed files with 179 additions and 1 deletions
2
next-ui/src/components.d.ts
vendored
2
next-ui/src/components.d.ts
vendored
|
|
@ -50,6 +50,7 @@ declare module 'vue' {
|
|||
ImportReadlistTable: typeof import('./components/import/readlist/Table.vue')['default']
|
||||
ItemCard: typeof import('./components/item/card/ItemCard.vue')['default']
|
||||
LayoutAppBar: typeof import('./components/layout/app/Bar.vue')['default']
|
||||
LayoutAppBarHolder: typeof import('./components/layout/app/BarHolder.vue')['default']
|
||||
LayoutAppDrawer: typeof import('./components/layout/app/drawer/Drawer.vue')['default']
|
||||
LayoutAppDrawerFooter: typeof import('./components/layout/app/drawer/Footer.vue')['default']
|
||||
LayoutAppDrawerMenu: typeof import('./components/layout/app/drawer/menu/Menu.vue')['default']
|
||||
|
|
@ -82,6 +83,7 @@ declare module 'vue' {
|
|||
RemoteFileList: typeof import('./components/RemoteFileList.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SelectionBar: typeof import('./components/selection/Bar.vue')['default']
|
||||
SeriesCard: typeof import('./components/series/card/SeriesCard.vue')['default']
|
||||
SeriesDeletionWarning: typeof import('./components/series/DeletionWarning.vue')['default']
|
||||
SeriesFormEditMetadata: typeof import('./components/series/form/EditMetadata.vue')['default']
|
||||
|
|
|
|||
30
next-ui/src/components/layout/app/Bar.stories.ts
Normal file
30
next-ui/src/components/layout/app/Bar.stories.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
|
||||
import Bar from './Bar.vue'
|
||||
|
||||
const meta = {
|
||||
component: Bar,
|
||||
render: (args: object) => ({
|
||||
components: { Bar },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: '<Bar v-bind="args"/>',
|
||||
}),
|
||||
parameters: {
|
||||
// More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
|
||||
docs: {
|
||||
description: {
|
||||
component: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
args: {},
|
||||
} satisfies Meta<typeof Bar>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {},
|
||||
}
|
||||
38
next-ui/src/components/layout/app/BarHolder.stories.ts
Normal file
38
next-ui/src/components/layout/app/BarHolder.stories.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
|
||||
import BarHolder from './BarHolder.vue'
|
||||
import { useSelectionStore } from '@/stores/selection'
|
||||
|
||||
const meta = {
|
||||
component: BarHolder,
|
||||
render: (args: object) => ({
|
||||
components: { BarHolder },
|
||||
setup() {
|
||||
const selectionStore = useSelectionStore()
|
||||
return { args, selectionStore }
|
||||
},
|
||||
template:
|
||||
'<BarHolder v-bind="args"/><v-btn @click="selectionStore.selection.push(`a`)">Add item</v-btn>',
|
||||
}),
|
||||
parameters: {
|
||||
// More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'Holder to display the app bar, or the selection bar on top when items are selected.',
|
||||
},
|
||||
},
|
||||
},
|
||||
args: {},
|
||||
} satisfies Meta<typeof BarHolder>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {},
|
||||
play: () => {
|
||||
const selectionStore = useSelectionStore()
|
||||
selectionStore.selection = ['a', 'b']
|
||||
},
|
||||
}
|
||||
12
next-ui/src/components/layout/app/BarHolder.vue
Normal file
12
next-ui/src/components/layout/app/BarHolder.vue
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<template>
|
||||
<LayoutAppBar v-if="selectionStore.isEmpty" />
|
||||
<v-fade-transition>
|
||||
<SelectionBar v-if="!selectionStore.isEmpty" />
|
||||
</v-fade-transition>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSelectionStore } from '@/stores/selection'
|
||||
|
||||
const selectionStore = useSelectionStore()
|
||||
</script>
|
||||
35
next-ui/src/components/selection/Bar.stories.ts
Normal file
35
next-ui/src/components/selection/Bar.stories.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
||||
|
||||
import Bar from './Bar.vue'
|
||||
import { useSelectionStore } from '@/stores/selection'
|
||||
|
||||
const meta = {
|
||||
component: Bar,
|
||||
render: (args: object) => ({
|
||||
components: { Bar },
|
||||
setup() {
|
||||
return { args }
|
||||
},
|
||||
template: '<Bar v-bind="args"/>',
|
||||
}),
|
||||
parameters: {
|
||||
// More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
|
||||
docs: {
|
||||
description: {
|
||||
component: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
args: {},
|
||||
} satisfies Meta<typeof Bar>
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {},
|
||||
play: () => {
|
||||
const selectionStore = useSelectionStore()
|
||||
selectionStore.selection = ['a', 'b']
|
||||
},
|
||||
}
|
||||
38
next-ui/src/components/selection/Bar.vue
Normal file
38
next-ui/src/components/selection/Bar.vue
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<v-app-bar
|
||||
elevation="2"
|
||||
color="surface-light"
|
||||
>
|
||||
<template #prepend>
|
||||
<v-app-bar-nav-icon
|
||||
icon="i-mdi:close"
|
||||
@click="selectionStore.clear()"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<v-app-bar-title>
|
||||
{{
|
||||
$formatMessage(
|
||||
{
|
||||
description: 'Selection bar: count of items',
|
||||
defaultMessage: '{count} selected',
|
||||
id: 'lqyIjk',
|
||||
},
|
||||
{
|
||||
count: selectionStore.count,
|
||||
},
|
||||
)
|
||||
}}
|
||||
</v-app-bar-title>
|
||||
</v-app-bar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSelectionStore } from '@/stores/selection'
|
||||
|
||||
const selectionStore = useSelectionStore()
|
||||
</script>
|
||||
|
||||
<script lang="ts"></script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -74,6 +74,7 @@ import { useAppStore } from '@/stores/app'
|
|||
import { useItemsPerPage, usePagination } from '@/composables/pagination'
|
||||
import { useSearchConditionLibraries } from '@/composables/search'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useSelectionStore } from '@/stores/selection'
|
||||
|
||||
const route = useRoute('/libraries/[id]/series')
|
||||
const libraryId = route.params.id
|
||||
|
|
@ -87,7 +88,8 @@ const presentationMode = appStore.getPresentationMode(`${libraryId}_series`, 'gr
|
|||
const { itemsPerPage } = useItemsPerPage(browsingPageSize)
|
||||
const { page0, page1, pageCount } = usePagination()
|
||||
|
||||
const selectedItems = ref<components['schemas']['SeriesDto'][]>([])
|
||||
const selectionStore = useSelectionStore()
|
||||
const { selection: selectedItems } = storeToRefs(selectionStore)
|
||||
const preSelect = computed(() => selectedItems.value.length > 0)
|
||||
|
||||
const { data: series } = useQuery(seriesListQuery, () => {
|
||||
|
|
|
|||
21
next-ui/src/stores/selection.ts
Normal file
21
next-ui/src/stores/selection.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useSelectionStore = defineStore('selection', () => {
|
||||
const route = useRoute()
|
||||
|
||||
const selection = ref<unknown[]>([])
|
||||
|
||||
watch(
|
||||
() => route?.path,
|
||||
() => {
|
||||
selection.value = []
|
||||
},
|
||||
)
|
||||
|
||||
const isEmpty = computed(() => selection.value.length === 0)
|
||||
const count = computed(() => selection.value.length)
|
||||
|
||||
const clear = () => (selection.value = [])
|
||||
|
||||
return { selection, count, isEmpty, clear }
|
||||
})
|
||||
Loading…
Reference in a new issue