release v2.0.0 #4

Merged
crimsen merged 481 commits from develop into master 2024-01-18 15:15:08 +00:00
4 changed files with 132 additions and 26 deletions
Showing only changes of commit 9b19dc225b - Show all commits

View File

@ -0,0 +1,85 @@
<template>
<q-input
class="col-xs-12 col-sm-6 q-pa-sm"
filled
:readonly="readonly"
:label="label"
:value="getDate()"
placeholder="YYYY-MM-DD"
v-on:input="dateChanged"
:rules="[isDate]"
>
<template v-slot:append>
<q-icon
name="event"
class="cursor-pointer"
>
<q-popup-proxy
ref="qDateProxy"
transition-show="scale"
transition-hide="scale"
>
<q-date
:value="getDate()"
mask="YYYY-MM-DD"
v-on:input="dateChanged"
>
<div class="row items-center justify-end">
<q-btn
v-close-popup
label="Schließen"
color="primary"
flat
/>
</div>
</q-date>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
import { date } from 'quasar';
interface Props {
value?: Date;
label?: string;
readonly: boolean;
}
export default defineComponent({
name: 'IsoDateInput',
props: {
value: {
required: true,
},
label: {},
readonly: {
default: false,
},
},
setup(props: Props, { emit }) {
function getDate() {
if (props.value) {
return date.formatDate(props.value, 'YYYY-MM-DD');
}
return '';
}
function dateChanged(dateString: string) {
emit('input', new Date(dateString));
}
function isDate(val: string) {
return !val || /^\d{4}-\d\d-\d\d$/.test(val) || 'Datum ist nicht gültig.';
}
return {
getDate,
dateChanged,
isDate,
};
},
});
</script>

View File

@ -13,6 +13,7 @@ declare namespace FG {
firstname: string; firstname: string;
lastname: string; lastname: string;
mail: string; mail: string;
birthday?: Date;
roles: Array<string>; roles: Array<string>;
} }
type Permission = string; type Permission = string;
@ -25,10 +26,9 @@ declare namespace FG {
id: number; id: number;
time: Date; time: Date;
amount: number; amount: number;
reversal?: this; sender_id: string;
sender_id?: string; receiver_id: string;
receiver_id?: string; author_id: string;
author_id?: string;
} }
interface Event { interface Event {
id: number; id: number;

View File

@ -1,5 +1,8 @@
<template> <template>
<q-form @submit="save" @reset="reset"> <q-form
@submit="save"
@reset="reset"
>
<q-card-section class="fit row justify-start content-center items-center"> <q-card-section class="fit row justify-start content-center items-center">
<q-input <q-input
class="col-xs-12 col-sm-6 q-pa-sm" class="col-xs-12 col-sm-6 q-pa-sm"
@ -15,12 +18,12 @@
v-model="props.user.lastname" v-model="props.user.lastname"
filled filled
/> />
<q-input <q-input
class="col-xs-12 col-sm-6 q-pa-sm" class="col-xs-12 col-sm-6 q-pa-sm"
label="Benutzername" label="Angezeigter Name"
:readonly="!props.newUser" :rules="[notEmpty]"
v-model="props.user.userid" v-model="props.user.display_name"
:rules="[isUseridUsed, notEmpty]"
filled filled
/> />
<q-input <q-input
@ -32,9 +35,10 @@
/> />
<q-input <q-input
class="col-xs-12 col-sm-6 q-pa-sm" class="col-xs-12 col-sm-6 q-pa-sm"
label="Display Name" label="Benutzername"
:rules="[notEmpty]" :readonly="!props.newUser"
v-model="props.user.display_name" v-model="props.user.userid"
:rules="[isUseridUsed, notEmpty]"
filled filled
/> />
<q-select <q-select
@ -49,6 +53,10 @@
option-label="name" option-label="name"
option-value="name" option-value="name"
/> />
<IsoDateInput
v-model="props.user.birthday"
label="Geburtstag"
/>
</q-card-section> </q-card-section>
<q-separator v-if="!props.newUser" /> <q-separator v-if="!props.newUser" />
<q-card-section <q-card-section
@ -83,8 +91,15 @@
/> />
</q-card-section> </q-card-section>
<q-card-actions align="right"> <q-card-actions align="right">
<q-btn label="Reset" type="reset" /> <q-btn
<q-btn color="primary" type="submit" label="Speichern" /> label="Reset"
type="reset"
/>
<q-btn
color="primary"
type="submit"
label="Speichern"
/>
</q-card-actions> </q-card-actions>
</q-form> </q-form>
</template> </template>
@ -94,11 +109,12 @@ import {
computed, computed,
defineComponent, defineComponent,
ref, ref,
onBeforeMount onBeforeMount,
} from '@vue/composition-api'; } from '@vue/composition-api';
import { Store } from 'vuex'; import { Store } from 'vuex';
import { StateInterface } from 'src/store'; import { StateInterface } from 'src/store';
import { hasPermission } from 'src/components/permission'; import { hasPermission } from 'src/components/permission';
import IsoDateInput from 'src/components/utils/IsoDateInput.vue';
interface Props { interface Props {
user?: FG.User; user?: FG.User;
@ -107,19 +123,20 @@ interface Props {
export default defineComponent({ export default defineComponent({
name: 'MainUserSettings', name: 'MainUserSettings',
components: { IsoDateInput: IsoDateInput },
props: { props: {
user: { user: {
required: true required: true,
}, },
newUser: { newUser: {
default: false default: false,
} },
}, },
setup(props: Props, { root, emit }) { setup(props: Props, { root, emit }) {
const store = <Store<StateInterface>>root.$store; const store = <Store<StateInterface>>root.$store;
onBeforeMount(() => { onBeforeMount(() => {
store.dispatch('user/getRoles', false).catch(error => { store.dispatch('user/getRoles', false).catch((error) => {
console.warn(error); console.warn(error);
}); });
}); });
@ -133,13 +150,13 @@ export default defineComponent({
const oldUser = computed(() => { const oldUser = computed(() => {
if (isCurrentUser.value) return <FG.User>store.state.user.currentUser; if (isCurrentUser.value) return <FG.User>store.state.user.currentUser;
else else
return store.state.user.users.filter(user => { return store.state.user.users.filter((user) => {
user.userid === props.user?.userid; user.userid === props.user?.userid;
})[0]; })[0];
}); });
const allRoles = computed(() => const allRoles = computed(() =>
store.state.user.roles.map(role => role.name) store.state.user.roles.map((role) => role.name)
); );
const password = ref(''); const password = ref('');
const new_password = ref(''); const new_password = ref('');
@ -148,14 +165,13 @@ export default defineComponent({
function save() { function save() {
let changed = <FG.User>props.user; let changed = <FG.User>props.user;
changed = Object.assign(changed, { changed = Object.assign(changed, {
password: password.value password: password.value,
}); });
if (new_password.value != '') { if (new_password.value != '') {
changed = Object.assign(changed, { changed = Object.assign(changed, {
new_password: new_password.value new_password: new_password.value,
}); });
} }
console.log(changed);
emit('update:user', changed); emit('update:user', changed);
} }
@ -206,8 +222,8 @@ export default defineComponent({
notEmpty, notEmpty,
isUseridUsed, isUseridUsed,
save, save,
reset reset,
}; };
} },
}); });
</script> </script>

View File

@ -68,6 +68,8 @@ const actions: ActionTree<UserStateInterface, StateInterface> = {
axios axios
.get(`/users/${rootState.session.currentSession.userid}`) .get(`/users/${rootState.session.currentSession.userid}`)
.then((response: AxiosResponse<CurrentUserResponse>) => { .then((response: AxiosResponse<CurrentUserResponse>) => {
if (response.data.birthday)
response.data.birthday = new Date(response.data.birthday);
commit('setCurrentUser', response.data); commit('setCurrentUser', response.data);
commit('setCurrentPermissions', response.data.permissions); commit('setCurrentPermissions', response.data.permissions);
}) })
@ -87,6 +89,9 @@ const actions: ActionTree<UserStateInterface, StateInterface> = {
axios axios
.get('/users') .get('/users')
.then((response: AxiosResponse<FG.User[]>) => { .then((response: AxiosResponse<FG.User[]>) => {
response.data.forEach(user => {
if (user.birthday) user.birthday = new Date(user.birthday);
});
commit('setUsers', response.data); commit('setUsers', response.data);
}) })
.catch(err => { .catch(err => {