migrate to vue 3
This commit is contained in:
parent
bb07a6b641
commit
bb71c44aa7
16 changed files with 318 additions and 432 deletions
|
@ -1,43 +1,39 @@
|
|||
{
|
||||
"name": "c3cloc",
|
||||
"name": "c3lf",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"serve": "vue-cli-service serve --modern",
|
||||
"build": "vue-cli-service build --modern",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.25",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.11.2",
|
||||
"@fortawesome/vue-fontawesome": "^0.1.8",
|
||||
"axios": "^1.6.2",
|
||||
"base-64": "^0.1.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/vue-fontawesome": "^3.0.6",
|
||||
"base-64": "^1.0.0",
|
||||
"bootstrap": "^4.3.1",
|
||||
"core-js": "^3.3.2",
|
||||
"core-js": "^3.35.1",
|
||||
"jquery": "^3.4.1",
|
||||
"lodash": "^4.17.15",
|
||||
"luxon": "^1.21.3",
|
||||
"popper.js": "^1.16.0",
|
||||
"popper.js": "^1.16.1",
|
||||
"ramda": "^0.26.1",
|
||||
"sass": "^1.19.0",
|
||||
"sass-loader": "^10.4.1",
|
||||
"utf8": "^3.0.0",
|
||||
"vue": "^2.6.10",
|
||||
"vue-debounce": "^2.2.0",
|
||||
"vue-qrcode-component": "^2.1.1",
|
||||
"vue-router": "^3.1.3",
|
||||
"vuex": "^3.1.2",
|
||||
"vuex-router-sync": "^5.0.0",
|
||||
"vuex-shared-mutations": "^1.0.2",
|
||||
"vue": "^3.2.47",
|
||||
"vue-router": "^4.1.6",
|
||||
"vuex": "^4.1.0",
|
||||
"yarn": "^1.22.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^5.0.8",
|
||||
"@vue/cli-service": "^5.0.8",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
"webpack": "^5"
|
||||
"webpack": "^5",
|
||||
"webpack-dev-server": "^4.15.1"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
|
|
@ -5,40 +5,30 @@
|
|||
<AddBoxModal v-if="showAddBoxModal && isLoggedIn" @close="closeAddBoxModal()" isModal="true"/>
|
||||
<Navbar v-if="isLoggedIn" @addItemClicked="openAddItemModal()" @addTicketClicked="openAddTicketModal()"/>
|
||||
<router-view/>
|
||||
<div aria-live="polite" aria-atomic="true" v-if="isLoggedIn"
|
||||
class="d-flex justify-content-end align-items-start fixed-top mx-1 my-5 py-3"
|
||||
style="min-height: 200px; z-index: 100000; pointer-events: none">
|
||||
<Toast v-for="(toast , index) in toasts" :key="index" :title="toast.title" :message="toast.message"
|
||||
:color="toast.color"
|
||||
@close="removeToast(toast.key)" style="pointer-events: auto"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Navbar from '@/components/Navbar';
|
||||
import AddItemModal from '@/components/AddItemModal';
|
||||
import Toast from './components/Toast';
|
||||
import {mapState, mapMutations, mapActions, mapGetters} from 'vuex';
|
||||
import AddTicketModal from "@/components/AddTicketModal.vue";
|
||||
import AddBoxModal from "@/components/AddBoxModal.vue";
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {AddBoxModal, Toast, Navbar, AddItemModal, AddTicketModal},
|
||||
components: {AddBoxModal, Navbar, AddItemModal, AddTicketModal},
|
||||
computed: {
|
||||
...mapState(['loadedItems', 'layout', 'toasts', 'showAddBoxModal']),
|
||||
...mapGetters(['isLoggedIn']),
|
||||
},
|
||||
data: () => ({
|
||||
addItemModalOpen: false,
|
||||
addTicketModalOpen: false,
|
||||
notify_socket: null,
|
||||
socket_toast: null,
|
||||
addTicketModalOpen: false
|
||||
}),
|
||||
methods: {
|
||||
...mapMutations(['removeToast', 'createToast', 'closeAddBoxModal', 'openAddBoxModal']),
|
||||
...mapActions(['loadEventItems', 'loadTickets']),
|
||||
...mapActions(['loadEvents']),
|
||||
openAddItemModal() {
|
||||
this.addItemModalOpen = true;
|
||||
},
|
||||
|
@ -50,72 +40,10 @@ export default {
|
|||
},
|
||||
closeAddTicketModal() {
|
||||
this.addTicketModalOpen = false;
|
||||
},
|
||||
tryConnect() {
|
||||
if (!this.notify_socket || this.notify_socket.readyState !== WebSocket.OPEN) {
|
||||
//if (this.socket_toast) {
|
||||
// this.removeToast(this.socket_toast.key);
|
||||
// this.socket_toast = null;
|
||||
//}
|
||||
//this.socket_toast = this.createToast({
|
||||
// title: "Connecting...",
|
||||
// message: "Connecting to websocket...",
|
||||
// color: "warning"
|
||||
//});
|
||||
const scheme = window.location.protocol === "https:" ? "wss" : "ws";
|
||||
this.notify_socket = new WebSocket(scheme + '://' + window.location.host + '/ws/2/notify/');
|
||||
this.notify_socket.onopen = (e) => {
|
||||
//if (this.socket_toast) {
|
||||
// this.removeToast(this.socket_toast.key);
|
||||
// this.socket_toast = null;
|
||||
//}
|
||||
//this.socket_toast = this.createToast({
|
||||
// title: "Connection established",
|
||||
// message: JSON.stringify(e),
|
||||
// color: "success"
|
||||
//});
|
||||
//console.log(e);
|
||||
};
|
||||
this.notify_socket.onclose = (e) => {
|
||||
//if (this.socket_toast) {
|
||||
// this.removeToast(this.socket_toast.key);
|
||||
// this.socket_toast = null;
|
||||
//}
|
||||
//this.socket_toast = this.createToast({
|
||||
// title: "Connection closed",
|
||||
// message: JSON.stringify(e),
|
||||
// color: "danger"
|
||||
//});
|
||||
//console.log(e);
|
||||
setTimeout(() => {
|
||||
this.tryConnect();
|
||||
}, 1000);
|
||||
};
|
||||
this.notify_socket.onerror = (e) => {
|
||||
//if (this.socket_toast) {
|
||||
// this.removeToast(this.socket_toast.key);
|
||||
// this.socket_toast = null;
|
||||
//}
|
||||
//this.socket_toast = this.createToast({
|
||||
// title: "Connection error",
|
||||
// message: JSON.stringify(e),
|
||||
// color: "danger"
|
||||
//});
|
||||
//console.log(e);
|
||||
setTimeout(() => {
|
||||
this.tryConnect();
|
||||
}, 1000);
|
||||
};
|
||||
this.notify_socket.onmessage = (e) => {
|
||||
let data = JSON.parse(e.data);
|
||||
this.loadEventItems()
|
||||
this.loadTickets()
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
created: function () {
|
||||
this.tryConnect();
|
||||
document.title = document.location.hostname;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
<script>
|
||||
import Modal from '@/components/Modal';
|
||||
import EditItem from '@/components/EditItem';
|
||||
import {mapActions, mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: 'AddItemModal',
|
||||
|
@ -23,12 +24,16 @@ export default {
|
|||
data: () => ({
|
||||
item: {}
|
||||
}),
|
||||
computed: {
|
||||
...mapState(['lastUsed'])
|
||||
},
|
||||
created() {
|
||||
this.item = {box: this.$store.state.lastUsed.box || '', cid: this.$store.state.lastUsed.cid || ''};
|
||||
this.item = {box: this.lastUsed.box || '', cid: this.lastUsed.cid || ''};
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['postItem']),
|
||||
saveNewItem() {
|
||||
this.$store.dispatch('postItem', this.item).then(() => {
|
||||
this.postItem(this.item).then(() => {
|
||||
this.$emit('close');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {mapActions} from 'vuex';
|
||||
import Modal from '@/components/Modal';
|
||||
import EditItem from '@/components/EditItem';
|
||||
|
||||
|
@ -32,11 +33,12 @@ export default {
|
|||
}
|
||||
}),
|
||||
created() {
|
||||
this.ticket = {box: this.$store.state.lastUsed.box || '', cid: this.$store.state.lastUsed.cid || ''};
|
||||
this.ticket = {};
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['postManualTicket']),
|
||||
saveNewTicket() {
|
||||
this.$store.dispatch('postManualTicket', this.ticket).then(() => {
|
||||
this.postManualTicket(this.ticket).then(() => {
|
||||
this.$emit('close');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,31 +1,6 @@
|
|||
<template>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-xl-2">
|
||||
<!--div class="card bg-dark text-light mb-2" id="filters">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-info">Sort & Filter</h5>
|
||||
<div class="form-group" v-for="(column, index) in columns" :key="index">
|
||||
<label>{{ column }}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button
|
||||
:class="[ 'btn', column === sortBy ? 'btn-outline-info' : 'btn-outline-secondary' ]"
|
||||
type="button"
|
||||
@click="toggleSort(column)">
|
||||
<font-awesome-icon :icon="getSortIcon(column)"/>
|
||||
</button>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="filter"
|
||||
:value="filters[column]"
|
||||
@input="changeFilter(column, $event.target.value)"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div-->
|
||||
</div>
|
||||
<div class="col-lg-9 col-xl-8">
|
||||
<div class="w-100"
|
||||
|
@ -48,6 +23,8 @@
|
|||
|
||||
<script>
|
||||
|
||||
import {mapGetters} from "vuex";
|
||||
|
||||
export default {
|
||||
name: 'CollapsableCards',
|
||||
props: {
|
||||
|
@ -75,25 +52,18 @@ export default {
|
|||
};
|
||||
},
|
||||
created() {
|
||||
const query = this.$router.currentRoute.query.collapsed;
|
||||
const query = this.$router.currentRoute ? (this.$router.currentRoute.query ? this.$router.currentRoute.query.collapsed : null) : null;
|
||||
if (query !== null && query !== undefined) {
|
||||
this.collapsed = this.unpackInt(parseInt(query), this.sections.length);
|
||||
} else {
|
||||
this.collapsed = this.sections.map(() => true);
|
||||
}
|
||||
|
||||
//this.$router.push({...this.$router.currentRoute, query: {...this.$router.currentRoute.query, layout}});
|
||||
//this.collapsed = this.sections.map(() => true);
|
||||
/*this.columns.map(e => ({
|
||||
k: e,
|
||||
v: this.$store.getters.getFilters[e]
|
||||
})).filter(e => e.v).forEach(e => this.setFilter(e.k, e.v));*/
|
||||
},
|
||||
computed: {
|
||||
grouped_items() {
|
||||
return this.sections.map(section => this.items.filter(item => item[this.keyName] === section.slug));
|
||||
},
|
||||
|
||||
...mapGetters(['route']),
|
||||
},
|
||||
methods: {
|
||||
packInt(arr) {
|
||||
|
@ -112,8 +82,11 @@ export default {
|
|||
collapsed: {
|
||||
handler() {
|
||||
const encoded = this.packInt(this.collapsed).toString()
|
||||
if (this.$router.currentRoute.query.collapsed !== encoded)
|
||||
this.$router.push({...this.$router.currentRoute, query: {...this.$router.currentRoute.query, collapsed: encoded}});
|
||||
if (this.route.query.collapsed !== encoded)
|
||||
this.$router.push({
|
||||
...this.$router.currentRoute,
|
||||
query: {...this.$router.currentRoute.query, collapsed: encoded}
|
||||
});
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
|
|
|
@ -119,13 +119,13 @@ export default {
|
|||
emits: ['addItemClicked', 'addTicketClicked'],
|
||||
computed: {
|
||||
...mapState(['events']),
|
||||
...mapGetters(['getEventSlug', 'getActiveView', "checkPermission", "hasPermissions", "layout"]),
|
||||
...mapGetters(['getEventSlug', 'getActiveView', "checkPermission", "hasPermissions", "layout", "route"]),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['changeEvent', 'changeView', 'searchEventItems']),
|
||||
...mapMutations(['logout']),
|
||||
navigateTo(link) {
|
||||
if (this.$router.currentRoute.path !== link)
|
||||
if (this.route.path !== link)
|
||||
this.$router.push(link);
|
||||
},
|
||||
isItemView() {
|
||||
|
@ -135,9 +135,9 @@ export default {
|
|||
return this.getActiveView === 'tickets' || this.getActiveView === 'ticket';
|
||||
},
|
||||
setLayout(layout) {
|
||||
if (this.$router.currentRoute.query.layout === layout)
|
||||
if (this.route.query.layout === layout)
|
||||
return;
|
||||
this.$router.push({...this.$router.currentRoute, query: {...this.$router.currentRoute.query, layout}});
|
||||
this.$router.push({...this.route, query: {...this.route.query, layout}});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
<template>
|
||||
<div class="toast" :class="color && ('border-' + color)" role="alert" ref="toast" data-autohide="false">
|
||||
<div class="toast-header" :class="[color && ('bg-' + color), color && 'text-light']">
|
||||
<strong class="mr-auto pr-3">{{ title }}</strong>
|
||||
<small>{{ displayTime }}</small>
|
||||
<button type="button" class="ml-2 mb-1 close" @click="close()">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="toast-body" v-html="message">{{ message }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
import 'bootstrap/js/dist/toast';
|
||||
import {DateTime} from 'luxon';
|
||||
|
||||
export default {
|
||||
name: 'Toast',
|
||||
props: ['title', 'message', 'color'],
|
||||
data: () => ({
|
||||
creationTime: DateTime.local(),
|
||||
displayTime: 'just now',
|
||||
timer: undefined
|
||||
}),
|
||||
mounted() {
|
||||
const {toast} = this.$refs;
|
||||
$(toast).toast('show');
|
||||
this.timer = setInterval(this.updateDisplayTime, 1000);
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
const {toast} = this.$refs;
|
||||
$(toast).toast('hide');
|
||||
window.setTimeout(() => {
|
||||
this.$emit('close');
|
||||
}, 500);
|
||||
},
|
||||
updateDisplayTime() {
|
||||
this.displayTime = this.creationTime.toRelative();
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -1,11 +1,8 @@
|
|||
import Vue from 'vue';
|
||||
import {createApp} from 'vue'
|
||||
import App from './App.vue';
|
||||
import {sync} from 'vuex-router-sync';
|
||||
import store from './store';
|
||||
import router from './router';
|
||||
|
||||
// bootstrap
|
||||
import 'jquery/dist/jquery.min.js';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import 'bootstrap/dist/js/bootstrap.min.js';
|
||||
|
||||
|
@ -46,20 +43,12 @@ import {
|
|||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
|
||||
|
||||
import vueDebounce from 'vue-debounce';
|
||||
|
||||
library.add(faPlus, faCheckCircle, faEdit, faTrash, faCat, faSyncAlt, faSort, faSortUp, faSortDown, faTh, faList,
|
||||
faWindowClose, faCamera, faStop, faPen, faCheck, faTimes, faSave, faEye, faComment, faUser, faComments, faEnvelope,
|
||||
faArchive, faMinus, faExclamation, faHourglass, faClipboard, faTasks, faAngleDown, faAngleRight);
|
||||
Vue.component('font-awesome-icon', FontAwesomeIcon);
|
||||
|
||||
sync(store, router);
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
store,
|
||||
router,
|
||||
render: h => h(App),
|
||||
});
|
||||
const app = createApp(App).use(store).use(router);
|
||||
|
||||
Vue.use(vueDebounce);
|
||||
app.component('font-awesome-icon', FontAwesomeIcon);
|
||||
app.mount('#app')
|
|
@ -1,24 +1,21 @@
|
|||
import {createRouter, createWebHistory} from 'vue-router'
|
||||
import store from '@/store';
|
||||
|
||||
import Items from './views/Items';
|
||||
import Boxes from './views/Boxes';
|
||||
import Files from './views/Files';
|
||||
import Error from './views/Error';
|
||||
import HowTo from './views/HowTo';
|
||||
import VueRouter from 'vue-router';
|
||||
import Vue from 'vue';
|
||||
import Login from '@/views/Login.vue';
|
||||
import Register from '@/views/Register.vue';
|
||||
import Debug from "@/views/admin/Debug.vue";
|
||||
import Tickets from "@/views/Tickets.vue";
|
||||
import Ticket from "@/views/Ticket.vue";
|
||||
import Admin from "@/views/admin/Admin.vue";
|
||||
import store from "@/store";
|
||||
import Empty from "@/views/Empty.vue";
|
||||
import Events from "@/views/admin/Events.vue";
|
||||
import AccessControl from "@/views/admin/AccessControl.vue";
|
||||
import {default as BoxesAdmin} from "@/views/admin/Boxes.vue"
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
const routes = [
|
||||
{path: '/', redirect: '/37C3/items', meta: {requiresAuth: false}},
|
||||
{path: '/login/', name: 'login', component: Login, meta: {requiresAuth: false}},
|
||||
|
@ -75,11 +72,11 @@ const routes = [
|
|||
]
|
||||
},
|
||||
{path: '/user', name: 'user', component: Empty, meta: {requiresAuth: true}},
|
||||
{path: '*', component: Error},
|
||||
];
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
linkActiveClass: "active",
|
||||
routes,
|
||||
});
|
||||
|
||||
|
@ -101,13 +98,10 @@ router.beforeEach((to, from, next) => {
|
|||
});
|
||||
|
||||
router.afterEach((to, from) => {
|
||||
if (to.params.event) {
|
||||
if (to.params.event && to.params.event !== store.state.lastEvent) {
|
||||
//console.log('update last event', to.params.event);
|
||||
store.commit('updateLastEvent', to.params.event);
|
||||
}
|
||||
if (to.query.layout !== from.query.layout) {
|
||||
store.commit('triggerLayoutChange', to.query.layout);
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
|
@ -1,63 +1,11 @@
|
|||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import AxiosBootstrap from 'axios';
|
||||
import * as _ from 'lodash/fp';
|
||||
import router from '../router';
|
||||
import {createStore} from 'vuex';
|
||||
import router from './router';
|
||||
|
||||
import * as base64 from 'base-64';
|
||||
import * as utf8 from 'utf8';
|
||||
import {ticketStateColorLookup, ticketStateIconLookup} from "@/utils";
|
||||
import createMutationsSharer from "vuex-shared-mutations";
|
||||
import {ticketStateColorLookup, ticketStateIconLookup, http} from "@/utils";
|
||||
|
||||
Vue.use(Vuex);
|
||||
const axios = AxiosBootstrap.create({
|
||||
baseURL: '/api',
|
||||
});
|
||||
axios.interceptors.response.use(response => response, error => {
|
||||
if (error.response.status === 401) {
|
||||
console.log('401 interceptor fired');
|
||||
store.dispatch('reloadToken').then((ok) => {
|
||||
if (ok) {
|
||||
error.config.headers['Authorization'] = `Token ${store.state.token}`;
|
||||
return axios.request(error.config);
|
||||
}
|
||||
});
|
||||
} else if (error.response.status === 403) {
|
||||
const message = `
|
||||
<h3>Access denied.</h3>
|
||||
<p>
|
||||
url: ${error.config.url}
|
||||
<br>
|
||||
method: ${error.config.method}
|
||||
<br>
|
||||
response-body: ${error.response && error.response.body}
|
||||
</p>
|
||||
`;
|
||||
store.commit('createToast', {title: 'Error: Access denied', message, color: 'danger'});
|
||||
return Promise.reject(error)
|
||||
} else {
|
||||
console.error('error interceptor fired', error.message);
|
||||
|
||||
if (error.isAxiosError) {
|
||||
const message = `
|
||||
<h3>A HTTP ${error.config.method} request failed.</h3>
|
||||
<p>
|
||||
url: ${error.config.url}
|
||||
<br>
|
||||
timeout: ${!!error.request.timeout}
|
||||
<br>
|
||||
response-body: ${error.response && error.response.body}
|
||||
</p>
|
||||
`;
|
||||
store.commit('createToast', {title: 'Error: HTTP', message, color: 'danger'});
|
||||
} else {
|
||||
store.commit('createToast', {title: 'Error: Unknown', message: error.toString(), color: 'danger'});
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
});
|
||||
|
||||
const store = new Vuex.Store({
|
||||
const store = createStore({
|
||||
state: {
|
||||
keyIncrement: 0,
|
||||
events: [],
|
||||
|
@ -68,26 +16,30 @@ const store = new Vuex.Store({
|
|||
tickets: [],
|
||||
users: [],
|
||||
groups: [],
|
||||
state_options: [],
|
||||
lastEvent: localStorage.getItem('lf_lastEvent') || '37C3',
|
||||
lastUsed: JSON.parse(localStorage.getItem('lf_lastUsed') || '{}'),
|
||||
remember: false,
|
||||
user: null,
|
||||
password: null,
|
||||
userPermissions: [],
|
||||
token: null,
|
||||
state_options: [],
|
||||
token_expiry: null,
|
||||
|
||||
user: {
|
||||
username: null,
|
||||
password: null,
|
||||
permissions: [],
|
||||
token: null,
|
||||
expiry: null,
|
||||
},
|
||||
|
||||
local_loaded: false,
|
||||
showAddBoxModal: false,
|
||||
toggle: false,
|
||||
},
|
||||
getters: {
|
||||
getEventSlug: state => state.route && state.route.params.event ? state.route.params.event : state.lastEvent,
|
||||
getActiveView: state => state.route.name || 'items',
|
||||
getFilters: state => state.route.query,
|
||||
route: state => router.currentRoute.value,
|
||||
getEventSlug: state => router.currentRoute.value.params.event ? router.currentRoute.value.params.event : state.lastEvent,
|
||||
getActiveView: state => router.currentRoute.value.name || 'items',
|
||||
getFilters: state => router.currentRoute.value.query,
|
||||
getBoxes: state => state.loadedBoxes,
|
||||
checkPermission: state => (event, perm) => state.userPermissions.includes(`${event}:${perm}`) || state.userPermissions.includes(`*:${perm}`),
|
||||
hasPermissions: state => state.userPermissions.length > 0,
|
||||
checkPermission: state => (event, perm) => state.user.permissions.includes(`${event}:${perm}`) || state.user.permissions.includes(`*:${perm}`),
|
||||
hasPermissions: state => state.user.permissions.length > 0,
|
||||
stateInfo: state => (slug) => {
|
||||
const obj = state.state_options.filter((s) => s.value === slug)[0];
|
||||
if (obj) {
|
||||
|
@ -107,9 +59,8 @@ const store = new Vuex.Store({
|
|||
}
|
||||
},
|
||||
layout: (state, getters) => {
|
||||
state.toggle = !state.toggle;
|
||||
if (router.currentRoute.query.layout)
|
||||
return router.currentRoute.query.layout;
|
||||
if (router.currentRoute.value.query.layout)
|
||||
return router.currentRoute.value.query.layout;
|
||||
if (getters.getActiveView === 'items')
|
||||
return 'cards';
|
||||
if (getters.getActiveView === 'tickets')
|
||||
|
@ -118,21 +69,20 @@ const store = new Vuex.Store({
|
|||
isLoggedIn(state) {
|
||||
if (!state.local_loaded) {
|
||||
state.remember = localStorage.getItem('remember') === 'true';
|
||||
state.user = localStorage.getItem('user');
|
||||
state.user.username = localStorage.getItem('user');
|
||||
//state.password = localStorage.getItem('password');
|
||||
state.userPermissions = JSON.parse(localStorage.getItem('permissions') || '[]');
|
||||
state.token = localStorage.getItem('token');
|
||||
state.token_expiry = localStorage.getItem('token_expiry');
|
||||
state.user.permissions = JSON.parse(localStorage.getItem('permissions') || '[]');
|
||||
state.user.token = localStorage.getItem('token');
|
||||
state.user.expiry = localStorage.getItem('token_expiry');
|
||||
state.local_loaded = true;
|
||||
axios.defaults.headers.common['Authorization'] = `Token ${state.token}`;
|
||||
}
|
||||
|
||||
return state.user !== null && state.token !== null;
|
||||
return state.user && state.user.username !== null && state.user.token !== null;
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
updateLastUsed(state, diff) {
|
||||
state.lastUsed = _.extend(state.lastUsed, diff);
|
||||
state.lastUsed = {...state.lastUsed, ...diff};
|
||||
localStorage.setItem('lf_lastUsed', JSON.stringify(state.lastUsed));
|
||||
},
|
||||
updateLastEvent(state, slug) {
|
||||
|
@ -200,38 +150,39 @@ const store = new Vuex.Store({
|
|||
localStorage.setItem('remember', remember);
|
||||
},
|
||||
setUser(state, user) {
|
||||
state.user = user;
|
||||
state.user.username = user;
|
||||
if (user)
|
||||
localStorage.setItem('user', user);
|
||||
},
|
||||
setPassword(state, password) {
|
||||
state.password = password;
|
||||
state.user.password = password;
|
||||
},
|
||||
setPermissions(state, permissions) {
|
||||
state.userPermissions = permissions;
|
||||
state.user.permissions = permissions;
|
||||
if (permissions)
|
||||
localStorage.setItem('permissions', JSON.stringify(permissions));
|
||||
},
|
||||
setToken(state, {token, expiry}) {
|
||||
state.token = token;
|
||||
state.token_expiry = expiry;
|
||||
const user = {...state.user};
|
||||
user.token = token;
|
||||
user.expiry = expiry;
|
||||
state.user = user;
|
||||
if (token)
|
||||
localStorage.setItem('token', token);
|
||||
localStorage.setItem('token_expiry', expiry);
|
||||
},
|
||||
logout(state) {
|
||||
state.user = null;
|
||||
state.token = null;
|
||||
localStorage.removeItem('user');
|
||||
localStorage.removeItem('permissions');
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('token_expiry');
|
||||
if (router.currentRoute.name !== 'login')
|
||||
router.push('/login');
|
||||
setUserInfo(state, user) {
|
||||
state.user = user;
|
||||
},
|
||||
logout(state) {
|
||||
const user = {...state.user};
|
||||
user.user = null;
|
||||
user.password = null;
|
||||
user.token = null;
|
||||
user.expiry = null;
|
||||
user.permissions = null;
|
||||
state.user = user;
|
||||
},
|
||||
triggerLayoutChange(state) {
|
||||
state.toggle = !state.toggle;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async login({commit, dispatch, state}, {username, password, remember}) {
|
||||
|
@ -247,7 +198,6 @@ const store = new Vuex.Store({
|
|||
commit('setToken', data);
|
||||
commit('setUser', username);
|
||||
commit('setPassword', password);
|
||||
axios.defaults.headers.common['Authorization'] = `Token ${data.token}`;
|
||||
dispatch('afterLogin');
|
||||
return true;
|
||||
} else {
|
||||
|
@ -258,18 +208,17 @@ const store = new Vuex.Store({
|
|||
return false;
|
||||
}
|
||||
},
|
||||
async reloadToken({commit, state}) {
|
||||
async reloadToken({commit, state, getters}) {
|
||||
try {
|
||||
if (state.password) {
|
||||
if (state.user.username && state.user.password) {
|
||||
const data = await fetch('/api/2/login/', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({username: state.user, password: state.password}),
|
||||
body: JSON.stringify({username: state.user.username, password: state.user.password}),
|
||||
credentials: 'omit'
|
||||
}).then(r => r.json()).catch(e => console.error(e))
|
||||
if (data && data.token) {
|
||||
commit('setToken', data);
|
||||
axios.defaults.headers.common['Authorization'] = `Token ${data.token}`;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -280,29 +229,33 @@ const store = new Vuex.Store({
|
|||
store.commit('logout');
|
||||
},
|
||||
//async verifyToken({commit, state}) {
|
||||
async afterLogin({dispatch}) {
|
||||
const boxes = dispatch('loadBoxes');
|
||||
const states = dispatch('fetchTicketStates');
|
||||
const items = dispatch('loadEventItems');
|
||||
const tickets = dispatch('loadTickets');
|
||||
const user = dispatch('loadUserInfo');
|
||||
await Promise.all([boxes, items, tickets, user, states]);
|
||||
async afterLogin({dispatch, state}) {
|
||||
let promises = [];
|
||||
promises.push(dispatch('loadBoxes'));
|
||||
promises.push(dispatch('fetchTicketStates'));
|
||||
promises.push(dispatch('loadEventItems'));
|
||||
promises.push(dispatch('loadTickets'));
|
||||
if (!state.user.permissions) {
|
||||
promises.push(dispatch('loadUserInfo'));
|
||||
}
|
||||
await Promise.all(promises);
|
||||
},
|
||||
async fetchImage({state}, url) {
|
||||
return await fetch(url, {headers: {'Authorization': `Token ${state.token}`}});
|
||||
return await fetch(url, {headers: {'Authorization': `Token ${state.user.token}`}});
|
||||
},
|
||||
async loadUserInfo({commit}) {
|
||||
const {data} = await axios.get('/2/self/');
|
||||
commit('setUser', data.username);
|
||||
async loadUserInfo({commit, state}) {
|
||||
const {data, success} = await http.get('/2/self/', state.user.token);
|
||||
commit('setPermissions', data.permissions);
|
||||
},
|
||||
async loadEvents({commit}) {
|
||||
const {data} = await axios.get('/2/events/');
|
||||
commit('replaceEvents', data);
|
||||
async loadEvents({commit, state}) {
|
||||
const {data, success} = await http.get('/2/events/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceEvents', data);
|
||||
},
|
||||
async fetchTicketStates({commit}) {
|
||||
const {data} = await axios.get('/2/tickets/states/');
|
||||
commit('replaceTicketStates', data);
|
||||
async fetchTicketStates({commit, state}) {
|
||||
const {data, success} = await http.get('/2/tickets/states/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceTicketStates', data);
|
||||
},
|
||||
changeEvent({dispatch, getters, commit}, eventName) {
|
||||
router.push({path: `/${eventName.slug}/${getters.getActiveView}/`});
|
||||
|
@ -321,121 +274,121 @@ const store = new Vuex.Store({
|
|||
if (slug in state.itemCache) {
|
||||
commit('replaceLoadedItems', state.itemCache[slug]);
|
||||
}
|
||||
const {data} = await axios.get(`/2/${slug}/items/`);
|
||||
commit('replaceLoadedItems', data);
|
||||
commit('setItemCache', {slug, items: data});
|
||||
const {data, success} = await http.get(`/2/${slug}/items/`, state.user.token);
|
||||
if (data && success) {
|
||||
commit('replaceLoadedItems', data);
|
||||
commit('setItemCache', {slug, items: data});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error loading items");
|
||||
}
|
||||
},
|
||||
async searchEventItems({commit, getters}, query) {
|
||||
async searchEventItems({commit, getters, state}, query) {
|
||||
const foo = utf8.encode(query);
|
||||
const bar = base64.encode(foo);
|
||||
|
||||
const {data} = await axios.get(`/2/${getters.getEventSlug}/items/${bar}/`);
|
||||
commit('replaceLoadedItems', data);
|
||||
const {data, success} = await http.get(`/2/${getters.getEventSlug}/items/${bar}/`, state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceLoadedItems', data);
|
||||
},
|
||||
async loadBoxes({commit}) {
|
||||
const {data} = await axios.get('/2/boxes/');
|
||||
commit('replaceBoxes', data);
|
||||
async loadBoxes({commit, state}) {
|
||||
const {data, success} = await http.get('/2/boxes/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceBoxes', data);
|
||||
},
|
||||
async createBox({commit, dispatch}, box) {
|
||||
const {data} = await axios.post('/2/boxes/', box);
|
||||
async createBox({commit, dispatch, state}, box) {
|
||||
const {data, success} = await http.post('/2/boxes/', box, state.user.token);
|
||||
commit('replaceBoxes', data);
|
||||
dispatch('loadBoxes').then(() => {
|
||||
commit('closeAddBoxModal');
|
||||
});
|
||||
},
|
||||
async deleteBox({commit, dispatch}, box_id) {
|
||||
await axios.delete(`/2/boxes/${box_id}/`);
|
||||
async deleteBox({commit, dispatch, state}, box_id) {
|
||||
await http.delete(`/2/boxes/${box_id}/`, state.user.token);
|
||||
dispatch('loadBoxes');
|
||||
},
|
||||
async updateItem({commit, getters}, item) {
|
||||
const {data} = await axios.put(`/2/${getters.getEventSlug}/item/${item.uid}/`, item);
|
||||
async updateItem({commit, getters, state}, item) {
|
||||
const {
|
||||
data,
|
||||
success
|
||||
} = await http.put(`/2/${getters.getEventSlug}/item/${item.uid}/`, item, state.user.token);
|
||||
commit('updateItem', data);
|
||||
},
|
||||
async markItemReturned({commit, getters}, item) {
|
||||
await axios.patch(`/2/${getters.getEventSlug}/item/${item.uid}/`, {returned: true});
|
||||
async markItemReturned({commit, getters, state}, item) {
|
||||
await http.patch(`/2/${getters.getEventSlug}/item/${item.uid}/`, {returned: true}, state.user.token);
|
||||
commit('removeItem', item);
|
||||
},
|
||||
async deleteItem({commit, getters}, item) {
|
||||
await axios.delete(`/2/${getters.getEventSlug}/item/${item.uid}/`, item);
|
||||
async deleteItem({commit, getters, state}, item) {
|
||||
await http.delete(`/2/${getters.getEventSlug}/item/${item.uid}/`, item, state.user.token);
|
||||
commit('removeItem', item);
|
||||
},
|
||||
async postItem({commit, getters}, item) {
|
||||
async postItem({commit, getters, state}, item) {
|
||||
commit('updateLastUsed', {box: item.box, cid: item.cid});
|
||||
const {data} = await axios.post(`/2/${getters.getEventSlug}/item/`, item);
|
||||
const {data, success} = await http.post(`/2/${getters.getEventSlug}/item/`, item, state.user.token);
|
||||
commit('appendItem', data);
|
||||
},
|
||||
async loadTickets({commit}) {
|
||||
const {data} = await axios.get('/2/tickets/');
|
||||
commit('replaceTickets', data);
|
||||
async loadTickets({commit, state}) {
|
||||
const {data, success} = await http.get('/2/tickets/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceTickets', data);
|
||||
},
|
||||
async sendMail({commit, dispatch}, {id, message}) {
|
||||
const {data} = await axios.post(`/2/tickets/${id}/reply/`, {message});
|
||||
await dispatch('loadTickets');
|
||||
async sendMail({commit, dispatch, state}, {id, message}) {
|
||||
const {data, success} = await http.post(`/2/tickets/${id}/reply/`, {message}, state.user.token);
|
||||
if (data && success) {
|
||||
await dispatch('loadTickets');
|
||||
}
|
||||
},
|
||||
async postManualTicket({commit, dispatch}, {sender, message, title,}) {
|
||||
const {data} = await axios.post(`/2/tickets/manual/`, {
|
||||
async postManualTicket({commit, dispatch, state}, {sender, message, title,}) {
|
||||
const {data, success} = await http.post(`/2/tickets/manual/`, {
|
||||
name: title,
|
||||
sender,
|
||||
body: message,
|
||||
recipient: 'mail@c3lf.de'
|
||||
});
|
||||
}, state.user.token);
|
||||
await dispatch('loadTickets');
|
||||
},
|
||||
async postComment({commit, dispatch}, {id, message}) {
|
||||
const {data} = await axios.post(`/2/tickets/${id}/comment/`, {comment: message});
|
||||
await dispatch('loadTickets');
|
||||
async postComment({commit, dispatch, state}, {id, message}) {
|
||||
const {data, success} = await http.post(`/2/tickets/${id}/comment/`, {comment: message}, state.user.token);
|
||||
if (data && success) {
|
||||
await dispatch('loadTickets');
|
||||
}
|
||||
},
|
||||
async loadUsers({commit}) {
|
||||
const {data} = await axios.get('/2/users/');
|
||||
commit('replaceUsers', data);
|
||||
async loadUsers({commit, state}) {
|
||||
const {data, success} = await http.get('/2/users/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceUsers', data);
|
||||
},
|
||||
async loadGroups({commit}) {
|
||||
const {data} = await axios.get('/2/groups/');
|
||||
commit('replaceGroups', data);
|
||||
async loadGroups({commit, state}) {
|
||||
const {data, success} = await http.get('/2/groups/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceGroups', data);
|
||||
},
|
||||
async updateTicket({commit}, ticket) {
|
||||
const {data} = await axios.put(`/2/tickets/${ticket.id}/`, ticket);
|
||||
async updateTicket({commit, state}, ticket) {
|
||||
const {data, success} = await http.put(`/2/tickets/${ticket.id}/`, ticket, state.user.token);
|
||||
commit('updateTicket', data);
|
||||
},
|
||||
async updateTicketPartial({commit}, {id, ...ticket}) {
|
||||
const {data} = await axios.patch(`/2/tickets/${id}/`, ticket);
|
||||
async updateTicketPartial({commit, state}, {id, ...ticket}) {
|
||||
const {data, success} = await http.patch(`/2/tickets/${id}/`, ticket, state.user.token);
|
||||
commit('updateTicket', data);
|
||||
}
|
||||
},
|
||||
plugins: [createMutationsSharer({
|
||||
predicate: [
|
||||
'replaceLoadedItems',
|
||||
'setItemCache',
|
||||
'setLayout',
|
||||
'replaceBoxes',
|
||||
'updateItem',
|
||||
'removeItem',
|
||||
'appendItem',
|
||||
'replaceTickets',
|
||||
'replaceUsers',
|
||||
'replaceGroups',
|
||||
'updateTicket',
|
||||
'openAddBoxModal',
|
||||
'closeAddBoxModal',
|
||||
'createToast',
|
||||
'removeToast',
|
||||
'setRemember',
|
||||
'setUser',
|
||||
'setPermissions',
|
||||
'setToken',
|
||||
'logout',
|
||||
]
|
||||
})],
|
||||
});
|
||||
|
||||
store.watch((state) => state.user, (user) => {
|
||||
console.log('user changed', user);
|
||||
if (store.getters.isLoggedIn) {
|
||||
if (router.currentRoute.value.name === 'login' && router.currentRoute.value.query.redirect)
|
||||
router.push(router.currentRoute.value.query.redirect);
|
||||
else if (router.currentRoute.value.name === 'login')
|
||||
router.push('/');
|
||||
} else {
|
||||
if (router.currentRoute.value.name !== 'login') {
|
||||
router.push({
|
||||
name: 'login',
|
||||
query: {redirect: router.currentRoute.value.fullPath},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
||||
store.dispatch('loadEvents').then(() => {
|
||||
if (store.getters.isLoggedIn) {
|
||||
axios.defaults.headers.common['Authorization'] = `Token ${store.state.token}`;
|
||||
store.dispatch('afterLogin');
|
||||
}
|
||||
});
|
|
@ -24,4 +24,80 @@ function ticketStateIconLookup(ticket) {
|
|||
return 'exclamation';
|
||||
}
|
||||
|
||||
export {ticketStateColorLookup, ticketStateIconLookup};
|
||||
const http = {
|
||||
get: async (url, token) => {
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
const response = await fetch('/api' + url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Token ${token}`,
|
||||
},
|
||||
});
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
},
|
||||
post: async (url, data, token) => {
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
const response = await fetch('/api' + url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Token ${token}`,
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
},
|
||||
put: async (url, data, token) => {
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
const response = await fetch('/api' + url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Token ${token}`,
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
},
|
||||
patch: async (url, data, token) => {
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
const response = await fetch('/api' + url, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Token ${token}`,
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
},
|
||||
delete: async (url, token) => {
|
||||
if (!token) {
|
||||
return null;
|
||||
}
|
||||
const response = await fetch('/api' + url, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Token ${token}`,
|
||||
},
|
||||
});
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
}
|
||||
}
|
||||
|
||||
export {ticketStateColorLookup, ticketStateIconLookup, http};
|
|
@ -93,7 +93,7 @@ export default {
|
|||
...mapGetters(['layout']),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['deleteItem', 'markItemReturned']),
|
||||
...mapActions(['deleteItem', 'markItemReturned', 'loadEventItems', 'updateItem']),
|
||||
openLightboxModalWith(item) {
|
||||
this.lightboxHash = item.file;
|
||||
},
|
||||
|
@ -107,12 +107,15 @@ export default {
|
|||
this.editingItem = null;
|
||||
},
|
||||
saveEditingItem() { // Saves the edited copy of the item.
|
||||
this.$store.dispatch('updateItem', this.editingItem);
|
||||
this.updateItem(this.editingItem);
|
||||
this.closeEditingModal();
|
||||
},
|
||||
confirm(message) {
|
||||
return window.confirm(message);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadEventItems();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -100,7 +100,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
input{
|
||||
input {
|
||||
background-color: var(--dark);
|
||||
border: var(--gray) 1px solid;;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div class="card-header">
|
||||
<ul class="nav nav-tabs card-header-tabs">
|
||||
<li class="nav-item">
|
||||
<router-link class="nav-link" :to="{name: 'admin'}" active-class="active" exact>Dashboard</router-link>
|
||||
<router-link class="nav-link" :to="{name: 'admin'}" active-class="dummy" exact-active-class="active">Dashboard</router-link>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<router-link class="nav-link" :to="{name: 'events'}" active-class="active">Events</router-link>
|
||||
|
|
|
@ -22,27 +22,13 @@
|
|||
{{ box.name }}
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="text-center">Mails</h3>
|
||||
<!--p>{{ mails }}</p-->
|
||||
<ul>
|
||||
<li v-for="mail in mails" :key="mail.id">
|
||||
{{ mail.id }}
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="text-center">Issues</h3>
|
||||
<!--p>{{ issues }}</p-->
|
||||
<ul>
|
||||
<li v-for="issue in issues" :key="issue.id">
|
||||
<li v-for="issue in tickets" :key="issue.id">
|
||||
{{ issue.id }}
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="text-center">System Events</h3>
|
||||
<!--p>{{ systemEvents }}</p-->
|
||||
<ul>
|
||||
<li v-for="systemEvent in systemEvents" :key="systemEvent.id">
|
||||
{{ systemEvent.id }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -54,19 +40,17 @@ export default {
|
|||
name: 'Debug',
|
||||
components: {Table},
|
||||
computed: {
|
||||
...mapState(['events', 'loadedItems', 'loadedBoxes', 'mails', 'issues', 'systemEvents']),
|
||||
...mapState(['events', 'loadedItems', 'loadedBoxes', 'tickets']),
|
||||
qr_url() {
|
||||
return window.location.href;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['changeEvent', 'loadMails', 'loadIssues', 'loadSystemEvents']),
|
||||
...mapActions(['changeEvent', 'loadTickets']),
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.loadMails();
|
||||
this.loadIssues();
|
||||
this.loadSystemEvents();
|
||||
this.loadTickets();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
31
web/vue.config.js
Normal file
31
web/vue.config.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
// vue.config.js
|
||||
|
||||
module.exports = {
|
||||
devServer: {
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Headers": "*",
|
||||
"Access-Control-Allow-Methods": "*"
|
||||
},
|
||||
proxy: {
|
||||
'^/media/2': {
|
||||
target: 'https://staging.c3lf.de/',
|
||||
changeOrigin: true
|
||||
},
|
||||
'^/api/2': {
|
||||
target: 'https://staging.c3lf.de/',
|
||||
changeOrigin: true,
|
||||
},
|
||||
'^/api/1': {
|
||||
target: 'https://staging.c3lf.de/',
|
||||
changeOrigin: true,
|
||||
},
|
||||
'^/ws/2': {
|
||||
target: 'http://127.0.0.1:8082/',
|
||||
//changeOrigin: true,
|
||||
ws: true,
|
||||
logLevel: 'debug',
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue