yunohost-admin/app/src/views/user/UserEdit.vue
2020-10-14 16:59:38 +02:00

284 lines
8.8 KiB
Vue

<template lang="html">
<div class="user-edit">
<b-card v-if="this.form.firstname" :header="user ? $t('user_username_edit', { name: user.username }) : ''" header-tag="h2">
<b-form id="user-edit" @submit.prevent="onSubmit">
<!-- USER FULLNAME -->
<b-form-group label-cols="auto">
<template v-slot:label aria-hidden="true">
{{ $t('user_fullname') }}
</template>
<div class="input-double">
<b-input-group>
<b-input-group-prepend
tag="label" class="ssr-only" is-text
for="input-firstname"
>
{{ $t('common.firstname') }}
</b-input-group-prepend>
<b-input
id="input-firstname" :placeholder="$t('placeholder.firstname')"
v-model="form.firstname"
/>
</b-input-group>
<b-input-group>
<b-input-group-prepend
tag="label" class="ssr-only" is-text
for="input-lastname"
>
{{ $t('common.lastname') }}
</b-input-group-prepend>
<b-input
id="input-firstname" :placeholder="$t('placeholder.lastname')"
v-model="form.lastname"
/>
</b-input-group>
</div>
</b-form-group>
<!-- USER EMAIL -->
<b-form-group label-cols="auto" :label="$t('user_email')" label-for="input-email">
<splitted-mail-input
id="input-email" feedback="email-feedback"
v-model="form.mail" :domains="domains"
:state="isValid.mail" @input="validateEmail"
/>
<b-form-invalid-feedback id="email-feedback" :state="isValid.mail">
{{ this.error.mail }}
</b-form-invalid-feedback>
</b-form-group>
<!-- MAILBOX QUOTA -->
<hr>
<b-form-group
label-cols="auto" :label="$t('user_mailbox_quota')" label-for="input-mailbox-quota"
:description="$t('mailbox_quota_description')"
>
<b-input-group append="M">
<b-input
id="input-mailbox-quota" :placeholder="$t('mailbox_quota_placeholder')"
v-model="form['mailbox-quota']" type="number" min="0"
/>
</b-input-group>
</b-form-group>
<!-- MAIL ALIASES -->
<hr>
<b-form-group label-cols="auto" :label="$t('user_emailaliases')" class="mail-list">
<splitted-mail-input
v-for="(alias, index) in form['mail-aliases']" :key="index"
feedback="mail-aliases-feedback"
v-model="form['mail-aliases'][index]" :domains="domains"
/>
</b-form-group>
<!-- MAIL FORWARD -->
<hr>
<b-form-group label-cols="auto" :label="$t('user_emailforward')" class="mail-list">
<b-input
v-for="(forward, index) in form['mail-forward']" :key="index"
id="input-mailbox-quota" :placeholder="$t('user_new_forward')"
v-model="form['mail-forward'][index]" type="email"
/>
</b-form-group>
<!-- USER PASSWORD -->
<hr>
<b-form-group label-cols="auto" :label="$t('password')" label-for="input-password">
<b-input
id="input-password" placeholder="••••••••"
aria-describedby="password-feedback"
v-model="form.password" type="password"
:state="isValid.password" @input="validatePassword"
/>
<b-form-invalid-feedback id="password-feedback" :state="isValid.password">
{{ $t('passwords_too_short') }}
</b-form-invalid-feedback>
</b-form-group>
<!-- USER PASSWORD CONFIRMATION -->
<b-form-group
label-cols="auto" :label="$t('password_confirmation')" label-for="input-confirmation"
:description="$t('good_practices_about_user_password')"
>
<b-input
id="input-confirmation" placeholder="••••••••"
aria-describedby="confirmation-feedback"
v-model="form.confirmation" type="password"
:state="isValid.confirmation" @input="validatePassword"
/>
<b-form-invalid-feedback id="confirmation-feedback" :state="isValid.confirmation">
{{ $t('passwords_dont_match') }}
</b-form-invalid-feedback>
</b-form-group>
<b-form-invalid-feedback id="global-feedback" :state="server.isValid">
{{ this.server.error }}
</b-form-invalid-feedback>
</b-form>
<template v-slot:footer>
<div class="d-flex d-flex justify-content-end">
<b-button type="submit" form="user-edit" variant="success">
{{ $t('save') }}
</b-button>
</div>
</template>
</b-card>
</div>
</template>
<script>
import SplittedMailInput from '@/components/SplittedMailInput'
export default {
name: 'UserEdit',
props: {
name: { type: String, required: true }
},
data () {
return {
form: {
firstname: '',
lastname: '',
mail: '',
'mailbox-quota': '',
'mail-aliases': [],
'mail-forward': [],
password: '',
confirmation: ''
},
isValid: {
mail: null,
password: null,
confirmation: null
},
error: {
mail: ''
},
server: {
isValid: null,
error: ''
}
}
},
computed: {
user () {
return this.$store.state.data.users_details[this.name]
},
domains () {
return this.$store.state.data.domains
}
},
methods: {
onSubmit () {
for (const key in this.isValid) {
if (this.isValid[key] === false) return
}
const data = {}
for (const key of ['firstname', 'lastname', 'mail']) {
if (this.form[key] !== this.user[key]) data[key] = this.form[key]
}
let quota = this.form['mailbox-quota']
quota = parseInt(quota) ? quota + 'M' : 'No quota'
if (quota !== this.user['mailbox-quota'].limit) {
data.mailbox_quota = quota !== 'No quota' ? quota : 0
}
const mails = {
add_mailalias: arrayDiff(this.form['mail-aliases'], this.user['mail-aliases']),
remove_mailalias: arrayDiff(this.user['mail-aliases'], this.form['mail-aliases']),
add_mailforward: arrayDiff(this.form['mail-forward'], this.user['mail-forward']),
remove_mailforward: arrayDiff(this.user['mail-forward'], this.form['mail-forward'])
}
for (const [key, value] of Object.entries(mails)) {
if (value.length > 0) data[key] = value
}
// FIXME move to utils
function arrayDiff (arr1 = [], arr2 = []) {
return arr1.filter(item => ((arr2.indexOf(item) === -1) && (item !== '')))
}
this.$store.dispatch('PUT',
{ uri: 'users', data, param: this.user.username, storeKey: 'users_details' }
).then(() => {
this.$router.push({ name: 'user-list' })
}).catch(error => {
this.server.error = error.message
this.server.isValid = false
})
},
validateEmail () {
// FIXME check allowed characters
const isValid = this.form.mail.split('@')[0].match('^[A-Za-z0-9-_]+$')
this.error.mail = isValid ? '' : this.$i18n.t('form_errors.email_syntax')
this.isValid.mail = isValid ? null : false
},
validatePassword () {
const { password, confirmation } = this.form
this.isValid.password = password.length >= 8 ? null : false
this.isValid.confirmation = password === confirmation ? null : false
}
},
created () {
this.$store.dispatch('FETCH', { uri: 'domains' })
this.$store.dispatch('FETCH',
{ uri: 'users', param: this.name, storeKey: 'users_details' }
).then(userData => {
this.form.firstname = userData.firstname
this.form.lastname = userData.lastname
this.form.mail = userData.mail
this.form['mail-aliases'] = userData['mail-aliases'] ? [...userData['mail-aliases'], ''] : ['']
this.form['mail-forward'] = userData['mail-forward'] ? [...userData['mail-forward'], ''] : ['']
if (userData['mailbox-quota'].limit !== 'No quota') {
this.form['mailbox-quota'] = userData['mailbox-quota'].limit.slice(0, -1)
}
})
},
components: {
SplittedMailInput
}
}
</script>
<style lang="scss" scoped>
@include media-breakpoint-down(xs) {
.form-group:not(:first-of-type) {
padding-top: .5rem;
border-top: $thin-border;
}
hr {
display: none;
}
}
@include media-breakpoint-up(md) {
.input-double {
display: flex;
.input-group + .input-group {
margin-left: .5rem;
}
}
}
.mail-list .col > *:not(:first-of-type) {
margin-top: .5rem;
input {
max-width: 10rem;
}
}
</style>