diff --git a/next-ui/package-lock.json b/next-ui/package-lock.json index 62128fd5..25c4113e 100644 --- a/next-ui/package-lock.json +++ b/next-ui/package-lock.json @@ -12,6 +12,7 @@ "@pinia/colada": "^0.21.1", "@pinia/colada-plugin-auto-refetch": "^0.2.4", "@pinia/colada-plugin-delay": "^0.1.4", + "@vueuse/components": "^14.1.0", "@vueuse/core": "^14.1.0", "@vueuse/router": "^14.1.0", "core-js": "^3.47.0", @@ -4427,6 +4428,19 @@ "vuetify": "^3.0.0" } }, + "node_modules/@vueuse/components": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-14.1.0.tgz", + "integrity": "sha512-SDRJUAv3H7/PMh+KkYpq0d5KMzpKOfqx4qcV4xyN4mZOLPw8NkiWu+yDcfXwI8h1uCqhRNz2cdeaLa+IuaehFw==", + "license": "MIT", + "dependencies": { + "@vueuse/core": "14.1.0", + "@vueuse/shared": "14.1.0" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, "node_modules/@vueuse/core": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.1.0.tgz", diff --git a/next-ui/package.json b/next-ui/package.json index 9ca0c04a..c76ef6ab 100644 --- a/next-ui/package.json +++ b/next-ui/package.json @@ -33,6 +33,7 @@ "@pinia/colada": "^0.21.1", "@pinia/colada-plugin-auto-refetch": "^0.2.4", "@pinia/colada-plugin-delay": "^0.1.4", + "@vueuse/components": "^14.1.0", "@vueuse/core": "^14.1.0", "@vueuse/router": "^14.1.0", "core-js": "^3.47.0", diff --git a/next-ui/src/colada/series.ts b/next-ui/src/colada/series.ts index f9e499bf..eb297bf5 100644 --- a/next-ui/src/colada/series.ts +++ b/next-ui/src/colada/series.ts @@ -1,7 +1,8 @@ -import { defineQueryOptions } from '@pinia/colada' +import { defineMutation, defineQueryOptions, useMutation } from '@pinia/colada' import { komgaClient } from '@/api/komga-client' import type { components } from '@/generated/openapi/komga' import type { PageRequest } from '@/types/PageRequest' +import { seriesMetadataToDto } from '@/functions/series' export const QUERY_KEYS_SERIES = { root: ['series'] as const, @@ -16,7 +17,7 @@ export const seriesListQuery = defineQueryOptions( pageRequest, }: { search: components['schemas']['SeriesSearch'] - pause: boolean + pause?: boolean pageRequest?: PageRequest }) => ({ key: QUERY_KEYS_SERIES.bySearch({ search: search, pageRequest: pageRequest }), @@ -51,3 +52,93 @@ export const seriesDetailQuery = defineQueryOptions(({ seriesId }: { seriesId: s // unwrap the openapi-fetch structure on success .then((res) => res.data), })) + +export const useRefreshMetadataSeries = defineMutation(() => + useMutation({ + mutation: (seriesId: string) => + komgaClient.POST('/api/v1/series/{seriesId}/metadata/refresh', { + params: { + path: { + seriesId: seriesId, + }, + }, + }), + }), +) + +export const useAnalyzeSeries = defineMutation(() => + useMutation({ + mutation: (seriesId: string) => + komgaClient.POST('/api/v1/series/{seriesId}/analyze', { + params: { + path: { + seriesId: seriesId, + }, + }, + }), + }), +) + +export const useDeleteSeries = defineMutation(() => + useMutation({ + mutation: (seriesId: string) => + komgaClient.DELETE('/api/v1/series/{seriesId}/file', { + params: { + path: { + seriesId: seriesId, + }, + }, + }), + }), +) + +export const useMarkSeriesRead = defineMutation(() => + useMutation({ + mutation: (seriesId: string) => + komgaClient.POST('/api/v1/series/{seriesId}/read-progress', { + params: { + path: { + seriesId: seriesId, + }, + }, + }), + }), +) + +export const useMarkSeriesUnread = defineMutation(() => + useMutation({ + mutation: (seriesId: string) => + komgaClient.DELETE('/api/v1/series/{seriesId}/read-progress', { + params: { + path: { + seriesId: seriesId, + }, + }, + }), + }), +) + +export const useUpdateSeriesMetadata = defineMutation(() => { + // const queryCache = useQueryCache() + return useMutation({ + mutation: ({ + seriesId, + metadata, + }: { + seriesId: string + metadata: components['schemas']['SeriesMetadataDto'] + }) => + komgaClient.PATCH('/api/v1/series/{seriesId}/metadata', { + params: { + path: { + seriesId: seriesId, + }, + }, + body: seriesMetadataToDto(metadata), + }), + onSuccess: () => { + //TODO: check how to invalidate cache + // void queryCache.invalidateQueries({ key: QUERY_KEYS_LIBRARIES.root }) + }, + }) +}) diff --git a/next-ui/src/components.d.ts b/next-ui/src/components.d.ts index d97cb483..ec24c397 100644 --- a/next-ui/src/components.d.ts +++ b/next-ui/src/components.d.ts @@ -42,8 +42,8 @@ declare module 'vue' { ImportBooksDirectorySelection: typeof import('./components/import/books/DirectorySelection.vue')['default'] ImportBooksTransientBooksTable: typeof import('./components/import/books/TransientBooksTable.vue')['default'] ImportReadlistTable: typeof import('./components/import/readlist/Table.vue')['default'] - ItemCard: typeof import('./components/item/Card/ItemCard.vue')['default'] - ItemCardSeries: typeof import('./components/item/Card/Series.vue')['default'] + ItemCard: typeof import('./components/item/card/ItemCard.vue')['default'] + ItemCardSeries: typeof import('./components/item/card/Series.vue')['default'] LayoutAppBar: typeof import('./components/layout/app/Bar.vue')['default'] LayoutAppDrawer: typeof import('./components/layout/app/drawer/Drawer.vue')['default'] LayoutAppDrawerFooter: typeof import('./components/layout/app/drawer/Footer.vue')['default'] @@ -77,6 +77,11 @@ declare module 'vue' { RemoteFileList: typeof import('./components/RemoteFileList.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] + SeriesDeletionWarning: typeof import('./components/series/DeletionWarning.vue')['default'] + SeriesFormEditMetadata: typeof import('./components/series/form/EditMetadata.vue')['default'] + SeriesMenu: typeof import('./components/series/menu/SeriesMenu.vue')['default'] + SeriesMenuBottomSheet: typeof import('./components/series/menu/SeriesMenuBottomSheet.vue')['default'] + 'SeriesMenuBottomSheet.stories': typeof import('./components/series/menu/SeriesMenuBottomSheet.stories.ts')['default'] ServerSettings: typeof import('./components/server/Settings.vue')['default'] SnackQueue: typeof import('./components/SnackQueue.vue')['default'] ThemeSelector: typeof import('./components/ThemeSelector.vue')['default'] diff --git a/next-ui/src/components/item/card/ItemCard.stories.ts b/next-ui/src/components/item/card/ItemCard.stories.ts index 78d3c431..b77e3ced 100644 --- a/next-ui/src/components/item/card/ItemCard.stories.ts +++ b/next-ui/src/components/item/card/ItemCard.stories.ts @@ -94,6 +94,15 @@ export const QuickActionIcon: Story = { }, } +export const MenuIcon: Story = { + args: { + menuIcon: 'i-mdi:menu', + }, + play: ({ canvas, userEvent }) => { + userEvent.hover(canvas.getByRole('img')) + }, +} + export const SelectableHover: Story = { args: {}, play: ({ canvas, userEvent }) => { diff --git a/next-ui/src/components/item/card/ItemCard.vue b/next-ui/src/components/item/card/ItemCard.vue index 01e25e12..f7cc47ab 100644 --- a/next-ui/src/components/item/card/ItemCard.vue +++ b/next-ui/src/components/item/card/ItemCard.vue @@ -1,5 +1,8 @@