mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
fix(client): show authors on collapsed series rows in table view
The table rendered a dash in every column of a collapsed series row, including Authors, although the row already carries the first volume's authors and the grid and list views show them. Render them as the same read-only author chips book rows use. Closes #1645
This commit is contained in:
@@ -878,7 +878,12 @@ defineExpose({
|
||||
@click="focusTableCell(vItem.index, colIdx, $event, rowBook(vItem.index).id, col.id)"
|
||||
>
|
||||
<template v-if="rowBook(vItem.index).collapsedSeries">
|
||||
<BookTableCollapsedSeriesCell :book="rowBook(vItem.index)" :col-id="col.id" @open-series="handleOpenSeries(rowBook(vItem.index))" />
|
||||
<BookTableCollapsedSeriesCell
|
||||
:book="rowBook(vItem.index)"
|
||||
:col-id="col.id"
|
||||
:link-fn="getChipsLinkFn(col.id)"
|
||||
@open-series="handleOpenSeries(rowBook(vItem.index))"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<BookTableCellDispatcher
|
||||
|
||||
+10
@@ -68,6 +68,7 @@ function makeBook(id: number, overrides: Partial<BookCard> = {}): BookCard {
|
||||
const collapsedSeriesBook = makeBook(1, {
|
||||
seriesId: 7,
|
||||
seriesName: 'Discworld',
|
||||
authors: ['Terry Pratchett'],
|
||||
collapsedSeries: { bookCount: 3, readCount: 0, coverBookIds: [1], seriesLatestAddedAt: null },
|
||||
})
|
||||
const plainBook = makeBook(2)
|
||||
@@ -139,4 +140,13 @@ describe('VirtualBookTable collapsed series rows', () => {
|
||||
|
||||
expect(wrapper.emitted('select')?.[0]?.[0]).toBe(plainBook.id)
|
||||
})
|
||||
|
||||
it('gives a collapsed series row the author link used by book rows', () => {
|
||||
const wrapper = mountTable()
|
||||
const authorsCell = wrapper.findAllComponents({ name: 'BookTableCollapsedSeriesCell' }).find((cell) => cell.props('colId') === 'authors')
|
||||
const linkFn = authorsCell?.props('linkFn') as ((chip: string) => string | null) | undefined
|
||||
|
||||
expect(authorsCell?.props('book')).toMatchObject({ authors: ['Terry Pratchett'] })
|
||||
expect(linkFn?.('Terry Pratchett')).toBe('/authors?q=Terry%20Pratchett')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -4,12 +4,14 @@ import { useI18n } from 'vue-i18n'
|
||||
import { ChevronRight, LibraryBig } from '@lucide/vue'
|
||||
import { FORMAT_TO_GROUP, type BookCard } from '@bookorbit/types'
|
||||
import BookCoverSurface from '../BookCoverSurface.vue'
|
||||
import BookTableChipsCell from './BookTableChipsCell.vue'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import { useCoverVersions } from '@/features/book/composables/useCoverVersions'
|
||||
|
||||
const props = defineProps<{
|
||||
book: BookCard
|
||||
colId: string
|
||||
linkFn?: (chip: string) => string | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -95,6 +97,8 @@ function handleOpenSeries() {
|
||||
>
|
||||
</div>
|
||||
|
||||
<BookTableChipsCell v-else-if="colId === 'authors'" :value="book.authors" :is-active="false" is-read-only :link-fn="linkFn" />
|
||||
|
||||
<div v-else-if="colId === 'actions'" class="flex h-full w-6 items-center justify-center">
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
|
||||
+29
-4
@@ -1,4 +1,4 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { mount, RouterLinkStub } from '@vue/test-utils'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import type { BookCard } from '@bookorbit/types'
|
||||
import BookTableCollapsedSeriesCell from '../BookTableCollapsedSeriesCell.vue'
|
||||
@@ -12,7 +12,7 @@ vi.mock('@/features/book/composables/useCoverVersions', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
function makeBook(format: string | null): BookCard {
|
||||
function makeBook(format: string | null, overrides: Partial<BookCard> = {}): BookCard {
|
||||
return {
|
||||
id: 1,
|
||||
status: 'present',
|
||||
@@ -50,6 +50,7 @@ function makeBook(format: string | null): BookCard {
|
||||
coverUpdatedAtByBookId: { 10: '2024-01-01T00:00:00.000Z', 11: '2024-02-01T00:00:00.000Z' },
|
||||
seriesLatestAddedAt: null,
|
||||
},
|
||||
...overrides,
|
||||
} as BookCard
|
||||
}
|
||||
|
||||
@@ -59,11 +60,16 @@ const CoverSurfaceStub = {
|
||||
template: '<div data-testid="surface" :data-comic="isComic"><slot /></div>',
|
||||
}
|
||||
|
||||
function mountCell(format: string | null, colId = 'cover') {
|
||||
function mountCell(
|
||||
format: string | null,
|
||||
colId = 'cover',
|
||||
options: { overrides?: Partial<BookCard>; linkFn?: (chip: string) => string | null } = {},
|
||||
) {
|
||||
return mount(BookTableCollapsedSeriesCell, {
|
||||
props: { book: makeBook(format), colId },
|
||||
props: { book: makeBook(format, options.overrides), colId, linkFn: options.linkFn },
|
||||
global: {
|
||||
stubs: {
|
||||
RouterLink: RouterLinkStub,
|
||||
BookCoverSurface: CoverSurfaceStub,
|
||||
Tooltip: { template: '<div><slot /></div>' },
|
||||
TooltipTrigger: { template: '<div><slot /></div>' },
|
||||
@@ -115,4 +121,23 @@ describe('BookTableCollapsedSeriesCell comic flag', () => {
|
||||
await button.trigger('click')
|
||||
expect(wrapper.emitted('open-series')).toEqual([[]])
|
||||
})
|
||||
|
||||
it('links the series authors in the authors column', () => {
|
||||
const wrapper = mountCell('epub', 'authors', {
|
||||
overrides: { authors: ['Terry Pratchett', 'Neil Gaiman', 'Stephen Baxter'] },
|
||||
linkFn: (name) => `/authors?q=${encodeURIComponent(name)}`,
|
||||
})
|
||||
const links = wrapper.findAllComponents(RouterLinkStub)
|
||||
|
||||
expect(links.map((link) => link.text())).toEqual(['Terry Pratchett', 'Neil Gaiman'])
|
||||
expect(links.map((link) => link.props('to'))).toEqual(['/authors?q=Terry%20Pratchett', '/authors?q=Neil%20Gaiman'])
|
||||
expect(wrapper.text()).toContain('+1')
|
||||
})
|
||||
|
||||
it('shows a dash in the authors column when the series has no authors', () => {
|
||||
const wrapper = mountCell('epub', 'authors', { linkFn: (name) => `/authors?q=${name}` })
|
||||
|
||||
expect(wrapper.findAllComponents(RouterLinkStub)).toHaveLength(0)
|
||||
expect(wrapper.text()).toBe('-')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user