mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
refactor: rework async UserEdit
This commit is contained in:
parent
1e2a1e2663
commit
66bf3a5560
1 changed files with 66 additions and 63 deletions
|
@ -4,11 +4,9 @@ import { useI18n } from 'vue-i18n'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import type ViewBase from '@/components/globals/ViewBase.vue'
|
|
||||||
import { useDomains, useUsersAndGroups } from '@/composables/data'
|
import { useDomains, useUsersAndGroups } from '@/composables/data'
|
||||||
import { useArrayRule, useForm } from '@/composables/form'
|
import { useArrayRule, useForm } from '@/composables/form'
|
||||||
import { useInitialQueries } from '@/composables/useInitialQueries'
|
import { arrayDiff, getKeys } from '@/helpers/commons'
|
||||||
import { arrayDiff } from '@/helpers/commons'
|
|
||||||
import {
|
import {
|
||||||
emailForward,
|
emailForward,
|
||||||
emailLocalPart,
|
emailLocalPart,
|
||||||
|
@ -20,7 +18,8 @@ import {
|
||||||
sameAs,
|
sameAs,
|
||||||
} from '@/helpers/validators'
|
} from '@/helpers/validators'
|
||||||
import { formatAdress, formatForm, sizeToM } from '@/helpers/yunohostArguments'
|
import { formatAdress, formatForm, sizeToM } from '@/helpers/yunohostArguments'
|
||||||
import type { AdressModelValue, FieldProps, FormFieldDict } from '@/types/form'
|
import type { UserDetails } from '@/types/core/data'
|
||||||
|
import type { FieldProps, FormFieldDict } from '@/types/form'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
name: string
|
name: string
|
||||||
|
@ -28,29 +27,30 @@ const props = defineProps<{
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { loading } = useInitialQueries(
|
await api.fetchAll([
|
||||||
[
|
{
|
||||||
{
|
uri: `users/${props.name}`,
|
||||||
uri: `users/${props.name}`,
|
cachePath: `userDetails.${props.name}`,
|
||||||
cachePath: `userDetails.${props.name}`,
|
},
|
||||||
},
|
{ uri: 'domains', cachePath: 'domains' },
|
||||||
{ uri: 'domains', cachePath: 'domains' },
|
])
|
||||||
],
|
|
||||||
{ onQueriesResponse },
|
|
||||||
)
|
|
||||||
|
|
||||||
const viewElem = ref<InstanceType<typeof ViewBase> | null>(null)
|
|
||||||
|
|
||||||
const { domainsAsChoices, mainDomain } = useDomains()
|
const { domainsAsChoices, mainDomain } = useDomains()
|
||||||
|
const { user } = useUsersAndGroups(() => props.name)
|
||||||
|
// mailbox-quota could be 'No quota' or 'Pas de quota'...
|
||||||
|
const mailboxQuota =
|
||||||
|
parseInt(user.value['mailbox-quota'].limit) > 0
|
||||||
|
? sizeToM(user.value['mailbox-quota'].limit) ?? 0
|
||||||
|
: 0
|
||||||
|
|
||||||
type Form = typeof form.value
|
type Form = typeof form.value
|
||||||
const form = ref({
|
const form = ref({
|
||||||
username: props.name,
|
username: props.name,
|
||||||
fullname: '',
|
fullname: user.value.fullname,
|
||||||
mail: { localPart: '', separator: '@', domain: '' } as AdressModelValue,
|
mail: formatAdress(user.value.mail),
|
||||||
mailbox_quota: '' as string | number,
|
mailbox_quota: mailboxQuota,
|
||||||
mail_aliases: [] as AdressModelValue[],
|
mail_aliases: user.value['mail-aliases'].map((mail) => formatAdress(mail)),
|
||||||
mail_forward: [] as string[],
|
mail_forward: [...user.value['mail-forward']],
|
||||||
change_password: '',
|
change_password: '',
|
||||||
confirmation: '',
|
confirmation: '',
|
||||||
})
|
})
|
||||||
|
@ -74,7 +74,10 @@ const fields = reactive({
|
||||||
mail: reactive({
|
mail: reactive({
|
||||||
component: 'AdressItem',
|
component: 'AdressItem',
|
||||||
label: t('user_email'),
|
label: t('user_email'),
|
||||||
rules: { localPart: { required, email: emailLocalPart } },
|
rules: {
|
||||||
|
localPart: { required, email: emailLocalPart },
|
||||||
|
domain: { required },
|
||||||
|
},
|
||||||
cProps: { id: 'mail', choices: domainsAsChoices },
|
cProps: { id: 'mail', choices: domainsAsChoices },
|
||||||
}) satisfies FieldProps<'AdressItem', Form['mail']>,
|
}) satisfies FieldProps<'AdressItem', Form['mail']>,
|
||||||
|
|
||||||
|
@ -88,13 +91,17 @@ const fields = reactive({
|
||||||
cProps: {
|
cProps: {
|
||||||
id: 'mailbox-quota',
|
id: 'mailbox-quota',
|
||||||
placeholder: t('mailbox_quota_placeholder'),
|
placeholder: t('mailbox_quota_placeholder'),
|
||||||
|
type: 'number',
|
||||||
},
|
},
|
||||||
} satisfies FieldProps<'InputItem', Form['mailbox_quota']>,
|
} satisfies FieldProps<'InputItem', Form['mailbox_quota']>,
|
||||||
|
|
||||||
mail_aliases: reactive({
|
mail_aliases: reactive({
|
||||||
component: 'AdressItem',
|
component: 'AdressItem',
|
||||||
|
label: t('user_emailaliases'),
|
||||||
|
id: 'mail_aliases',
|
||||||
rules: useArrayRule(() => form.value.mail_aliases, {
|
rules: useArrayRule(() => form.value.mail_aliases, {
|
||||||
localPart: { required, email: emailLocalPart },
|
localPart: { required, email: emailLocalPart },
|
||||||
|
domain: { required },
|
||||||
}),
|
}),
|
||||||
cProps: {
|
cProps: {
|
||||||
placeholder: t('placeholder.username'),
|
placeholder: t('placeholder.username'),
|
||||||
|
@ -104,6 +111,8 @@ const fields = reactive({
|
||||||
|
|
||||||
mail_forward: reactive({
|
mail_forward: reactive({
|
||||||
component: 'InputItem',
|
component: 'InputItem',
|
||||||
|
label: t('user_emailforward'),
|
||||||
|
id: 'mail_forward',
|
||||||
rules: useArrayRule(() => form.value.mail_forward, {
|
rules: useArrayRule(() => form.value.mail_forward, {
|
||||||
required,
|
required,
|
||||||
emailForward,
|
emailForward,
|
||||||
|
@ -145,57 +154,51 @@ const fields = reactive({
|
||||||
|
|
||||||
const { v, onSubmit } = useForm(form, fields)
|
const { v, onSubmit } = useForm(form, fields)
|
||||||
|
|
||||||
function onQueriesResponse(user_: any) {
|
|
||||||
form.value.fullname = user_.fullname
|
|
||||||
form.value.mail = formatAdress(user_.mail)
|
|
||||||
if (user_['mail-aliases']) {
|
|
||||||
form.value.mail_aliases = user_['mail-aliases'].map((mail) =>
|
|
||||||
formatAdress(mail),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (user_['mail-forward']) {
|
|
||||||
form.value.mail_forward = user_['mail-forward'].map((mail) => ({ mail })) // Copy value
|
|
||||||
}
|
|
||||||
// mailbox-quota could be 'No quota' or 'Pas de quota'...
|
|
||||||
if (parseInt(user_['mailbox-quota'].limit) > 0) {
|
|
||||||
form.value.mailbox_quota = sizeToM(user_['mailbox-quota'].limit)
|
|
||||||
} else {
|
|
||||||
form.value.mailbox_quota = ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onUserEdit = onSubmit(async (onError, serverErrors) => {
|
const onUserEdit = onSubmit(async (onError, serverErrors) => {
|
||||||
const { username: _, ...formData } = await formatForm(form, {
|
const {
|
||||||
|
username: _,
|
||||||
|
confirmation: __,
|
||||||
|
...formData
|
||||||
|
} = await formatForm(form, {
|
||||||
removeEmpty: true,
|
removeEmpty: true,
|
||||||
})
|
})
|
||||||
const user_ = useUsersAndGroups(props.name).user.value!
|
const data = {} as Partial<
|
||||||
const data = {}
|
Omit<UserDetails, 'mail-aliases' | 'mail-forward' | 'mailbox-quota'> &
|
||||||
|
Record<
|
||||||
|
| 'add_mailalias'
|
||||||
|
| 'remove_mailalias'
|
||||||
|
| 'add_mailforward'
|
||||||
|
| 'remove_mailforward',
|
||||||
|
string[]
|
||||||
|
> & { mailbox_quota: string; change_password: string }
|
||||||
|
>
|
||||||
if (!Object.prototype.hasOwnProperty.call(formData, 'mailbox_quota')) {
|
if (!Object.prototype.hasOwnProperty.call(formData, 'mailbox_quota')) {
|
||||||
formData.mailbox_quota = ''
|
formData.mailbox_quota = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// formData.mail_forward = formData.mail_forward?.map((v) => v.mail)
|
for (const key of ['mail_aliases', 'mail_forward'] as const) {
|
||||||
|
const dashedKey = key.replace('_', '-') as 'mail-aliases' | 'mail-forward'
|
||||||
for (const key of ['mail_aliases', 'mail_forward']) {
|
const newKey = key.replace('_', '').replace('es', '') as
|
||||||
const dashedKey = key.replace('_', '-')
|
| 'mailalias'
|
||||||
const newKey = key.replace('_', '').replace('es', '')
|
| 'mailforward'
|
||||||
const addDiff = arrayDiff(formData[key], user_[dashedKey])
|
const addDiff = arrayDiff(formData[key], user.value[dashedKey])
|
||||||
const rmDiff = arrayDiff(user_[dashedKey], formData[key])
|
const rmDiff = arrayDiff(user.value[dashedKey], formData[key])
|
||||||
if (addDiff.length) data['add_' + newKey] = addDiff
|
if (addDiff.length) data[`add_${newKey}`] = addDiff
|
||||||
if (rmDiff.length) data['remove_' + newKey] = rmDiff
|
if (rmDiff.length) data[`remove_${newKey}`] = rmDiff
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const key in formData) {
|
getKeys(formData).forEach((key) => {
|
||||||
|
if (key === 'mail_aliases' || key === 'mail_forward') return
|
||||||
if (key === 'mailbox_quota') {
|
if (key === 'mailbox_quota') {
|
||||||
const quota =
|
if (formData[key] !== mailboxQuota) {
|
||||||
parseInt(formData[key]) > 0 ? formData[key] + 'M' : 'No quota'
|
data[key] = formData[key]! > 0 ? formData[key] + 'M' : 'No quota'
|
||||||
if (parseInt(quota) !== parseInt(user_['mailbox-quota'].limit)) {
|
|
||||||
data[key] = quota === 'No quota' ? '0' : quota
|
|
||||||
}
|
}
|
||||||
} else if (!key.includes('mail_') && formData[key] !== user_[key]) {
|
} else if (key === 'change_password') {
|
||||||
|
data.change_password = formData[key]
|
||||||
|
} else if (formData[key] !== user.value[key]) {
|
||||||
data[key] = formData[key]
|
data[key] = formData[key]
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
if (Object.keys(data).length === 0) {
|
if (Object.keys(data).length === 0) {
|
||||||
serverErrors.global = [t('error_modify_something')]
|
serverErrors.global = [t('error_modify_something')]
|
||||||
|
@ -217,7 +220,7 @@ const onUserEdit = onSubmit(async (onError, serverErrors) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ViewBase ref="viewElem" :loading="loading" skeleton="CardFormSkeleton">
|
<div>
|
||||||
<CardForm
|
<CardForm
|
||||||
v-model="form"
|
v-model="form"
|
||||||
icon="user"
|
icon="user"
|
||||||
|
@ -252,7 +255,7 @@ const onUserEdit = onSubmit(async (onError, serverErrors) => {
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</CardForm>
|
</CardForm>
|
||||||
</ViewBase>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
Loading…
Reference in a new issue