2020-11-06 00:17:04 +00:00
|
|
|
<template>
|
2020-11-18 02:11:34 +00:00
|
|
|
<q-form @submit="save" @reset="reset">
|
2020-11-06 00:17:04 +00:00
|
|
|
<q-card-section class="fit row justify-start content-center items-center">
|
|
|
|
<q-input
|
|
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
|
|
label="Vorname"
|
|
|
|
:rules="[notEmpty]"
|
|
|
|
v-model="props.user.firstname"
|
|
|
|
filled
|
|
|
|
/>
|
|
|
|
<q-input
|
|
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
|
|
label="Nachname"
|
|
|
|
:rules="[notEmpty]"
|
|
|
|
v-model="props.user.lastname"
|
|
|
|
filled
|
|
|
|
/>
|
2020-11-15 18:47:05 +00:00
|
|
|
|
2020-11-06 00:17:04 +00:00
|
|
|
<q-input
|
|
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
2020-11-15 18:47:05 +00:00
|
|
|
label="Angezeigter Name"
|
|
|
|
:rules="[notEmpty]"
|
|
|
|
v-model="props.user.display_name"
|
2020-11-06 00:17:04 +00:00
|
|
|
filled
|
|
|
|
/>
|
|
|
|
<q-input
|
|
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
|
|
label="E-Mail"
|
|
|
|
:rules="[isEmail, notEmpty]"
|
|
|
|
v-model="props.user.mail"
|
|
|
|
filled
|
|
|
|
/>
|
|
|
|
<q-input
|
|
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
2020-11-15 18:47:05 +00:00
|
|
|
label="Benutzername"
|
|
|
|
:readonly="!props.newUser"
|
|
|
|
v-model="props.user.userid"
|
|
|
|
:rules="[isUseridUsed, notEmpty]"
|
2020-11-06 00:17:04 +00:00
|
|
|
filled
|
|
|
|
/>
|
|
|
|
<q-select
|
|
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
|
|
label="Rollen"
|
|
|
|
filled
|
|
|
|
multiple
|
|
|
|
use-chips
|
|
|
|
v-model="props.user.roles"
|
2020-11-06 00:31:46 +00:00
|
|
|
:readonly="!canSetRoles"
|
2020-11-06 00:17:04 +00:00
|
|
|
:options="allRoles"
|
|
|
|
option-label="name"
|
|
|
|
option-value="name"
|
|
|
|
/>
|
2020-11-15 18:47:05 +00:00
|
|
|
<IsoDateInput
|
2020-11-16 01:28:03 +00:00
|
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
2020-11-15 18:47:05 +00:00
|
|
|
v-model="props.user.birthday"
|
|
|
|
label="Geburtstag"
|
|
|
|
/>
|
2020-11-16 01:28:03 +00:00
|
|
|
<q-file
|
|
|
|
class="col-xs-12 col-sm-6 q-pa-sm"
|
|
|
|
v-model="avatar"
|
|
|
|
filled
|
|
|
|
label="Avatar"
|
|
|
|
accept=".jpg, image/*"
|
2020-11-16 12:36:55 +00:00
|
|
|
max-file-size="204800"
|
|
|
|
hint="Bilddateien, max. 200 KiB"
|
2020-11-16 01:28:03 +00:00
|
|
|
@rejected="onAvatarRejected"
|
|
|
|
>
|
|
|
|
<template v-slot:append>
|
2020-11-18 02:11:34 +00:00
|
|
|
<q-icon name="mdi-file-image" @click.stop />
|
2020-11-16 01:28:03 +00:00
|
|
|
</template>
|
|
|
|
</q-file>
|
2020-11-06 00:17:04 +00:00
|
|
|
</q-card-section>
|
2020-11-12 21:48:19 +00:00
|
|
|
<q-separator v-if="!props.newUser" />
|
2021-01-21 15:23:40 +00:00
|
|
|
<q-card-section class="fit row justify-start content-center items-center" v-if="!props.newUser">
|
2020-11-06 00:17:04 +00:00
|
|
|
<q-input
|
|
|
|
v-if="isCurrentUser"
|
|
|
|
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]"
|
|
|
|
v-model="password"
|
|
|
|
filled
|
|
|
|
/>
|
|
|
|
<q-input
|
|
|
|
class="col-xs-12 col-sm-6 col-md-4 q-pa-sm"
|
|
|
|
label="Neues Password"
|
|
|
|
type="password"
|
|
|
|
v-model="new_password"
|
|
|
|
filled
|
|
|
|
/>
|
|
|
|
<q-input
|
|
|
|
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]"
|
|
|
|
v-model="new_password2"
|
|
|
|
filled
|
|
|
|
/>
|
|
|
|
</q-card-section>
|
|
|
|
<q-card-actions align="right">
|
2020-11-18 02:11:34 +00:00
|
|
|
<q-btn label="Reset" type="reset" />
|
|
|
|
<q-btn color="primary" type="submit" label="Speichern" />
|
2020-11-06 00:17:04 +00:00
|
|
|
</q-card-actions>
|
|
|
|
</q-form>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2021-01-21 15:23:40 +00:00
|
|
|
import { computed, defineComponent, ref, onBeforeMount } from '@vue/composition-api';
|
2020-11-06 00:17:04 +00:00
|
|
|
import { Store } from 'vuex';
|
|
|
|
import { StateInterface } from 'src/store';
|
2020-11-24 17:42:43 +00:00
|
|
|
import { hasPermission } from 'src/utils/permission';
|
2020-11-15 18:47:05 +00:00
|
|
|
import IsoDateInput from 'src/components/utils/IsoDateInput.vue';
|
2020-11-16 01:28:03 +00:00
|
|
|
import { Notify } from 'quasar';
|
2020-11-06 00:17:04 +00:00
|
|
|
|
|
|
|
interface Props {
|
|
|
|
user?: FG.User;
|
2020-11-12 21:48:19 +00:00
|
|
|
newUser?: boolean;
|
2020-11-06 00:17:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
name: 'MainUserSettings',
|
2020-11-15 18:47:05 +00:00
|
|
|
components: { IsoDateInput: IsoDateInput },
|
2020-11-12 21:48:19 +00:00
|
|
|
props: {
|
|
|
|
user: {
|
2020-11-18 02:11:34 +00:00
|
|
|
required: true
|
2020-11-12 21:48:19 +00:00
|
|
|
},
|
|
|
|
newUser: {
|
2020-11-18 02:11:34 +00:00
|
|
|
default: false
|
|
|
|
}
|
2020-11-12 21:48:19 +00:00
|
|
|
},
|
|
|
|
setup(props: Props, { root, emit }) {
|
2020-11-06 00:17:04 +00:00
|
|
|
const store = <Store<StateInterface>>root.$store;
|
|
|
|
|
|
|
|
onBeforeMount(() => {
|
2020-11-18 02:11:34 +00:00
|
|
|
store.dispatch('user/getRoles', false).catch(error => {
|
2020-11-06 00:17:04 +00:00
|
|
|
console.warn(error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const isCurrentUser = computed(
|
|
|
|
() => props.user?.userid === store.state.user.currentUser?.userid
|
|
|
|
);
|
|
|
|
|
|
|
|
const canSetRoles = computed(() => hasPermission('users_set_roles', store));
|
|
|
|
|
|
|
|
const oldUser = computed(() => {
|
|
|
|
if (isCurrentUser.value) return <FG.User>store.state.user.currentUser;
|
|
|
|
else
|
2020-11-18 02:11:34 +00:00
|
|
|
return store.state.user.users.filter(user => {
|
2020-11-06 00:17:04 +00:00
|
|
|
user.userid === props.user?.userid;
|
|
|
|
})[0];
|
|
|
|
});
|
|
|
|
|
2020-11-17 23:27:44 +00:00
|
|
|
const avatar = ref([]);
|
2020-11-16 01:28:03 +00:00
|
|
|
function onAvatarRejected() {
|
|
|
|
Notify.create({
|
2020-11-16 12:44:38 +00:00
|
|
|
group: false,
|
|
|
|
type: 'negative',
|
|
|
|
message: 'Datei zu groß oder keine gültige Bilddatei.',
|
|
|
|
timeout: 10000,
|
|
|
|
progress: true,
|
2020-11-18 02:11:34 +00:00
|
|
|
actions: [{ icon: 'mdi-close', color: 'white' }]
|
2020-11-16 01:28:03 +00:00
|
|
|
});
|
2020-11-17 23:27:44 +00:00
|
|
|
avatar.value = [];
|
2020-11-16 01:28:03 +00:00
|
|
|
}
|
|
|
|
|
2021-01-21 15:23:40 +00:00
|
|
|
const allRoles = computed(() => store.state.user.roles.map(role => role.name));
|
2020-11-06 00:17:04 +00:00
|
|
|
const password = ref('');
|
|
|
|
const new_password = ref('');
|
|
|
|
const new_password2 = ref('');
|
|
|
|
|
|
|
|
function save() {
|
|
|
|
let changed = <FG.User>props.user;
|
2021-01-21 15:23:40 +00:00
|
|
|
if (typeof changed.birthday === 'string') changed.birthday = new Date(changed.birthday);
|
2020-11-06 00:17:04 +00:00
|
|
|
changed = Object.assign(changed, {
|
2020-11-18 02:11:34 +00:00
|
|
|
password: password.value
|
2020-11-06 00:17:04 +00:00
|
|
|
});
|
|
|
|
if (new_password.value != '') {
|
|
|
|
changed = Object.assign(changed, {
|
2020-11-18 02:11:34 +00:00
|
|
|
new_password: new_password.value
|
2020-11-06 00:17:04 +00:00
|
|
|
});
|
|
|
|
}
|
2020-11-12 21:48:19 +00:00
|
|
|
|
|
|
|
emit('update:user', changed);
|
2020-11-18 02:11:34 +00:00
|
|
|
|
2021-01-21 15:23:40 +00:00
|
|
|
if (avatar.value && (avatar.value.length > 0 || avatar.value instanceof File))
|
2020-11-17 02:43:34 +00:00
|
|
|
store
|
|
|
|
.dispatch('user/uploadAvatar', {
|
|
|
|
user: changed,
|
2020-11-18 02:11:34 +00:00
|
|
|
file: avatar.value
|
2020-11-17 02:43:34 +00:00
|
|
|
})
|
|
|
|
.catch((response: Response) => {
|
|
|
|
if (response && response.status == 400) {
|
|
|
|
onAvatarRejected();
|
|
|
|
}
|
|
|
|
});
|
2020-11-17 23:27:44 +00:00
|
|
|
reset();
|
2020-11-06 00:17:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function reset() {
|
2021-01-21 15:23:40 +00:00
|
|
|
//TODO: hier müssen wir uns etwas anderes einfallen lassen!
|
|
|
|
// eslint-disable-next-line vue/no-mutating-props
|
2020-11-06 00:17:04 +00:00
|
|
|
props.user = oldUser.value;
|
|
|
|
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 (
|
2021-01-21 15:23:40 +00:00
|
|
|
!val || /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w\w+)+$/.test(val) || 'E-Mail ist nicht valide.'
|
2020-11-06 00:17:04 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-11-12 21:48:19 +00:00
|
|
|
function isUseridUsed(val: string) {
|
|
|
|
return (
|
|
|
|
!store.state.user.users.find((user: FG.User) => {
|
|
|
|
return user.userid == val;
|
|
|
|
}) ||
|
|
|
|
!props.newUser ||
|
|
|
|
'Benutzername ist schon vergeben'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-11-06 00:17:04 +00:00
|
|
|
return {
|
2020-11-16 01:28:03 +00:00
|
|
|
avatar,
|
|
|
|
onAvatarRejected,
|
2020-11-06 00:17:04 +00:00
|
|
|
props,
|
|
|
|
allRoles,
|
|
|
|
canSetRoles,
|
|
|
|
password,
|
|
|
|
new_password,
|
|
|
|
new_password2,
|
|
|
|
samePassword,
|
|
|
|
isCurrentUser,
|
|
|
|
isEmail,
|
|
|
|
notEmpty,
|
2020-11-12 21:48:19 +00:00
|
|
|
isUseridUsed,
|
2020-11-06 00:17:04 +00:00
|
|
|
save,
|
2020-11-18 02:11:34 +00:00
|
|
|
reset
|
2020-11-06 00:17:04 +00:00
|
|
|
};
|
2020-11-18 02:11:34 +00:00
|
|
|
}
|
2020-11-06 00:17:04 +00:00
|
|
|
});
|
|
|
|
</script>
|