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 ./"
},
"dependencies": {
"@quasar/extras": "^1.9.15",
"@quasar/extras": "^1.9.16",
"axios": "^0.21.1",
"cordova": "^10.0.0",
"core-js": "^3.7.0",
"quasar": "^2.0.0-beta.1",
"vue-router": "4.0.3"
"quasar": "^2.0.0-beta.2"
},
"prettier": {
"singleQuote": true,
@ -24,7 +23,7 @@
"arrowParens": "always"
},
"devDependencies": {
"@quasar/app": "^3.0.0-beta.1",
"@quasar/app": "^3.0.0-beta.2",
"@quasar/quasar-app-extension-qcalendar": "^3.3.4",
"@types/node": "^12.19.6",
"@types/webpack": "^4.41.26",

View File

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

View File

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

View File

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

View File

@ -129,7 +129,8 @@ export default defineComponent({
else {
if (row.receiver_id == null) return 'Angeschrieben';
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';
}
}

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
<template>
<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
v-for="(tabindex, index) in tabs"
:key="'tab' + index"
@ -8,10 +8,10 @@
:label="tabindex.label"
/>
</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" />
</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-item
v-for="(tabindex, index) in tabs"
@ -46,13 +46,11 @@
</template>
<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 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 { Store } from 'vuex';
import { StateInterface } from 'src/store';
import { hasPermission } from 'src/utils/permission';
import { PERMISSIONS } from '../permissions';
import { Screen } from 'quasar';
@ -60,10 +58,8 @@ import { Screen } from 'quasar';
export default defineComponent({
name: 'EventOverview',
components: { AgendaView, Eventtypes, JobTypes },
setup(_, { root }) {
const store = <Store<StateInterface>>root.$store;
const canEditRoles = computed(() => hasPermission(PERMISSIONS.ROLES_EDIT, store));
setup() {
const canEditRoles = computed(() => hasPermission(PERMISSIONS.ROLES_EDIT));
interface Tab {
name: string;
@ -71,7 +67,7 @@ export default defineComponent({
}
const tabs: Tab[] = [
{ name: 'agendaView', label: 'Kalendar' },
{ name: 'agendaView', label: 'Kalendar' }
// { name: 'eventtypes', label: 'Veranstaltungsarten' },
// { name: 'jobtypes', label: 'Dienstarten' }
];
@ -84,7 +80,7 @@ export default defineComponent({
},
set: (val: boolean) => {
drawer.value = val;
},
}
});
const tab = ref<string>('agendaView');
@ -93,8 +89,8 @@ export default defineComponent({
canEditRoles,
showDrawer,
tab,
tabs,
tabs
};
},
}
});
</script>

View File

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

View File

@ -16,3 +16,7 @@ export function formatDateTime(
});
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"
integrity sha1-FPzHEqUwA475vhzmlSMVqDn0Zqg=
"@quasar/app@^3.0.0-beta.1":
version "3.0.0-beta.1"
resolved "https://registry.yarnpkg.com/@quasar/app/-/app-3.0.0-beta.1.tgz#006a8c8880d9d8e70b4a2de0d26eac29c95a1388"
integrity sha512-awQnaMcCGQ4BL838oBnBwCwh7n+olqZzhp32m/J3TEzz2VQlqJzzfKAHAIkcy17ICA+HoymTL+U7ZYOs36QwAg==
"@quasar/app@^3.0.0-beta.2":
version "3.0.0-beta.2"
resolved "https://registry.yarnpkg.com/@quasar/app/-/app-3.0.0-beta.2.tgz#650d94be2fad351544b54e2c5e85b06ca7e7e9f9"
integrity sha512-pX30q3yg3Qjp9MkQJmdtdA10GURg5eL/ENzJf70FcseN38kbfDQTG15CwraE+uS2ORDfs0g5qIuEl1DwFH+3pw==
dependencies:
"@quasar/babel-preset-app" "2.0.1"
"@quasar/fastclick" "1.1.4"
@ -1111,10 +1111,10 @@
core-js "^3.6.5"
core-js-compat "^3.6.5"
"@quasar/extras@^1.9.15":
version "1.9.15"
resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.9.15.tgz#bfc22bf4edcb079820dea248c06fe21f73221262"
integrity sha512-dm2oztROc3PgjieMEMAaqEcJ6ZC6PUGIZQet/eP2p/2vJTPwcyzhCGTBWoRJzEjOKoQeIJzM+F5diMhCaFFksA==
"@quasar/extras@^1.9.16":
version "1.9.16"
resolved "https://registry.yarnpkg.com/@quasar/extras/-/extras-1.9.16.tgz#015c6bea60e42c2e4fb6cd6892567190f78c4c91"
integrity sha512-qr2Odjc3y3s71yAfhcHYc+LnHVEQR/4ibdpB7TRSL9+Sn7tHxx7p5kkogzrs4/GzpZGlBNvbj4KaFRNyMFv0aQ==
"@quasar/fastclick@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"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
quasar@^2.0.0-beta.1:
version "2.0.0-beta.1"
resolved "https://registry.yarnpkg.com/quasar/-/quasar-2.0.0-beta.1.tgz#297ee1f4760f11ea10fc5be53389e80d90225323"
integrity sha512-jUH76ha2Rc4InHTiU12V1v5TBKwUSdecX4ZSFAB+tX0CaFQudpNOxdQSSmllhxRe9np3tjGQ4CemKrlZNb4QPw==
quasar@^2.0.0-beta.2:
version "2.0.0-beta.2"
resolved "https://registry.yarnpkg.com/quasar/-/quasar-2.0.0-beta.2.tgz#eeedad6190eea60799a7710f33f8ad0b481b47fe"
integrity sha512-Xy7Av0bHSASHRG4IZ0tz1lu6/6844SmeQQ6KJrHb0C5EC1MS+kLkgU8+1rx0I5daHgDo2RnQt+K/e16DpB1Hqg==
query-string@^4.1.0:
version "4.3.4"
@ -10079,7 +10079,7 @@ vue-loader@^16.1.2:
hash-sum "^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"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.3.tgz#8b26050c88b2dec7e27a88835f71046b365823ec"
integrity sha512-AD1OjtVPyQHTSpoRsEGfPpxRQwhAhxcacOYO3zJ3KNkYP/r09mileSp6kdMQKhZWP2cFsPR3E2M3PZguSN5/ww==