From a4e92ef798f1566a6810c23d300df497d7c3cc9f Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Tue, 27 May 2025 15:17:47 +0800 Subject: [PATCH] user creation and revamp edit dialog to support restrictions --- next-ui/src/colada/mutations/update-user.ts | 15 ++ next-ui/src/colada/queries/libraries.ts | 14 ++ next-ui/src/colada/queries/referential.ts | 14 ++ next-ui/src/components.d.ts | 1 + .../forms/user/FormUserChangePassword.vue | 10 +- .../components/forms/user/FormUserEdit.vue | 180 ++++++++++++++++++ .../components/forms/user/FormUserRoles.vue | 22 --- next-ui/src/generated/openapi/komga.d.ts | 6 +- next-ui/src/pages/server/users.vue | 94 ++++++--- 9 files changed, 305 insertions(+), 51 deletions(-) create mode 100644 next-ui/src/colada/queries/libraries.ts create mode 100644 next-ui/src/colada/queries/referential.ts create mode 100644 next-ui/src/components/forms/user/FormUserEdit.vue delete mode 100644 next-ui/src/components/forms/user/FormUserRoles.vue diff --git a/next-ui/src/colada/mutations/update-user.ts b/next-ui/src/colada/mutations/update-user.ts index e8662a8b8..1f20342e4 100644 --- a/next-ui/src/colada/mutations/update-user.ts +++ b/next-ui/src/colada/mutations/update-user.ts @@ -2,6 +2,21 @@ import {defineMutation, useMutation, useQueryCache} from '@pinia/colada' import {komgaClient} from '@/api/komga-client' import type {components} from '@/generated/openapi/komga' +export const useCreateUser = defineMutation(() => { + const queryCache = useQueryCache() + return useMutation({ + mutation: (user: components['schemas']['UserCreationDto']) => + komgaClient.POST('/api/v2/users', { + body: user, + }), + onSuccess: () => { + void queryCache.invalidateQueries({key: ['users']}) + }, + onError: (error) => { + console.log('create user error', error) + }, + }) +}) export const useUpdateUser = defineMutation(() => { const queryCache = useQueryCache() return useMutation({ diff --git a/next-ui/src/colada/queries/libraries.ts b/next-ui/src/colada/queries/libraries.ts new file mode 100644 index 000000000..db7d9c085 --- /dev/null +++ b/next-ui/src/colada/queries/libraries.ts @@ -0,0 +1,14 @@ +import {defineQuery, useQuery} from '@pinia/colada' +import {komgaClient} from '@/api/komga-client' + +export const useLibraries = defineQuery(() => { + return useQuery({ + key: () => ['libraries'], + query: () => komgaClient.GET('/api/v1/libraries') + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + // 1 hour + staleTime: 60 * 60 * 1000, + gcTime: false, + }) +}) diff --git a/next-ui/src/colada/queries/referential.ts b/next-ui/src/colada/queries/referential.ts new file mode 100644 index 000000000..3623e810f --- /dev/null +++ b/next-ui/src/colada/queries/referential.ts @@ -0,0 +1,14 @@ +import {defineQuery, useQuery} from '@pinia/colada' +import {komgaClient} from '@/api/komga-client' + +export const useSharingLabels = defineQuery(() => { + return useQuery({ + key: () => ['sharing-labels'], + query: () => komgaClient.GET('/api/v1/sharing-labels') + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + // 1 hour + staleTime: 60 * 60 * 1000, + gcTime: false, + }) +}) diff --git a/next-ui/src/components.d.ts b/next-ui/src/components.d.ts index 8c2850ef5..86723d8f3 100644 --- a/next-ui/src/components.d.ts +++ b/next-ui/src/components.d.ts @@ -24,6 +24,7 @@ declare module 'vue' { DialogConfirm: typeof import('./components/dialogs/DialogConfirm.vue')['default'] DialogConfirmEdit: typeof import('./components/dialogs/DialogConfirmEdit.vue')['default'] FormUserChangePassword: typeof import('./components/forms/user/FormUserChangePassword.vue')['default'] + FormUserEdit: typeof import('./components/forms/user/FormUserEdit.vue')['default'] FormUserRoles: typeof import('./components/forms/user/FormUserRoles.vue')['default'] HelloWorld: typeof import('./components/HelloWorld.vue')['default'] LoginForm: typeof import('./components/LoginForm.vue')['default'] diff --git a/next-ui/src/components/forms/user/FormUserChangePassword.vue b/next-ui/src/components/forms/user/FormUserChangePassword.vue index 5b81178d2..1dbe66084 100644 --- a/next-ui/src/components/forms/user/FormUserChangePassword.vue +++ b/next-ui/src/components/forms/user/FormUserChangePassword.vue @@ -4,18 +4,20 @@ :rules="[rules.required()]" label="New password" autocomplete="off" + autofocus :type="showPassword ? 'text' : 'password'" - :append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" - @click:append="showPassword = !showPassword" + :append-inner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" + @click:append-inner="showPassword = !showPassword" /> diff --git a/next-ui/src/components/forms/user/FormUserEdit.vue b/next-ui/src/components/forms/user/FormUserEdit.vue new file mode 100644 index 000000000..48a8155aa --- /dev/null +++ b/next-ui/src/components/forms/user/FormUserEdit.vue @@ -0,0 +1,180 @@ + + + diff --git a/next-ui/src/components/forms/user/FormUserRoles.vue b/next-ui/src/components/forms/user/FormUserRoles.vue deleted file mode 100644 index 62ea9feec..000000000 --- a/next-ui/src/components/forms/user/FormUserRoles.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/next-ui/src/generated/openapi/komga.d.ts b/next-ui/src/generated/openapi/komga.d.ts index c5d5c2484..f19941521 100644 --- a/next-ui/src/generated/openapi/komga.d.ts +++ b/next-ui/src/generated/openapi/komga.d.ts @@ -2669,7 +2669,7 @@ export interface components { /** Format: int32 */ age: number; /** @enum {string} */ - restriction: "ALLOW_ONLY" | "EXCLUDE"; + restriction: "ALLOW_ONLY" | "EXCLUDE" | "NONE"; }; AllOfBook: components["schemas"]["Book"] & { allOf: (components["schemas"]["AllOfBook"] | components["schemas"]["AnyOfBook"] | components["schemas"]["Author"] | components["schemas"]["Deleted"] | components["schemas"]["LibraryId"] | components["schemas"]["MediaProfile"] | components["schemas"]["MediaStatus"] | components["schemas"]["NumberSort"] | components["schemas"]["OneShot"] | components["schemas"]["Poster"] | components["schemas"]["ReadListId"] | components["schemas"]["ReadStatus"] | components["schemas"]["ReleaseDate"] | components["schemas"]["SeriesId"] | components["schemas"]["Tag"] | components["schemas"]["Title"])[]; @@ -3885,9 +3885,13 @@ export interface components { url: string; }; UserCreationDto: { + ageRestriction?: components["schemas"]["AgeRestrictionUpdateDto"]; email: string; + labelsAllow?: string[]; + labelsExclude?: string[]; password: string; roles: string[]; + sharedLibraries?: components["schemas"]["SharedLibrariesUpdateDto"]; }; UserDto: { ageRestriction?: components["schemas"]["AgeRestrictionDto"]; diff --git a/next-ui/src/pages/server/users.vue b/next-ui/src/pages/server/users.vue index 0e9fb7fa7..afec731f8 100644 --- a/next-ui/src/pages/server/users.vue +++ b/next-ui/src/pages/server/users.vue @@ -14,6 +14,30 @@ :headers="headers" :hide-default-footer="hideFooter" > + +