delete user

This commit is contained in:
Gauthier Roebroeck 2025-05-26 17:11:50 +08:00
parent 84d25f1cb1
commit b5b4562b1d
5 changed files with 144 additions and 4 deletions

View file

@ -33,3 +33,19 @@ export const useUpdateUserPassword = defineMutation(() => {
},
})
})
export const useDeleteUser = defineMutation(() => {
const queryCache = useQueryCache()
return useMutation({
mutation: (userId: string) =>
komgaClient.DELETE('/api/v2/users/{id}', {
params: {path: {id: userId}},
}),
onSuccess: () => {
void queryCache.invalidateQueries({key: ['users']})
},
onError: (error) => {
console.log('delete user error', error)
},
})
})

View file

@ -21,6 +21,7 @@ declare module 'vue' {
AppFooter: typeof import('./components/AppFooter.vue')['default']
BuildCommit: typeof import('./components/BuildCommit.vue')['default']
BuildVersion: typeof import('./components/BuildVersion.vue')['default']
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']
FormUserRoles: typeof import('./components/forms/user/FormUserRoles.vue')['default']

View file

@ -0,0 +1,89 @@
<template>
<v-dialog
v-model="showDialog"
:activator="activator"
:max-width="maxWidth"
>
<v-form
v-model="formValid"
@submit.prevent="submitForm()"
>
<v-card
:title="title"
:subtitle="subtitle"
>
<template #text>
<slot name="warning" />
<slot name="text">
Please type <span class="font-weight-bold">{{ validateText }}</span> to confirm.
</slot>
<v-text-field
:rules="[rules.sameAs(validateText)]"
hide-details
class="mt-2"
/>
</template>
<template #actions>
<v-spacer />
<v-btn
text="Cancel"
@click="close()"
/>
<v-btn
:disabled="!formValid"
:text="okText"
type="submit"
variant="elevated"
rounded="xs"
color="error"
/>
</template>
</v-card>
</v-form>
</v-dialog>
</template>
<script setup lang="ts">
import {useRules} from 'vuetify/labs/rules'
const showDialog = defineModel<boolean>('dialog', {required: false})
const emit = defineEmits<{
confirm: []
}>()
const formValid = ref<boolean>(false)
const rules = useRules()
function submitForm() {
if(formValid.value) {
emit('confirm')
close()
}
}
export interface Props {
title?: string,
subtitle?: string,
okText?: string,
validateText?: string,
maxWidth?: string | number,
activator?: Element | string,
}
const {
title = undefined,
subtitle = undefined,
okText = 'Confirm',
validateText = 'confirm',
maxWidth = undefined,
activator = undefined,
} = defineProps<Props>()
function close() {
showDialog.value = false
}
</script>

View file

@ -47,6 +47,7 @@
</template>
<script setup lang="ts">
/** Dialog super component de la race*/
const showDialog = defineModel<boolean>('dialog', {required: false})
const record = defineModel<unknown>('record', {required: true})
@ -56,7 +57,11 @@ function submitForm(callback: () => void) {
if(formValid.value) callback()
}
export interface Props {
interface Props {
/**
* Dialog title
* @type string
*/
title?: string,
subtitle?: string,
maxWidth?: string | number,
@ -74,4 +79,3 @@ function close() {
showDialog.value = false
}
</script>

View file

@ -54,7 +54,7 @@
icon="mdi-delete"
:disabled="me?.id == user.id"
@click="showDialog(ACTION.DELETE, user)"
@mouseenter="activator = $event.currentTarget"
@mouseenter="activatorDelete = $event.currentTarget"
/>
</div>
</template>
@ -75,6 +75,33 @@
/>
</template>
</DialogConfirmEdit>
<DialogConfirm
:activator="activatorDelete"
:title="dialogTitle"
:subtitle="userRecord?.email"
ok-text="Delete"
:validate-text="userRecord?.email"
max-width="600"
@confirm="handleDialogConfirmation()"
>
<template #warning>
<v-alert
type="warning"
variant="tonal"
class="mb-4"
>
<div>The user account will be deleted from this server.</div>
<ul class="ps-8">
<li>The read progress for this user account will be permanently deleted.</li>
<li>Authentication activity for this user will be permanently deleted.</li>
</ul>
<div class="font-weight-bold mt-4">
This action cannot be undone.
</div>
</v-alert>
</template>
</DialogConfirm>
</template>
</template>
@ -84,7 +111,7 @@ import {komgaClient} from '@/api/komga-client.ts'
import type {components} from '@/generated/openapi/komga'
import {useCurrentUser} from '@/colada/queries/current-user.ts'
import {UserRoles} from '@/types/UserRoles.ts'
import {useUpdateUser, useUpdateUserPassword} from '@/colada/mutations/update-user.ts'
import {useDeleteUser, useUpdateUser, useUpdateUserPassword} from '@/colada/mutations/update-user.ts'
import FormUserChangePassword from '@/components/forms/user/FormUserChangePassword.vue'
import FormUserRoles from '@/components/forms/user/FormUserRoles.vue'
import type {Component} from 'vue'
@ -140,12 +167,14 @@ const currentAction = ref<ACTION>()
// the record passed to the dialog's form's model
const dialogRecord = ref<unknown>()
const activator = ref<Element>()
const activatorDelete = ref<Element>()
const dialogTitle = ref<string>()
// dynamic component for the dialog's inner form
const dialogComponent = shallowRef<Component>()
const {mutate: mutateUser} = useUpdateUser()
const {mutate: mutateUserPassword} = useUpdateUserPassword()
const {mutate: mutateDeleteUser} = useDeleteUser()
enum ACTION {
EDIT, DELETE, RESTRICTIONS, PASSWORD
@ -184,6 +213,7 @@ function handleDialogConfirmation() {
mutateUser(dialogRecord.value as components["schemas"]["UserDto"])
break;
case ACTION.DELETE:
mutateDeleteUser(userRecord.value!.id)
break;
case ACTION.RESTRICTIONS:
break;