release v2.0.0 #4

Merged
crimsen merged 481 commits from develop into master 2024-01-18 15:15:08 +00:00
12 changed files with 194 additions and 200 deletions
Showing only changes of commit 78427aa5d2 - Show all commits

View File

@ -10,12 +10,11 @@
"lint": "eslint --ext .js,.ts,.vue ./" "lint": "eslint --ext .js,.ts,.vue ./"
}, },
"dependencies": { "dependencies": {
"@quasar/extras": "^1.9.15", "@quasar/extras": "^1.9.16",
"axios": "^0.21.1", "axios": "^0.21.1",
"cordova": "^10.0.0", "cordova": "^10.0.0",
"core-js": "^3.7.0", "core-js": "^3.7.0",
"quasar": "^2.0.0-beta.1", "quasar": "^2.0.0-beta.2"
"vue-router": "4.0.3"
}, },
"prettier": { "prettier": {
"singleQuote": true, "singleQuote": true,
@ -24,7 +23,7 @@
"arrowParens": "always" "arrowParens": "always"
}, },
"devDependencies": { "devDependencies": {
"@quasar/app": "^3.0.0-beta.1", "@quasar/app": "^3.0.0-beta.2",
"@quasar/quasar-app-extension-qcalendar": "^3.3.4", "@quasar/quasar-app-extension-qcalendar": "^3.3.4",
"@types/node": "^12.19.6", "@types/node": "^12.19.6",
"@types/webpack": "^4.41.26", "@types/webpack": "^4.41.26",

View File

@ -14,7 +14,7 @@ export default boot<UserSessionState>(({ router, store }) => {
// Secured area (LOGIN REQUIRED) // Secured area (LOGIN REQUIRED)
// Check login is ok // Check login is ok
if (!session || session.expires <= new Date()) { if (!session || session.expires <= new Date()) {
store.dispatch('session/logout').catch((error) => { store.dispatch('sessions/logout').catch((error) => {
console.warn(error); console.warn(error);
}); });
return; return;

View File

@ -298,10 +298,5 @@ export default boot<UserSessionState>(({ router, store, app }) => {
loadedPlugins.routes.forEach((route) => router.addRoute(route)); loadedPlugins.routes.forEach((route) => router.addRoute(route));
// save plugins in VM-variable // save plugins in VM-variable
<<<<<<< HEAD
console.log(store);
app.provide('flaschengeistPlugins', loadedPlugins);
=======
app.provide('flaschengeist', loadedPlugins); app.provide('flaschengeist', loadedPlugins);
>>>>>>> 3a1cb84... [Vue3] Fixed usage of plugins
}); });

View File

@ -9,22 +9,22 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, onBeforeMount } from 'vue'; import { computed, defineComponent, onBeforeMount } from 'vue';
import { UserBalance } from 'src/plugins/balance/store/balance'; import { UserBalance } from 'src/plugins/balance/store/balance';
import { mapGetters, Store, useStore } from 'vuex'; import { mapGetters, useStore } from 'vuex';
import { StateInterface } from 'src/store'; import { StateInterface } from 'src/store';
export default defineComponent({ export default defineComponent({
name: 'BalanceWidget', name: 'BalanceWidget',
setup() { setup() {
const store = useStore<StateInterface>();
const balanceGetters = mapGetters('balance', ['balances']);
const userGetters = mapGetters('users', ['currentUser']);
onBeforeMount(() => { onBeforeMount(() => {
store.dispatch('balance/getBalance').catch((err) => { store.dispatch('balance/getBalance').catch((err) => {
console.warn(err); console.warn(err);
}); });
}); });
const store = useStore<Store<StateInterface>>();
const balanceGetters = mapGetters('balance', ['balances']);
const userGetters = mapGetters('user', ['currentUser']);
const balance = computed( const balance = computed(
() => () =>
(<Map<string, UserBalance>>balanceGetters.balances()).get( (<Map<string, UserBalance>>balanceGetters.balances()).get(

View File

@ -129,7 +129,8 @@ export default defineComponent({
else { else {
if (row.receiver_id == null) return 'Angeschrieben'; if (row.receiver_id == null) return 'Angeschrieben';
else { else {
if (row.receiver_id === store.state.user.currentUser?.userid) return 'Bekommen von X'; if (row.receiver_id === (<FG.User>userGetters.currentUser())?.userid)
return 'Bekommen von X';
else return 'Gesendet an X'; else return 'Gesendet an X';
} }
} }

View File

@ -1,6 +1,6 @@
import { Module, MutationTree, ActionTree, GetterTree } from 'vuex'; import { Module, MutationTree, ActionTree, GetterTree } from 'vuex';
import { StateInterface } from 'src/store'; import { StateInterface } from 'src/store';
import { axios } from 'src/boot/axios'; import { api } from 'src/boot/axios';
import { AxiosResponse } from 'axios'; import { AxiosResponse } from 'axios';
interface BalanceResponse { interface BalanceResponse {
@ -94,24 +94,24 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
const sc = [...state.shortcuts, shortcut]; const sc = [...state.shortcuts, shortcut];
sc.sort(); sc.sort();
const user = <FG.User>rootState.user.currentUser; const user = <FG.User>rootState.users.currentUser;
return axios.put(`/users/${user.userid}/balance/shortcuts`, sc).then(() => { return api.put(`/users/${user.userid}/balance/shortcuts`, sc).then(() => {
commit('setShortcuts', sc); commit('setShortcuts', sc);
}); });
}, },
removeShortcut({ commit, state, rootState }, shortcut) { removeShortcut({ commit, state, rootState }, shortcut) {
const sc = state.shortcuts.filter((value: number) => value != shortcut); const sc = state.shortcuts.filter((value: number) => value != shortcut);
const user = <FG.User>rootState.user.currentUser; const user = <FG.User>rootState.users.currentUser;
return axios.put(`/users/${user.userid}/balance/shortcuts`, sc).then(() => { return api.put(`/users/${user.userid}/balance/shortcuts`, sc).then(() => {
commit('setShortcuts', sc); commit('setShortcuts', sc);
}); });
}, },
getShortcuts({ commit, state, rootState }, force = false) { getShortcuts({ commit, state, rootState }, force = false) {
if (force || state.shortcuts.length == 0) { if (force || state.shortcuts.length == 0) {
commit('setLoading'); commit('setLoading');
const user = <FG.User>rootState.user.currentUser; const user = <FG.User>rootState.users.currentUser;
return axios return api
.get(`/users/${user.userid}/balance/shortcuts`) .get(`/users/${user.userid}/balance/shortcuts`)
.then(({ data }: AxiosResponse<BalanceResponse>) => { .then(({ data }: AxiosResponse<BalanceResponse>) => {
commit('setShortcuts', data); commit('setShortcuts', data);
@ -122,8 +122,8 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
}, },
getBalance({ commit, rootState }, user: FG.User | undefined = undefined) { getBalance({ commit, rootState }, user: FG.User | undefined = undefined) {
commit('setLoading'); commit('setLoading');
if (!user) user = <FG.User>rootState.user.currentUser; if (!user) user = <FG.User>rootState.users.currentUser;
return axios return api
.get(`/users/${user.userid}/balance`) .get(`/users/${user.userid}/balance`)
.then(({ data }: AxiosResponse<BalanceResponse>) => { .then(({ data }: AxiosResponse<BalanceResponse>) => {
commit('setBalance', { userid: user?.userid, balance: data }); commit('setBalance', { userid: user?.userid, balance: data });
@ -132,7 +132,7 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
.finally(() => commit('setLoading', false)); .finally(() => commit('setLoading', false));
}, },
getBalances() { getBalances() {
return axios.get('/balance').then(({ data }: AxiosResponse<Array<BalancesResponse>>) => { return api.get('/balance').then(({ data }: AxiosResponse<Array<BalancesResponse>>) => {
return data; return data;
}); });
}, },
@ -151,9 +151,9 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
} }
) { ) {
commit('setLoading'); commit('setLoading');
if (!payload.userid) payload.userid = (<FG.User>rootState.user.currentUser).userid; if (!payload.userid) payload.userid = (<FG.User>rootState.users.currentUser).userid;
if (!payload.filter) payload.filter = { limit: 10 }; if (!payload.filter) payload.filter = { limit: 10 };
return axios return api
.get(`/users/${payload.userid}/balance/transactions`, { params: payload.filter || {} }) .get(`/users/${payload.userid}/balance/transactions`, { params: payload.filter || {} })
.then(({ data }: AxiosResponse<TransactionsResponse>) => { .then(({ data }: AxiosResponse<TransactionsResponse>) => {
data.transactions.forEach((t) => fixTransaction(t)); data.transactions.forEach((t) => fixTransaction(t));
@ -164,9 +164,9 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
}, },
getLimit({ rootState, commit }) { getLimit({ rootState, commit }) {
commit('setLoading'); commit('setLoading');
axios api
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */ /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
.get(`/users/${rootState.user.currentUser?.userid}/balance/limit`) .get(`/users/${rootState.users.currentUser?.userid}/balance/limit`)
.then(({ data }) => { .then(({ data }) => {
console.log(data); console.log(data);
}) })
@ -176,7 +176,7 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
.finally(() => commit('setLoading', false)); .finally(() => commit('setLoading', false));
}, },
revert({ dispatch, commit }, transaction: FG.Transaction) { revert({ dispatch, commit }, transaction: FG.Transaction) {
return axios return api
.delete(`/balance/${transaction.id}`) .delete(`/balance/${transaction.id}`)
.then(({ data }: AxiosResponse<FG.Transaction>) => { .then(({ data }: AxiosResponse<FG.Transaction>) => {
fixTransaction(data); fixTransaction(data);
@ -189,14 +189,14 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
data: { amount: number; user: string; sender?: string } data: { amount: number; user: string; sender?: string }
) { ) {
commit('setLoading'); commit('setLoading');
return axios return api
.put(`/users/${data.user}/balance`, data) .put(`/users/${data.user}/balance`, data)
.then((response: AxiosResponse<FG.Transaction>) => { .then((response: AxiosResponse<FG.Transaction>) => {
const transaction = response.data; const transaction = response.data;
fixTransaction(transaction); fixTransaction(transaction);
if ( if (
data.user == rootState.user.currentUser?.userid || data.user == rootState.users.currentUser?.userid ||
data.sender === rootState.user.currentUser?.userid data.sender === rootState.users.currentUser?.userid
) )
commit('addTransaction', transaction); commit('addTransaction', transaction);
commit(state.balances.has(data.user) ? 'changeBalance' : 'setBalance', { commit(state.balances.has(data.user) ? 'changeBalance' : 'setBalance', {

View File

@ -1,28 +1,27 @@
<template> <template>
<q-page padding> <q-page padding>
<q-card> <q-card>
<template>
<div style="max-width: 1800px; width: 100%"> <div style="max-width: 1800px; width: 100%">
<q-toolbar class="bg-primary text-white q-my-md shadow-2 items-center row justify-center"> <q-toolbar class="bg-primary text-white q-my-md shadow-2 items-center row justify-center">
<div class="row justify-center items-center"> <div class="row justify-center items-center">
<q-btn flat dense label="Prev" @click="calendarPrev" /> <q-btn flat dense label="Prev" @click="calendarPrev" />
<q-separator vertical /> <q-separator vertical />
<q-btn flat dense <q-btn flat dense
>{{ selectedDate | toMonth }} {{ selectedDate | toYear }} >{{ asMonth(selectedDate) }} {{ asYear(selectedDate) }}
<q-popup-proxy <q-popup-proxy
@before-show="updateProxy"
transition-show="scale" transition-show="scale"
transition-hide="scale" transition-hide="scale"
@before-show="updateProxy"
> >
<q-date v-model="proxyDate"> <q-date v-model="proxyDate">
<div class="row items-center justify-end q-gutter-sm"> <div class="row items-center justify-end q-gutter-sm">
<q-btn label="Cancel" color="primary" flat v-close-popup /> <q-btn v-close-popup label="Cancel" color="primary" flat />
<q-btn <q-btn
v-close-popup
label="OK" label="OK"
color="primary" color="primary"
flat flat
@click="saveNewSelectedDate(proxyDate)" @click="saveNewSelectedDate(proxyDate)"
v-close-popup
/> />
</div> </div>
</q-date> </q-date>
@ -34,8 +33,8 @@
<!-- <q-space /> --> <!-- <q-space /> -->
<q-btn-toggle <q-btn-toggle
class="row absolute-right"
v-model="calendarView" v-model="calendarView"
class="row absolute-right"
flat flat
stretch stretch
toggle-color="" toggle-color=""
@ -46,83 +45,56 @@
/> />
</q-toolbar> </q-toolbar>
<q-calendar <q-calendar
ref="calendar"
v-model="selectedDate" v-model="selectedDate"
:view="calendarView" :view="calendarView"
:weekdays="[1, 2, 3, 4, 5, 6, 0]" :weekdays="[1, 2, 3, 4, 5, 6, 0]"
locale="de-de" locale="de-de"
style="height: 100%; min-height: 400px" style="height: 100%; min-height: 400px"
ref="calendar"
> >
<template #day-body="{ timestamp }" style="min-height: 200px"> <template #day-body="{ timestamp }" style="min-height: 200px">
<template !v-if="getAgenda(timestamp)" style="min-height: 200px"> </template> <template v-if="!getAgenda(timestamp)" style="min-height: 200px"> </template>
<template v-for="agenda in getAgenda(timestamp)"> <template v-for="agenda in getAgenda(timestamp)" :key="agenda.id">
<eventslot :event="agenda" :key="agenda.id" /> <eventslot :event="agenda" />
</template> </template>
</template> </template>
</q-calendar> </q-calendar>
</div> </div>
</template>
</q-card> </q-card>
</q-page> </q-page>
</template> </template>
<script lang="ts"> <script lang="ts">
/* eslint-disable @typescript-eslint/no-unsafe-return */ import { computed, defineComponent, onBeforeMount, ref } from 'vue';
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ import { useStore } from 'vuex';
import { computed, defineComponent, onBeforeMount, ref } from '@vue/composition-api';
import { Store } from 'vuex';
import { StateInterface } from 'src/store';
import { ScheduleInterface } from '../../store/schedule'; import { ScheduleInterface } from '../../store/schedule';
import Eventslot from './slots/EventSlot.vue'; import Eventslot from './slots/EventSlot.vue';
import { date } from 'quasar'; import { date } from 'quasar';
export default defineComponent({ export default defineComponent({
name: 'AgendaView', name: 'AgendaView',
components: { Eventslot }, components: { Eventslot },
filters: {
toMonth: function (value: string) {
if (value) {
return date.formatDate(new Date(value), 'MMMM', {
months: [
'Januar',
'Februar',
'März',
'April',
'Mai',
'Juni',
'Juli',
'August',
'September',
'Oktober',
'November',
'Dezember',
],
});
}
},
toYear: function (value: string) {
if (value) {
return date.formatDate(new Date(value), 'YYYY');
}
},
},
setup(_, { root }) { setup() {
const store = <Store<StateInterface>>root.$store; const store = useStore();
// That looks evil
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const state = computed(() => <ScheduleInterface>store.state.schedule); const state = computed(() => <ScheduleInterface>store.state.schedule);
const selectedDate = ref(date.formatDate(new Date(), 'YYYY-MM-DD')); const selectedDate = ref(date.formatDate(new Date(), 'YYYY-MM-DD'));
const proxyDate = ref(''); const proxyDate = ref('');
const calendar = ref();
const calendarView = 'week-agenda'; const calendarView = 'week-agenda';
const events2 = computed(() => { const events2 = computed(() => {
let agenda: Agendas = {}; let agenda: Agendas = {};
// eslint-disable-next-line @typescript-eslint/no-unsafe-call // eslint-disable-next-line @typescript-eslint/no-unsafe-call
console.log('Hier Passiert was'); console.log('Hier Passiert was');
state.value.events state.value.events
.filter((event) => { .filter(event => {
const thisWeek = date.formatDate(new Date(selectedDate.value), 'w'); const thisWeek = date.formatDate(new Date(selectedDate.value), 'w');
console.log(thisWeek, date.formatDate(event.start, 'w')); console.log(thisWeek, date.formatDate(event.start, 'w'));
return date.formatDate(event.start, 'w') == thisWeek; return date.formatDate(event.start, 'w') == thisWeek;
}) })
.forEach((event) => { .forEach(event => {
let day = event.start.getDay(); let day = event.start.getDay();
console.log('event', event, day, !agenda[day]); console.log('event', event, day, !agenda[day]);
if (!agenda[day]) { if (!agenda[day]) {
@ -141,29 +113,56 @@ export default defineComponent({
onBeforeMount(() => { onBeforeMount(() => {
void store.dispatch('schedule/getEvents'); void store.dispatch('schedule/getEvents');
}); });
function getAgenda(this: any, day: { weekday: string }) { function getAgenda(day: { weekday: string }) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access return events2.value[parseInt(day.weekday, 10)];
return this.events2[parseInt(day.weekday, 10)];
} }
function calendarNext(this: any) { function calendarNext() {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call // eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call
return this.$refs.calendar.next(); return calendar.value.next();
} }
function calendarPrev(this: any) { function calendarPrev() {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call // eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call
return this.$refs.calendar.prev(); return calendar.value.prev();
} }
function updateProxy(this: any) { function updateProxy() {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
proxyDate.value = selectedDate.value; proxyDate.value = selectedDate.value;
} }
function saveNewSelectedDate(this: any) { function saveNewSelectedDate() {
proxyDate.value = date.formatDate(proxyDate.value, 'YYYY-MM-DD'); proxyDate.value = date.formatDate(proxyDate.value, 'YYYY-MM-DD');
selectedDate.value = proxyDate.value; selectedDate.value = proxyDate.value;
} }
function asMonth(value: string) {
if (value) {
return date.formatDate(new Date(value), 'MMMM', {
months: [
'Januar',
'Februar',
'März',
'April',
'Mai',
'Juni',
'Juli',
'August',
'September',
'Oktober',
'November',
'Dezember'
]
});
}
}
function asYear(value: string) {
if (value) {
return date.formatDate(new Date(value), 'YYYY');
}
}
return { return {
asYear,
asMonth,
calendar,
selectedDate, selectedDate,
events2, events2,
getAgenda, getAgenda,
@ -172,9 +171,9 @@ export default defineComponent({
updateProxy, updateProxy,
saveNewSelectedDate, saveNewSelectedDate,
proxyDate, proxyDate,
calendarView, calendarView
}; };
}, }
}); });
</script> </script>

View File

@ -14,11 +14,9 @@
</div> </div>
</header> </header>
<div v-for="(job, index) in event.jobs" v-bind:key="index"> <div v-for="(job, index) in event.jobs" :key="index">
<q-separator style="justify-start content-center" /> <q-separator style="justify-start content-center" />
<div class="text-weight-medium q-px-xs"> <div class="text-weight-medium q-px-xs">{{ asHour(job.start) }} - {{ asHour(job.end) }}</div>
{{ job.start | formatToHour }} - {{ job.end | formatToHour }}
</div>
<div class="q-px-xs"> <div class="q-px-xs">
{{ job.type.name }} {{ job.type.name }}
</div> </div>
@ -27,8 +25,9 @@
</div> </div>
<div> <div>
<q-select <q-select
filled :key="refreshKey"
v-model="job.services" v-model="job.services"
filled
:option-label="(opt) => userDisplay(opt)" :option-label="(opt) => userDisplay(opt)"
multiple multiple
disable disable
@ -39,26 +38,25 @@
style="font-size: 6px" style="font-size: 6px"
counter counter
:max-values="job.required_services" :max-values="job.required_services"
:key="refreshKey"
> >
</q-select> </q-select>
<div class="row col-12 justify-end"> <div class="row col-12 justify-end">
<q-btn v-if="false" /> <q-btn v-if="false" />
<q-btn <q-btn
v-if="!isUserEnrolled(job) && !jobFull(job)" v-if="!isUserEnrolled(job) && !jobFull(job)"
:key="refreshKey"
flat flat
color="primary" color="primary"
label="Eintragen" label="Eintragen"
@click="enrollForJob(job)" @click="enrollForJob(job)"
:key="refreshKey"
/> />
<q-btn <q-btn
v-if="isUserEnrolled(job)" v-if="isUserEnrolled(job)"
:key="refreshKey"
flat flat
color="negative" color="negative"
label="Austragen" label="Austragen"
@click="signOutFromJob(job)" @click="signOutFromJob(job)"
:key="refreshKey"
/> />
</div> </div>
</div> </div>
@ -68,22 +66,16 @@
<script lang="ts"> <script lang="ts">
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { defineComponent, ref, onBeforeMount } from '@vue/composition-api'; import { defineComponent, ref, onBeforeMount, PropType } from 'vue';
import { Store } from 'vuex'; import { useRouter } from 'vue-router';
import { useStore } from 'vuex';
import { StateInterface } from 'src/store'; import { StateInterface } from 'src/store';
import { date } from 'quasar'; import { date } from 'quasar';
import { asHour } from '../../../../../utils/datetime';
interface Props {
event: FG.Event;
}
export default defineComponent({ export default defineComponent({
name: 'Eventslot', name: 'Eventslot',
components: {}, components: {},
props: {
event: {
required: true,
},
},
filters: { filters: {
formatToHour: function (value: Date) { formatToHour: function (value: Date) {
if (value) { if (value) {
@ -91,16 +83,23 @@ export default defineComponent({
} }
}, },
}, },
props: {
event: {
required: true,
type: Object as PropType<FG.Event>,
},
},
setup(props: Props, { root, emit }) { setup(props) {
const store = <Store<StateInterface>>root.$store; const store = useStore<StateInterface>();
const state = store.state.user; const state = store.state.users;
const router = useRouter();
const availableUsers = null; const availableUsers = null;
const refreshKey = ref(0); const refreshKey = ref<number>(0);
const users = ref(state.users); const users = ref(state.users);
function refresh() { function refresh() {
root.$router.go(0); router.go(0);
refreshKey.value += 1; refreshKey.value += 1;
} }
onBeforeMount(() => { onBeforeMount(() => {
@ -122,7 +121,7 @@ export default defineComponent({
return state.users.find((user) => (user.userid = userid))?.display_name; return state.users.find((user) => (user.userid = userid))?.display_name;
} }
function enrollForJob(this: any, job: FG.Job) { function enrollForJob(job: FG.Job) {
console.log(job.services); console.log(job.services);
if (state.currentUser) { if (state.currentUser) {
const newService: FG.Service = { const newService: FG.Service = {
@ -132,7 +131,7 @@ export default defineComponent({
const newUserService = { user: newService }; const newUserService = { user: newService };
const UpdateInformation = { const UpdateInformation = {
eventId: <number>this.event.id, eventId: props.event.id,
JobId: job.id, JobId: job.id,
service: newUserService, service: newUserService,
}; };
@ -142,7 +141,7 @@ export default defineComponent({
} }
refresh(); refresh();
} }
function signOutFromJob(this: any, job: FG.Job) { function signOutFromJob(job: FG.Job) {
console.log(job.services); console.log(job.services);
if (state.currentUser) { if (state.currentUser) {
const newService: FG.Service = { const newService: FG.Service = {
@ -152,7 +151,7 @@ export default defineComponent({
const newUserService = { user: newService }; const newUserService = { user: newService };
const UpdateInformation = { const UpdateInformation = {
eventId: <number>this.event.id, eventId: props.event.id,
JobId: job.id, JobId: job.id,
service: newUserService, service: newUserService,
}; };
@ -174,6 +173,7 @@ export default defineComponent({
jobFull, jobFull,
userDisplay, userDisplay,
refresh, refresh,
asHour,
}; };
}, },
}); });

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<q-tabs v-model="tab" v-if="$q.screen.gt.sm"> <q-tabs v-if="$q.screen.gt.sm" v-model="tab">
<q-tab <q-tab
v-for="(tabindex, index) in tabs" v-for="(tabindex, index) in tabs"
:key="'tab' + index" :key="'tab' + index"
@ -8,10 +8,10 @@
:label="tabindex.label" :label="tabindex.label"
/> />
</q-tabs> </q-tabs>
<div class="fit row justify-end" v-else> <div v-else class="fit row justify-end">
<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 v-model="showDrawer" side="right" behavior="mobile" @click="showDrawer = !showDrawer">
<q-list v-model="tab"> <q-list v-model="tab">
<q-item <q-item
v-for="(tabindex, index) in tabs" v-for="(tabindex, index) in tabs"
@ -46,13 +46,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, ref } from '@vue/composition-api'; import { computed, defineComponent, ref } from 'vue';
import Eventtypes from '../components/management/Eventtypes.vue'; import Eventtypes from '../components/management/Eventtypes.vue';
import JobTypes from '../components/management/JobTypes.vue'; import JobTypes from '../components/management/JobTypes.vue';
import CreateEvent from '../components/management/CreateEvent.vue'; //import CreateEvent from '../components/management/CreateEvent.vue';
import AgendaView from '../components/overview/AgendaView.vue'; import AgendaView from '../components/overview/AgendaView.vue';
import { Store } from 'vuex';
import { StateInterface } from 'src/store';
import { hasPermission } from 'src/utils/permission'; import { hasPermission } from 'src/utils/permission';
import { PERMISSIONS } from '../permissions'; import { PERMISSIONS } from '../permissions';
import { Screen } from 'quasar'; import { Screen } from 'quasar';
@ -60,10 +58,8 @@ import { Screen } from 'quasar';
export default defineComponent({ export default defineComponent({
name: 'EventOverview', name: 'EventOverview',
components: { AgendaView, Eventtypes, JobTypes }, components: { AgendaView, Eventtypes, JobTypes },
setup(_, { root }) { setup() {
const store = <Store<StateInterface>>root.$store; const canEditRoles = computed(() => hasPermission(PERMISSIONS.ROLES_EDIT));
const canEditRoles = computed(() => hasPermission(PERMISSIONS.ROLES_EDIT, store));
interface Tab { interface Tab {
name: string; name: string;
@ -71,7 +67,7 @@ export default defineComponent({
} }
const tabs: Tab[] = [ const tabs: Tab[] = [
{ name: 'agendaView', label: 'Kalendar' }, { name: 'agendaView', label: 'Kalendar' }
// { name: 'eventtypes', label: 'Veranstaltungsarten' }, // { name: 'eventtypes', label: 'Veranstaltungsarten' },
// { name: 'jobtypes', label: 'Dienstarten' } // { name: 'jobtypes', label: 'Dienstarten' }
]; ];
@ -84,7 +80,7 @@ export default defineComponent({
}, },
set: (val: boolean) => { set: (val: boolean) => {
drawer.value = val; drawer.value = val;
}, }
}); });
const tab = ref<string>('agendaView'); const tab = ref<string>('agendaView');
@ -93,8 +89,8 @@ export default defineComponent({
canEditRoles, canEditRoles,
showDrawer, showDrawer,
tab, tab,
tabs, tabs
}; };
}, }
}); });
</script> </script>

View File

@ -4,8 +4,8 @@ import { UserStateInterface } from 'src/plugins/user/store/user';
import { SessionStateInterface } from 'src/plugins/user/store/session'; import { SessionStateInterface } from 'src/plugins/user/store/session';
export interface StateInterface { export interface StateInterface {
user: UserStateInterface; users: UserStateInterface;
session: SessionStateInterface; sessions: SessionStateInterface;
[key: string]: unknown; [key: string]: unknown;
} }

View File

@ -16,3 +16,7 @@ export function formatDateTime(
}); });
return dateTimeFormat.format(date); return dateTimeFormat.format(date);
} }
export function asHour(date: Date) {
return formatDateTime(date, false, true);
}

View File

@ -1005,10 +1005,10 @@
resolved "https://registry.yarnpkg.com/@positron/stack-trace/-/stack-trace-1.0.0.tgz#14fcc712a530038ef9be1ce6952315a839f466a8" resolved "https://registry.yarnpkg.com/@positron/stack-trace/-/stack-trace-1.0.0.tgz#14fcc712a530038ef9be1ce6952315a839f466a8"
integrity sha1-FPzHEqUwA475vhzmlSMVqDn0Zqg= integrity sha1-FPzHEqUwA475vhzmlSMVqDn0Zqg=
"@quasar/app@^3.0.0-beta.1": "@quasar/app@^3.0.0-beta.2":
version "3.0.0-beta.1" version "3.0.0-beta.2"
resolved "https://registry.yarnpkg.com/@quasar/app/-/app-3.0.0-beta.1.tgz#006a8c8880d9d8e70b4a2de0d26eac29c95a1388" resolved "https://registry.yarnpkg.com/@quasar/app/-/app-3.0.0-beta.2.tgz#650d94be2fad351544b54e2c5e85b06ca7e7e9f9"
integrity sha512-awQnaMcCGQ4BL838oBnBwCwh7n+olqZzhp32m/J3TEzz2VQlqJzzfKAHAIkcy17ICA+HoymTL+U7ZYOs36QwAg== integrity sha512-pX30q3yg3Qjp9MkQJmdtdA10GURg5eL/ENzJf70FcseN38kbfDQTG15CwraE+uS2ORDfs0g5qIuEl1DwFH+3pw==
dependencies: dependencies:
"@quasar/babel-preset-app" "2.0.1" "@quasar/babel-preset-app" "2.0.1"
"@quasar/fastclick" "1.1.4" "@quasar/fastclick" "1.1.4"
@ -1111,10 +1111,10 @@
core-js "^3.6.5" core-js "^3.6.5"
core-js-compat "^3.6.5" core-js-compat "^3.6.5"
"@quasar/extras@^1.9.15": "@quasar/extras@^1.9.16":
version "1.9.15" version "1.9.16"
resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.9.15.tgz#bfc22bf4edcb079820dea248c06fe21f73221262" resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.9.16.tgz#015c6bea60e42c2e4fb6cd6892567190f78c4c91"
integrity sha512-dm2oztROc3PgjieMEMAaqEcJ6ZC6PUGIZQet/eP2p/2vJTPwcyzhCGTBWoRJzEjOKoQeIJzM+F5diMhCaFFksA== integrity sha512-qr2Odjc3y3s71yAfhcHYc+LnHVEQR/4ibdpB7TRSL9+Sn7tHxx7p5kkogzrs4/GzpZGlBNvbj4KaFRNyMFv0aQ==
"@quasar/fastclick@1.1.4": "@quasar/fastclick@1.1.4":
version "1.1.4" version "1.1.4"
@ -8198,10 +8198,10 @@ qs@~6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
quasar@^2.0.0-beta.1: quasar@^2.0.0-beta.2:
version "2.0.0-beta.1" version "2.0.0-beta.2"
resolved "https://registry.yarnpkg.com/quasar/-/quasar-2.0.0-beta.1.tgz#297ee1f4760f11ea10fc5be53389e80d90225323" resolved "https://registry.yarnpkg.com/quasar/-/quasar-2.0.0-beta.2.tgz#eeedad6190eea60799a7710f33f8ad0b481b47fe"
integrity sha512-jUH76ha2Rc4InHTiU12V1v5TBKwUSdecX4ZSFAB+tX0CaFQudpNOxdQSSmllhxRe9np3tjGQ4CemKrlZNb4QPw== integrity sha512-Xy7Av0bHSASHRG4IZ0tz1lu6/6844SmeQQ6KJrHb0C5EC1MS+kLkgU8+1rx0I5daHgDo2RnQt+K/e16DpB1Hqg==
query-string@^4.1.0: query-string@^4.1.0:
version "4.3.4" version "4.3.4"
@ -10079,7 +10079,7 @@ vue-loader@^16.1.2:
hash-sum "^2.0.0" hash-sum "^2.0.0"
loader-utils "^2.0.0" loader-utils "^2.0.0"
vue-router@4.0.3, vue-router@^4.0.1: vue-router@^4.0.1:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.3.tgz#8b26050c88b2dec7e27a88835f71046b365823ec" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.3.tgz#8b26050c88b2dec7e27a88835f71046b365823ec"
integrity sha512-AD1OjtVPyQHTSpoRsEGfPpxRQwhAhxcacOYO3zJ3KNkYP/r09mileSp6kdMQKhZWP2cFsPR3E2M3PZguSN5/ww== integrity sha512-AD1OjtVPyQHTSpoRsEGfPpxRQwhAhxcacOYO3zJ3KNkYP/r09mileSp6kdMQKhZWP2cFsPR3E2M3PZguSN5/ww==