user password change form

This commit is contained in:
Gauthier Roebroeck 2025-05-23 17:41:08 +08:00
parent cffc4fdb20
commit e79c2ca88b
4 changed files with 85 additions and 35 deletions

View file

@ -18,3 +18,18 @@ export const useUpdateUser = defineMutation(() => {
},
})
})
export const useUpdateUserPassword = defineMutation(() => {
return useMutation({
mutation: ({userId, newPassword}: { userId: string, newPassword: string }) =>
komgaClient.PATCH('/api/v2/users/{id}/password', {
params: {path: {id: userId}},
body: {
password: newPassword,
},
}),
onError: (error) => {
console.log('update user password error', error)
},
})
})

View file

@ -10,12 +10,15 @@
@save="close()"
>
<template #default="{ model: proxyModel, cancel, save, isPristine }">
<v-card
:title="title"
:subtitle="subtitle"
<v-form
v-model="formValid"
@submit.prevent="submitForm(save)"
>
<template #text>
<v-form v-model="formValid">
<v-card
:title="title"
:subtitle="subtitle"
>
<template #text>
<slot
name="text"
:proxy-model="proxyModel"
@ -23,22 +26,21 @@
:save="save"
:is-pristine="isPristine"
/>
</v-form>
</template>
</template>
<template #actions>
<v-spacer />
<v-btn
text="Cancel"
@click="close()"
/>
<v-btn
:disabled="!formValid"
text="Save"
@click="save"
/>
</template>
</v-card>
<template #actions>
<v-spacer />
<v-btn
text="Cancel"
@click="close()"
/>
<v-btn
text="Save"
type="submit"
/>
</template>
</v-card>
</v-form>
</template>
</v-confirm-edit>
</v-dialog>
@ -50,6 +52,10 @@ const record = defineModel<unknown>('record', {required: true})
const formValid = ref<boolean>(false)
function submitForm(callback: () => void) {
if(formValid.value) callback()
}
export interface Props {
title?: string,
subtitle?: string,

View file

@ -1,17 +1,31 @@
<template>
<v-text-field :rules="rules" />
<v-text-field />
<v-text-field
v-model="newPassword"
:rules="[rules.required()]"
label="New password"
autocomplete="off"
:type="showPassword ? 'text' : 'password'"
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
@click:append="showPassword = !showPassword"
/>
<v-text-field
v-model="confirmPassword"
:rules="[rules.sameAs(newPassword)]"
label="Confirm password"
autocomplete="off"
:type="showPassword ? 'text' : 'password'"
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
@click:append="showPassword = !showPassword"
/>
</template>
<script setup lang="ts">
import type {components} from '@/generated/openapi/komga'
import { useRules } from 'vuetify/labs/rules'
const user = defineModel<components["schemas"]["UserDto"] | undefined>({required: true})
const rules = useRules()
const rules = [
value => {
if (value) return true
return 'You must enter a first name.'
},
]
const newPassword = defineModel<string>({required: true})
const confirmPassword = ref<string>()
const showPassword = ref<boolean>(false)
</script>

View file

@ -61,12 +61,12 @@
</v-data-table>
<DialogConfirmEdit
v-model:record="userRecord"
v-model:record="dialogRecord"
:activator="activator"
:title="dialogTitle"
:subtitle="userRecord?.email"
max-width="400"
@update:record="handleConfirmation()"
@update:record="handleDialogConfirmation()"
>
<template #text="{proxyModel}">
<component
@ -84,7 +84,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} from '@/colada/mutations/update-user.ts'
import {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'
@ -133,13 +133,19 @@ onMounted(() => refetchUsers())
// Dialogs handling
// stores the user being actioned upon
const userRecord = ref<components["schemas"]["UserDto"]>()
// stores the ongoing action, so we can handle the action when the dialog is closed with changes
const currentAction = ref<ACTION>()
// the record passed to the dialog's form's model
const dialogRecord = ref<unknown>()
const activator = 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()
enum ACTION {
EDIT, DELETE, RESTRICTIONS, PASSWORD
@ -151,32 +157,41 @@ function showDialog(action: ACTION, user: components["schemas"]["UserDto"]) {
case ACTION.EDIT:
dialogTitle.value = 'Edit Roles'
dialogComponent.value = FormUserRoles
dialogRecord.value = user
break;
case ACTION.DELETE:
dialogTitle.value = 'Delete User'
dialogComponent.value = FormUserRoles
dialogRecord.value = user
break;
case ACTION.RESTRICTIONS:
dialogTitle.value = 'Edit Restrictions'
dialogComponent.value = FormUserRoles
dialogRecord.value = user
break;
case ACTION.PASSWORD:
dialogTitle.value = 'Change Password'
dialogComponent.value = FormUserChangePassword
// password change initiated with an empty string
dialogRecord.value = ''
}
userRecord.value = user
}
function handleConfirmation() {
function handleDialogConfirmation() {
switch (currentAction.value) {
case ACTION.EDIT:
mutateUser(userRecord.value!)
mutateUser(dialogRecord.value as components["schemas"]["UserDto"])
break;
case ACTION.DELETE:
break;
case ACTION.RESTRICTIONS:
break;
case ACTION.PASSWORD:
mutateUserPassword({
userId: userRecord.value!.id,
newPassword: dialogRecord.value as string,
})
break;
}
}