release v2.0.0 #4

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

View File

@ -0,0 +1,42 @@
<template>
<q-card class="12">
<q-card-section class="fit row justify-start content-center items-center">
<div class="col-xs-12 col-sm-6 text-center text-h6">
Neues Mitglied
</div>
</q-card-section>
<q-card-section>
<MainUserSettings :user="user" @update:user="setUser" :new-user="true" />
</q-card-section>
</q-card>
</template>
<script lang="ts">
import { defineComponent, ref } from '@vue/composition-api';
import MainUserSettings from 'src/plugins/user/components/settings/MainUserSettings.vue';
import { Store } from 'vuex';
import { StateInterface } from 'src/store';
export default defineComponent({
name: 'NewUser',
components: { MainUserSettings },
setup(_, { root }) {
const store = <Store<StateInterface>>root.$store;
const user = ref<FG.User>({
userid: '',
display_name: '',
firstname: '',
lastname: '',
mail: '',
roles: []
});
function setUser(value: FG.User) {
store.dispatch('user/setUser', value).catch(error => {
console.warn(error);
});
}
return { user, setUser };
}
});
</script>
<style scoped></style>

View File

@ -0,0 +1,50 @@
<template>
<q-card class="col-12">
<q-card-section class="fit row justify-start content-center items-center">
<div class="col-xs-12 col-sm-6 text-center text-h6">
Benutzereinstellungen
</div>
<div class="col-xs-12 col-sm-6 q-pa-sm">
<UserSelector :user="user" @update:user="userUpdated" />
</div>
</q-card-section>
<MainUserSettings :user="user" @update:user="updateUser" />
</q-card>
</template>
<script lang="ts">
import { defineComponent, ref } from '@vue/composition-api';
import { Store } from 'vuex';
import { StateInterface } from '../../../store';
import UserSelector from '../components/UserSelector.vue';
import MainUserSettings from '../components/settings/MainUserSettings.vue';
export default defineComponent({
name: 'UpdateUser',
components: { UserSelector, MainUserSettings },
setup(_, { root }) {
const store = <Store<StateInterface>>root.$store;
const user = ref(<FG.User>store.state.user.currentUser);
// can be dropped with VUE3
const userUpdated = (value: FG.User) => {
user.value = value;
console.log(value);
};
function updateUser(value: FG.User) {
store.dispatch('user/updateUser', value).catch(error => {
console.warn(error);
});
}
return {
user,
userUpdated,
updateUser
};
}
});
</script>
<style scoped></style>

View File

@ -19,8 +19,9 @@
<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="Benutzername"
readonly :readonly="!props.newUser"
:value="props.user.userid" v-model="props.user.userid"
:rules="[isUseridUsed, notEmpty]"
filled filled
/> />
<q-input <q-input
@ -50,8 +51,11 @@
option-value="name" option-value="name"
/> />
</q-card-section> </q-card-section>
<q-separator /> <q-separator v-if="!props.newUser" />
<q-card-section class="fit row justify-start content-center items-center"> <q-card-section
class="fit row justify-start content-center items-center"
v-if="!props.newUser"
>
<q-input <q-input
v-if="isCurrentUser" v-if="isCurrentUser"
class="col-xs-12 col-sm-6 col-md-4 q-pa-sm" class="col-xs-12 col-sm-6 col-md-4 q-pa-sm"
@ -99,12 +103,20 @@ import { hasPermission } from 'src/components/permission';
interface Props { interface Props {
user?: FG.User; user?: FG.User;
newUser?: boolean;
} }
export default defineComponent({ export default defineComponent({
name: 'MainUserSettings', name: 'MainUserSettings',
props: ['user'], props: {
setup(props: Props, { root }) { user: {
required: true
},
newUser: {
default: false
}
},
setup(props: Props, { root, emit }) {
const store = <Store<StateInterface>>root.$store; const store = <Store<StateInterface>>root.$store;
onBeforeMount(() => { onBeforeMount(() => {
@ -144,9 +156,9 @@ export default defineComponent({
new_password: new_password.value new_password: new_password.value
}); });
} }
store.dispatch('user/updateUser', changed).catch(error => { console.log(changed);
console.warn(error);
}); emit('update:user', changed);
} }
function reset() { function reset() {
@ -172,6 +184,16 @@ export default defineComponent({
); );
} }
function isUseridUsed(val: string) {
return (
!store.state.user.users.find((user: FG.User) => {
return user.userid == val;
}) ||
!props.newUser ||
'Benutzername ist schon vergeben'
);
}
const loading = computed(() => store.state.user.loading > 0); const loading = computed(() => store.state.user.loading > 0);
return { return {
@ -185,6 +207,7 @@ export default defineComponent({
isCurrentUser, isCurrentUser,
isEmail, isEmail,
notEmpty, notEmpty,
isUseridUsed,
save, save,
reset, reset,
loading loading

View File

@ -1,42 +1,52 @@
<template> <template>
<div> <div>
<q-tabs v-model="tab" v-if="$q.screen.gt.sm"> <q-tabs v-model="tab" v-if="$q.screen.gt.sm">
<q-tab v-for="(tabindex, index) in tabs" :key="'tab'+index" :name="tabindex.name" :label="tabindex.label"/> <q-tab
v-for="(tabindex, index) in tabs"
:key="'tab' + index"
:name="tabindex.name"
:label="tabindex.label"
/>
</q-tabs> </q-tabs>
<div class="fit row justify-end" v-else> <div class="fit row justify-end" v-else>
<q-btn flat round icon="mdi-menu" @click="showDrawer = !showDrawer"/> <q-btn flat round icon="mdi-menu" @click="showDrawer = !showDrawer" />
</div> </div>
<q-drawer side="right" v-model="showDrawer" @click="showDrawer = !showDrawer" behavior="mobile"> <q-drawer
side="right"
v-model="showDrawer"
@click="showDrawer = !showDrawer"
behavior="mobile"
>
<q-list v-model="tab"> <q-list v-model="tab">
<q-item v-for="(tabindex, index) in tabs" :key="'tab'+index" :active="tab == tabindex.name" clickable <q-item
@click="tab = tabindex.name"> v-for="(tabindex, index) in tabs"
:key="'tab' + index"
:active="tab == tabindex.name"
clickable
@click="tab = tabindex.name"
>
<q-item-label>{{ tabindex.label }}</q-item-label> <q-item-label>{{ tabindex.label }}</q-item-label>
</q-item> </q-item>
</q-list> </q-list>
</q-drawer> </q-drawer>
<q-page padding <q-page
class="fit row justify-center content-start items-start q-gutter-sm"> padding
<q-tab-panels v-model="tab" style="background-color: transparent;" class="q-ma-none q-pa-none" animated> class="fit row justify-center content-start items-start q-gutter-sm"
<q-tab-panel name="user">
<q-card class="col-12">
<q-card-section
class="fit row justify-start content-center items-center"
> >
<div class="col-xs-12 col-sm-6 text-center text-h6"> <q-tab-panels
Benutzereinstellungen v-model="tab"
</div> style="background-color: transparent;"
<div class="col-xs-12 col-sm-6 q-pa-sm"> class="q-ma-none q-pa-none"
<UserSelector :user="user" @update:user="userUpdated"/> animated
</div> >
</q-card-section> <q-tab-panel name="user">
<MainUserSettings :user="user"/> <UpdateUser />
</q-card>
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="newUser"> <q-tab-panel name="newUser">
<h1>hier kommt noch was</h1> <NewUser />
</q-tab-panel> </q-tab-panel>
<q-tab-panel name="roles"> <q-tab-panel name="roles">
<RoleSettings v-if="canEditRoles"/> <RoleSettings v-if="canEditRoles" />
</q-tab-panel> </q-tab-panel>
</q-tab-panels> </q-tab-panels>
</q-page> </q-page>
@ -50,19 +60,19 @@ import {
onBeforeMount, onBeforeMount,
ref ref
} from '@vue/composition-api'; } from '@vue/composition-api';
import UserSelector from '../components/UserSelector.vue';
import MainUserSettings from '../components/settings/MainUserSettings.vue';
import RoleSettings from '../components/settings/RoleSettings.vue'; import RoleSettings from '../components/settings/RoleSettings.vue';
import {Store} from 'vuex'; import UpdateUser from '../components/UpdateUser.vue';
import {StateInterface} from 'src/store'; import NewUser from '../components/NewUser.vue';
import {hasPermission} from 'src/components/permission'; import { Store } from 'vuex';
import {PERMISSIONS} from '../permissions'; import { StateInterface } from 'src/store';
import {Screen} from 'quasar'; import { hasPermission } from 'src/components/permission';
import { PERMISSIONS } from '../permissions';
import { Screen } from 'quasar';
export default defineComponent({ export default defineComponent({
name: 'AdminSettings', name: 'AdminSettings',
components: {UserSelector, MainUserSettings, RoleSettings}, components: { RoleSettings, UpdateUser, NewUser },
setup(_, {root}) { setup(_, { root }) {
const store = <Store<StateInterface>>root.$store; const store = <Store<StateInterface>>root.$store;
onBeforeMount(() => { onBeforeMount(() => {
@ -72,13 +82,6 @@ export default defineComponent({
const canEditRoles = computed(() => const canEditRoles = computed(() =>
hasPermission(PERMISSIONS.ROLES_EDIT, store) hasPermission(PERMISSIONS.ROLES_EDIT, store)
); );
const user = ref(<FG.User>store.state.user.currentUser);
// can be dropped with VUE3
const userUpdated = (value: FG.User) => {
user.value = value;
console.log(value);
};
interface Tab { interface Tab {
name: string; name: string;
@ -86,27 +89,25 @@ export default defineComponent({
} }
const tabs: Tab[] = [ const tabs: Tab[] = [
{name: 'user', label: 'Mitglieder'}, { name: 'user', label: 'Mitglieder' },
{name: 'newUser', label: 'Neues Mitglied'}, { name: 'newUser', label: 'Neues Mitglied' },
{name: 'roles', label: 'Rollen'} { name: 'roles', label: 'Rollen' }
] ];
const drawer = ref<boolean>(false) const drawer = ref<boolean>(false);
const showDrawer = computed({ const showDrawer = computed({
get: () => { get: () => {
return !Screen.gt.sm && drawer.value return !Screen.gt.sm && drawer.value;
}, },
set: (val: boolean) => { set: (val: boolean) => {
drawer.value = val drawer.value = val;
} }
}) });
const tab = ref<string>('user'); const tab = ref<string>('user');
return { return {
user,
userUpdated,
canEditRoles, canEditRoles,
showDrawer, showDrawer,
tab, tab,

View File

@ -11,7 +11,7 @@
> >
<div class="col-12 text-center text-h6">Benutzereinstellungen</div> <div class="col-12 text-center text-h6">Benutzereinstellungen</div>
</q-card-section> </q-card-section>
<MainUserSettings :user="currentUser" /> <MainUserSettings :user="currentUser" @update:user="updateUser" />
</q-card> </q-card>
<div class="col-12 text-left text-h6">Aktive Sessions:</div> <div class="col-12 text-left text-h6">Aktive Sessions:</div>
<sessions <sessions
@ -51,11 +51,17 @@ export default defineComponent({
const currentUser = ref(<FG.User>store.state.user.currentUser); const currentUser = ref(<FG.User>store.state.user.currentUser);
const sessions = computed(() => store.state.session.sessions); const sessions = computed(() => store.state.session.sessions);
const sessionsLoading = computed(() => store.state.session.loading); const sessionsLoading = computed(() => store.state.session.loading);
function updateUser(value: FG.User) {
store.dispatch('user/updateUser', value).catch(error => {
console.warn(error);
});
}
return { return {
currentUser, currentUser,
sessionsLoading, sessionsLoading,
sessions sessions,
updateUser
}; };
} }
}); });

View File

@ -103,6 +103,23 @@ const actions: ActionTree<UserStateInterface, StateInterface> = {
}); });
}, },
setUser({ commit, state, dispatch }, data: FG.User) {
commit('setLoading');
axios
.post(`users`, data)
.then(() => {
if (state.currentUser && state.currentUser.userid === data.userid)
void dispatch('getCurrentUser');
else void dispatch('getUsers');
})
.catch(error => {
console.warn(error);
})
.finally(() => {
commit('setLoading', false);
});
},
getRoles({ commit, state }, force = false) { getRoles({ commit, state }, force = false) {
if (!force && state.roles.length > 0) return; if (!force && state.roles.length > 0) return;
commit('setLoading'); commit('setLoading');