<template> <q-form @submit="save" @reset="reset"> <q-card-section class="fit row justify-start content-center items-center"> <q-input v-model="user_model.firstname" class="col-xs-12 col-sm-6 q-pa-sm" label="Vorname" :rules="[notEmpty]" filled /> <q-input v-model="user_model.lastname" class="col-xs-12 col-sm-6 q-pa-sm" label="Nachname" :rules="[notEmpty]" filled /> <q-input v-model="user_model.display_name" class="col-xs-12 col-sm-6 q-pa-sm" label="Angezeigter Name" :rules="[notEmpty]" filled /> <q-input v-model="user_model.mail" class="col-xs-12 col-sm-6 q-pa-sm" label="E-Mail" :rules="[isEmail, notEmpty]" filled /> <q-input v-model="user_model.userid" class="col-xs-12 col-sm-6 q-pa-sm" label="Benutzername" :readonly="!newUser" :rules="[isUseridUsed, notEmpty]" filled /> <q-select v-model="user_model.roles" class="col-xs-12 col-sm-6 q-pa-sm" label="Rollen" filled multiple use-chips :readonly="!canSetRoles" :options="allRoles" option-label="name" option-value="name" /> <IsoDateInput v-model="user_model.birthday" class="col-xs-12 col-sm-6 q-pa-sm" label="Geburtstag" /> <q-file v-model="avatar" class="col-xs-12 col-sm-6 q-pa-sm" filled label="Avatar" accept=".jpg, image/*" max-file-size="204800" hint="Bilddateien, max. 200 KiB" @rejected="onAvatarRejected" > <template #append> <q-icon name="mdi-file-image" @click.stop /> </template> </q-file> </q-card-section> <q-separator v-if="!newUser" /> <q-card-section v-if="!newUser" class="fit row justify-start content-center items-center"> <q-input v-if="isCurrentUser" v-model="password" class="col-xs-12 col-sm-6 col-md-4 q-pa-sm" label="Password" type="password" hint="Password muss immer eingetragen werden" :rules="[notEmpty]" filled /> <q-input v-model="new_password" class="col-xs-12 col-sm-6 col-md-4 q-pa-sm" label="Neues Password" type="password" filled /> <q-input v-model="new_password2" class="col-xs-12 col-sm-6 col-md-4 q-pa-sm" label="Wiederhole neues Password" type="password" :disable="new_password.length == 0" :rules="[samePassword]" filled /> </q-card-section> <q-card-actions align="right"> <q-btn label="Reset" type="reset" /> <q-btn color="primary" type="submit" label="Speichern" /> </q-card-actions> </q-form> </template> <script lang="ts"> import { Notify } from 'quasar'; import { hasPermission } from 'src/utils/permission'; import IsoDateInput from 'src/components/utils/IsoDateInput.vue'; import { defineComponent, computed, ref, onBeforeMount, PropType } from 'vue'; import { useUserStore } from '../../store'; import { useMainStore } from 'src/store'; export default defineComponent({ name: 'MainUserSettings', components: { IsoDateInput }, props: { user: { required: true, type: Object as PropType<FG.User>, }, newUser: { type: Boolean, required: true }, }, emits: { 'update:user': (payload: FG.User) => !!payload, }, setup(props, { emit }) { const userStore = useUserStore(); const mainStore = useMainStore(); const user_model = ref(props.user); onBeforeMount(() => { void userStore.getRoles(false); }); const isCurrentUser = computed(() => user_model.value.userid === mainStore.currentUser.userid); const canSetRoles = computed(() => hasPermission('users_set_roles')); const avatar = ref([] as string[]); function onAvatarRejected() { Notify.create({ group: false, type: 'negative', message: 'Datei zu groß oder keine gültige Bilddatei.', timeout: 10000, progress: true, actions: [{ icon: 'mdi-close', color: 'white' }], }); avatar.value = []; } const allRoles = computed(() => userStore.roles.map((role) => role.name)); const password = ref(''); const new_password = ref(''); const new_password2 = ref(''); function save() { let changed = user_model.value; if (typeof changed.birthday === 'string') changed.birthday = new Date(changed.birthday); changed = Object.assign(changed, { password: password.value, }); if (new_password.value != '') { changed = Object.assign(changed, { new_password: new_password.value, }); } emit('update:user', changed); if (avatar.value && (avatar.value.length > 0 || avatar.value instanceof File)) userStore.uploadAvatar(changed, avatar.value[0]).catch((response: Response) => { if (response && response.status == 400) { onAvatarRejected(); } }); reset(); } function reset() { user_model.value = props.user; password.value = ''; new_password.value = ''; new_password2.value = ''; } function samePassword(val: string) { return val == new_password.value || 'Passwörter sind nicht identisch!'; } function notEmpty(val: string) { return !!val || 'Feld darf nicht leer sein!'; } function isEmail(val: string | null) { return ( !val || /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w\w+)+$/.test(val) || 'E-Mail ist nicht valide.' ); } function isUseridUsed(val: string) { return ( !userStore.users.find((user: FG.User) => { return user.userid == val; }) || !props.newUser || 'Benutzername ist schon vergeben' ); } return { avatar, user_model, onAvatarRejected, allRoles, canSetRoles, password, new_password, new_password2, samePassword, isCurrentUser, isEmail, notEmpty, isUseridUsed, save, reset, }; }, }); </script>