From ebd9ee3af645332c52293208d2112bca305519f1 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Thu, 4 Dec 2025 14:54:25 +0800 Subject: [PATCH] reorder libraries component --- next-ui/eslint.config.ts | 2 +- next-ui/package-lock.json | 19 +++ next-ui/package.json | 1 + next-ui/src/colada/client-settings.ts | 4 +- next-ui/src/components.d.ts | 1 + .../layout/app/drawer/Drawer.stories.ts | 30 ++++ .../app/drawer/ReorderLibraries.stories.ts | 107 +++++++++++++ .../layout/app/drawer/ReorderLibraries.vue | 144 ++++++++++++++++++ 8 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 next-ui/src/components/layout/app/drawer/Drawer.stories.ts create mode 100644 next-ui/src/components/layout/app/drawer/ReorderLibraries.stories.ts create mode 100644 next-ui/src/components/layout/app/drawer/ReorderLibraries.vue diff --git a/next-ui/eslint.config.ts b/next-ui/eslint.config.ts index d525fa27..3ff1b8ae 100644 --- a/next-ui/eslint.config.ts +++ b/next-ui/eslint.config.ts @@ -55,7 +55,7 @@ export default defineConfigWithVueTs( 'PascalCase', { registeredComponentsOnly: false, - ignores: ['/^v-/'], + ignores: ['/^v-/', 'draggable'], }, ], }, diff --git a/next-ui/package-lock.json b/next-ui/package-lock.json index 8bda9dc3..51e53045 100644 --- a/next-ui/package-lock.json +++ b/next-ui/package-lock.json @@ -21,6 +21,7 @@ "pinia-plugin-persistedstate": "^4.7.1", "vue": "^3.5.25", "vue-intl": "^6.5.27", + "vuedraggable": "^4.1.0", "vuetify": "^3.11.2" }, "devDependencies": { @@ -10113,6 +10114,12 @@ "node": ">=18" } }, + "node_modules/sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==", + "license": "MIT" + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -11708,6 +11715,18 @@ "dev": true, "license": "MIT" }, + "node_modules/vuedraggable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz", + "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", + "license": "MIT", + "dependencies": { + "sortablejs": "1.14.0" + }, + "peerDependencies": { + "vue": "^3.0.1" + } + }, "node_modules/vuetify": { "version": "3.11.2", "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.11.2.tgz", diff --git a/next-ui/package.json b/next-ui/package.json index 28cead58..e6fd2108 100644 --- a/next-ui/package.json +++ b/next-ui/package.json @@ -41,6 +41,7 @@ "pinia-plugin-persistedstate": "^4.7.1", "vue": "^3.5.25", "vue-intl": "^6.5.27", + "vuedraggable": "^4.1.0", "vuetify": "^3.11.2" }, "devDependencies": { diff --git a/next-ui/src/colada/client-settings.ts b/next-ui/src/colada/client-settings.ts index 1c22d0c9..8bcff744 100644 --- a/next-ui/src/colada/client-settings.ts +++ b/next-ui/src/colada/client-settings.ts @@ -38,7 +38,9 @@ export const useClientSettingsUser = defineQuery(() => { export const useUpdateClientSettingsUser = defineMutation(() => { const queryCache = useQueryCache() return useMutation({ - mutation: (settings: Record) => + mutation: ( + settings: Record, + ) => komgaClient.PATCH('/api/v1/client-settings/user', { body: settings, }), diff --git a/next-ui/src/components.d.ts b/next-ui/src/components.d.ts index 8d47ddd5..7fe25e2e 100644 --- a/next-ui/src/components.d.ts +++ b/next-ui/src/components.d.ts @@ -53,6 +53,7 @@ declare module 'vue' { LayoutAppDrawerMenuLogout: typeof import('./components/layout/app/drawer/menu/Logout.vue')['default'] LayoutAppDrawerMenuMedia: typeof import('./components/layout/app/drawer/menu/Media.vue')['default'] LayoutAppDrawerMenuServer: typeof import('./components/layout/app/drawer/menu/Server.vue')['default'] + LayoutAppDrawerReorderLibraries: typeof import('./components/layout/app/drawer/ReorderLibraries.vue')['default'] LocaleSelector: typeof import('./components/LocaleSelector.vue')['default'] PageHashKnownTable: typeof import('./components/pageHash/KnownTable.vue')['default'] PageHashMatchTable: typeof import('./components/pageHash/MatchTable.vue')['default'] diff --git a/next-ui/src/components/layout/app/drawer/Drawer.stories.ts b/next-ui/src/components/layout/app/drawer/Drawer.stories.ts new file mode 100644 index 00000000..81353380 --- /dev/null +++ b/next-ui/src/components/layout/app/drawer/Drawer.stories.ts @@ -0,0 +1,30 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import Drawer from './Drawer.vue' +import { useAppStore } from '@/stores/app' + +const meta = { + component: Drawer, + render: (args: object) => ({ + components: { Drawer }, + setup() { + return { args } + }, + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + }, + args: {}, +} satisfies Meta + +export default meta +type Story = StoryObj + +export const Default: Story = { + args: {}, + play: () => { + const appStore = useAppStore() + appStore.drawer = true + }, +} diff --git a/next-ui/src/components/layout/app/drawer/ReorderLibraries.stories.ts b/next-ui/src/components/layout/app/drawer/ReorderLibraries.stories.ts new file mode 100644 index 00000000..051ff856 --- /dev/null +++ b/next-ui/src/components/layout/app/drawer/ReorderLibraries.stories.ts @@ -0,0 +1,107 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' + +import ReorderLibraries from './ReorderLibraries.vue' +import { httpTyped } from '@/mocks/api/httpTyped' +import { CLIENT_SETTING_USER, type ClientSettingUserLibrary } from '@/types/ClientSettingsUser' +import type { components } from '@/generated/openapi/komga' +import { libraries } from '@/mocks/api/handlers/libraries' + +const meta = { + component: ReorderLibraries, + render: (args: object) => ({ + components: { ReorderLibraries }, + setup() { + return { args } + }, + template: '', + }), + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/configure/story-layout + }, + args: {}, +} satisfies Meta + +export default meta +type Story = StoryObj + +const libHandler = httpTyped.get('/api/v1/libraries', ({ response }) => { + const bds = { + ...libraries[0], + id: '3', + name: 'BDs', + } as components['schemas']['LibraryDto'] + const magazines = { + ...libraries[0], + id: '4', + name: 'Magazines', + } as components['schemas']['LibraryDto'] + const manga = { + ...libraries[0], + id: '5', + name: 'Mangas', + } as components['schemas']['LibraryDto'] + const libs = [...libraries, bds, magazines, manga] + return response(200).json(libs) +}) + +export const AllPinned: Story = { + args: {}, + parameters: { + msw: { + handlers: [libHandler], + }, + }, +} + +export const SomeUnpinned: Story = { + args: {}, + parameters: { + msw: { + handlers: [ + libHandler, + httpTyped.get('/api/v1/client-settings/user/list', ({ response }) => { + const userLibraries: Record = { + '2': { + unpinned: true, + }, + '4': { + unpinned: true, + }, + } + const settings: Record = { + [CLIENT_SETTING_USER.NEXTUI_LIBRARIES]: { + value: JSON.stringify(userLibraries), + }, + } + return response(200).json(settings) + }), + ], + }, + }, +} + +export const AllUnpinned: Story = { + args: {}, + parameters: { + msw: { + handlers: [ + httpTyped.get('/api/v1/client-settings/user/list', ({ response }) => { + const userLibraries: Record = { + '1': { + unpinned: true, + }, + '2': { + unpinned: true, + }, + } + const settings: Record = { + [CLIENT_SETTING_USER.NEXTUI_LIBRARIES]: { + value: JSON.stringify(userLibraries), + }, + } + return response(200).json(settings) + }), + ], + }, + }, +} diff --git a/next-ui/src/components/layout/app/drawer/ReorderLibraries.vue b/next-ui/src/components/layout/app/drawer/ReorderLibraries.vue new file mode 100644 index 00000000..b8ab2eb3 --- /dev/null +++ b/next-ui/src/components/layout/app/drawer/ReorderLibraries.vue @@ -0,0 +1,144 @@ + + + + +