release v2.0.0 #4
|
@ -7,6 +7,7 @@
|
|||
:placeholder="placeholder"
|
||||
:rules="customRules"
|
||||
:clearable="clearable"
|
||||
v-bind="attrs"
|
||||
@clear="dateTime = ''"
|
||||
>
|
||||
<template #append>
|
||||
|
@ -58,7 +59,7 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
emits: { 'update:modelValue': (date?: Date) => !!date || !date },
|
||||
setup(props, { emit }) {
|
||||
setup(props, { emit, attrs }) {
|
||||
const customRules = computed(() => [
|
||||
props.type == 'date' ? stringIsDate : props.type == 'time' ? stringIsTime : stringIsDateTime,
|
||||
...props.rules,
|
||||
|
@ -138,12 +139,13 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
return {
|
||||
attrs,
|
||||
clearable,
|
||||
date,
|
||||
time,
|
||||
dateTime,
|
||||
customRules,
|
||||
date,
|
||||
dateTime,
|
||||
placeholder,
|
||||
time,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<q-input v-model="password" v-bind="attrs" :label="label" :type="type">
|
||||
<template #append><q-icon :name="name" class="cursor-pointer" @click="toggle" /></template
|
||||
></q-input>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PasswordInput',
|
||||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
emits: {
|
||||
'update:modelValue': (value: string) => !!value,
|
||||
},
|
||||
setup(props, { emit, attrs }) {
|
||||
const isPassword = ref(true);
|
||||
const type = computed(() => (isPassword.value ? 'password' : 'text'));
|
||||
const name = computed(() => (isPassword.value ? 'visibility_off' : 'visibility'));
|
||||
const password = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value: string) => emit('update:modelValue', value),
|
||||
});
|
||||
function toggle() {
|
||||
isPassword.value = !isPassword.value;
|
||||
}
|
||||
|
||||
return {
|
||||
attrs,
|
||||
isPassword,
|
||||
name,
|
||||
password,
|
||||
toggle,
|
||||
type,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
|
@ -6,20 +6,21 @@
|
|||
</q-toolbar>
|
||||
|
||||
<q-card-section>
|
||||
<q-form ref="LoginForm" class="q-gutter-md" @submit="doLogin">
|
||||
<q-form class="q-gutter-md" @submit="doLogin">
|
||||
<q-input
|
||||
v-model="userid"
|
||||
filled
|
||||
label="Benutzername oder E-Mail"
|
||||
:rules="rules"
|
||||
autocomplete="username"
|
||||
:rules="[notEmpty]"
|
||||
tabindex="1"
|
||||
/>
|
||||
<q-input
|
||||
<password-input
|
||||
v-model="password"
|
||||
filled
|
||||
type="password"
|
||||
label="Password"
|
||||
:rules="rules"
|
||||
label="Passwort"
|
||||
autocomplete="cureent-password"
|
||||
:rules="[notEmpty]"
|
||||
tabindex="2"
|
||||
/>
|
||||
<div class="row justify-between">
|
||||
|
@ -54,15 +55,18 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Loading, Notify } from 'quasar';
|
||||
import { useMainStore } from 'src/stores';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import { setBaseURL, api } from 'boot/axios';
|
||||
import { notEmpty } from 'src/utils/validators';
|
||||
import { useUserStore } from 'src/plugins/user/store';
|
||||
import PasswordInput from 'src/components/utils/PasswordInput.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Login',
|
||||
components: { PasswordInput },
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
const mainRoute = { name: 'dashboard' };
|
||||
|
@ -71,7 +75,6 @@ export default defineComponent({
|
|||
/* Stuff for the real login page */
|
||||
const userid = ref('');
|
||||
const password = ref('');
|
||||
const rules = [(val: string) => (val && val.length > 0) || 'Feld darf nicht leer sein!'];
|
||||
const server = ref<string | undefined>(api.defaults.baseURL);
|
||||
const visible = ref(false);
|
||||
|
||||
|
@ -138,15 +141,15 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
return {
|
||||
userid,
|
||||
password,
|
||||
changeUrl,
|
||||
doLogin,
|
||||
doReset,
|
||||
rules,
|
||||
server,
|
||||
changeUrl,
|
||||
visible,
|
||||
notEmpty,
|
||||
openServerSettings,
|
||||
password,
|
||||
server,
|
||||
userid,
|
||||
visible,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -2,44 +2,48 @@
|
|||
<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"
|
||||
v-model="userModel.firstname"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
label="Vorname"
|
||||
:rules="[notEmpty]"
|
||||
autocomplete="given-name"
|
||||
filled
|
||||
/>
|
||||
<q-input
|
||||
v-model="user_model.lastname"
|
||||
v-model="userModel.lastname"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
label="Nachname"
|
||||
:rules="[notEmpty]"
|
||||
autocomplete="family-name"
|
||||
filled
|
||||
/>
|
||||
|
||||
<q-input
|
||||
v-model="user_model.display_name"
|
||||
v-model="userModel.display_name"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
label="Angezeigter Name"
|
||||
:rules="[notEmpty]"
|
||||
autocomplete="nickname"
|
||||
filled
|
||||
/>
|
||||
<q-input
|
||||
v-model="user_model.mail"
|
||||
v-model="userModel.mail"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
label="E-Mail"
|
||||
:rules="[isEmail, notEmpty]"
|
||||
autocomplete="email"
|
||||
filled
|
||||
/>
|
||||
<q-input
|
||||
v-model="user_model.userid"
|
||||
v-model="userModel.userid"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
label="Benutzername"
|
||||
:readonly="!newUser"
|
||||
:rules="[isUseridUsed, notEmpty]"
|
||||
:rules="[isUIDUsed, notEmpty]"
|
||||
autocomplete="username"
|
||||
filled
|
||||
/>
|
||||
<q-select
|
||||
v-model="user_model.roles"
|
||||
v-model="userModel.roles"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
label="Rollen"
|
||||
filled
|
||||
|
@ -51,9 +55,10 @@
|
|||
option-value="name"
|
||||
/>
|
||||
<IsoDateInput
|
||||
v-model="user_model.birthday"
|
||||
v-model="userModel.birthday"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
label="Geburtstag"
|
||||
autocomplete="bday"
|
||||
/>
|
||||
<q-file
|
||||
v-model="avatar"
|
||||
|
@ -72,31 +77,22 @@
|
|||
</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
|
||||
<PasswordInput
|
||||
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
|
||||
label="Passwort"
|
||||
autocomplete="current-password"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
hint="Passwort muss immer eingetragen werden"
|
||||
/>
|
||||
<q-input
|
||||
v-model="new_password"
|
||||
class="col-xs-12 col-sm-6 col-md-4 q-pa-sm"
|
||||
<PasswordInput
|
||||
v-model="newPassword"
|
||||
filled
|
||||
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
|
||||
autocomplete="new-password"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
/>
|
||||
</q-card-section>
|
||||
<q-card-actions align="right">
|
||||
|
@ -109,14 +105,16 @@
|
|||
<script lang="ts">
|
||||
import { Notify } from 'quasar';
|
||||
import { hasPermission } from 'src/utils/permission';
|
||||
import { notEmpty, isEmail } from 'src/utils/validators';
|
||||
import IsoDateInput from 'src/components/utils/IsoDateInput.vue';
|
||||
import PasswordInput from 'src/components/utils/PasswordInput.vue';
|
||||
import { defineComponent, computed, ref, onBeforeMount, PropType } from 'vue';
|
||||
import { useUserStore } from '../../store';
|
||||
import { useMainStore } from 'src/stores';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MainUserSettings',
|
||||
components: { IsoDateInput },
|
||||
components: { IsoDateInput, PasswordInput },
|
||||
props: {
|
||||
user: {
|
||||
required: true,
|
||||
|
@ -131,17 +129,19 @@ export default defineComponent({
|
|||
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 password = ref('');
|
||||
const newPassword = ref('');
|
||||
const avatar = ref<string[]>([]);
|
||||
const userModel = ref(props.user);
|
||||
|
||||
const canSetRoles = computed(() => hasPermission('users_set_roles'));
|
||||
const allRoles = computed(() => userStore.roles.map((role) => role.name));
|
||||
const isCurrentUser = computed(() => userModel.value.userid === mainStore.currentUser.userid);
|
||||
|
||||
const avatar = ref([] as string[]);
|
||||
function onAvatarRejected() {
|
||||
Notify.create({
|
||||
group: false,
|
||||
|
@ -154,20 +154,15 @@ export default defineComponent({
|
|||
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;
|
||||
let changed = userModel.value;
|
||||
if (typeof changed.birthday === 'string') changed.birthday = new Date(changed.birthday);
|
||||
changed = Object.assign(changed, {
|
||||
password: password.value,
|
||||
});
|
||||
if (new_password.value != '') {
|
||||
if (newPassword.value != '') {
|
||||
changed = Object.assign(changed, {
|
||||
new_password: new_password.value,
|
||||
new_password: newPassword.value,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -183,52 +178,32 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
function reset() {
|
||||
user_model.value = props.user;
|
||||
userModel.value = props.user;
|
||||
password.value = '';
|
||||
new_password.value = '';
|
||||
new_password2.value = '';
|
||||
newPassword.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) {
|
||||
function isUIDUsed(val: string) {
|
||||
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 ||
|
||||
userStore.users.findIndex((user) => user.userid === val) !== -1 ||
|
||||
'Benutzername ist schon vergeben'
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
avatar,
|
||||
user_model,
|
||||
onAvatarRejected,
|
||||
allRoles,
|
||||
avatar,
|
||||
canSetRoles,
|
||||
password,
|
||||
new_password,
|
||||
new_password2,
|
||||
samePassword,
|
||||
isCurrentUser,
|
||||
isEmail,
|
||||
isUIDUsed,
|
||||
newPassword,
|
||||
notEmpty,
|
||||
isUseridUsed,
|
||||
save,
|
||||
onAvatarRejected,
|
||||
password,
|
||||
reset,
|
||||
save,
|
||||
userModel,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -15,3 +15,9 @@ export function stringIsTime(val: string) {
|
|||
export function stringIsDateTime(val: string) {
|
||||
return !val || /^\d{4}-\d\d-\d\d \d\d:\d\d$/.test(val) || 'Datum und Zeit ist nicht gültig.';
|
||||
}
|
||||
|
||||
export function isEmail(val: string) {
|
||||
return (
|
||||
!val || /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w\w+)+$/.test(val) || 'E-Mail ist nicht gültig.'
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue