diff --git a/web/src/App.vue b/web/src/App.vue
index 18ba674..fc70347 100644
--- a/web/src/App.vue
+++ b/web/src/App.vue
@@ -36,7 +36,7 @@ export default {
}),
methods: {
...mapMutations(['removeToast', 'createToast', 'closeAddBoxModal', 'openAddBoxModal']),
- ...mapActions(['loadEvents', 'afterLogin']),
+ ...mapActions(['loadEvents']),
openAddItemModal() {
this.addItemModalOpen = true;
},
@@ -53,9 +53,9 @@ export default {
created: function () {
document.title = document.location.hostname;
this.loadEvents().then(() => {
- if (this.isLoggedIn) {
+ /*if (this.isLoggedIn) {
this.afterLogin();
- }
+ }*/
});
}
};
diff --git a/web/src/shared-state-plugin/index.js b/web/src/shared-state-plugin/index.js
index e97fcd6..c74ac01 100644
--- a/web/src/shared-state-plugin/index.js
+++ b/web/src/shared-state-plugin/index.js
@@ -165,6 +165,14 @@ export default (config) => {
if (config.debug) console.log('worker started');
const updateWorkerState = (key, new_value, old_value = null) => {
+ if(new_value === old_value) {
+ if (config.debug) console.log('updateWorkerState: no change', key, new_value);
+ return;
+ }
+ if (new_value === undefined) {
+ if (config.debug) console.log('updateWorkerState: undefined', key, new_value);
+ return;
+ }
worker.port.postMessage({
type: 'state_diff',
key: key,
diff --git a/web/src/store.js b/web/src/store.js
index 0512b6e..95b26e2 100644
--- a/web/src/store.js
+++ b/web/src/store.js
@@ -1,60 +1,12 @@
import {createStore} from 'vuex';
-import AxiosBootstrap from 'axios';
import router from './router';
import * as base64 from 'base-64';
import * as utf8 from 'utf8';
-import {ticketStateColorLookup, ticketStateIconLookup} from "@/utils";
+import {ticketStateColorLookup, ticketStateIconLookup, http} from "@/utils";
import sharedStatePlugin from "@/shared-state-plugin";
import persistentStatePlugin from "@/persistent-state-plugin";
-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 = `
-
Access denied.
-
- url: ${error.config.url}
-
- method: ${error.config.method}
-
- response-body: ${error.response && error.response.body}
-
- `;
- 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 = `
- A HTTP ${error.config.method} request failed.
-
- url: ${error.config.url}
-
- timeout: ${!!error.request.timeout}
-
- response-body: ${error.response && error.response.body}
-
- `;
- 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 = createStore({
state: {
keyIncrement: 0,
@@ -213,8 +165,6 @@ const store = createStore({
user.expiry = null;
user.permissions = null;
state.user = user;
- if (state.route.name !== 'login')
- router.push('/login');
},
setTest(state, test) {
state.test = test;
@@ -231,8 +181,7 @@ const store = createStore({
credentials: 'omit'
}).then(r => r.json())
if (data && data.token) {
- axios.defaults.headers.common['Authorization'] = `Token ${data.token}`;
- const {data: {permissions}} = await axios.get('/2/self/');
+ const {data: {permissions}} = await http.get('/2/self/', data.token);
commit('setUserInfo', {...data, permissions, username, password});
return true;
} else {
@@ -254,7 +203,6 @@ const store = createStore({
}).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;
}
}
@@ -265,32 +213,31 @@ const store = createStore({
store.commit('logout');
},
//async verifyToken({commit, state}) {
- async afterLogin({dispatch, state}) {
- axios.defaults.headers.common['Authorization'] = `Token ${state.user.token}`;
- /*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}) {
+ //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]);
if (!state.user.permissions) {
const user = dispatch('loadUserInfo');
await Promise.all([user]);
}
- },
+ },*/
async fetchImage({state}, url) {
return await fetch(url, {headers: {'Authorization': `Token ${state.user.token}`}});
},
- async loadUserInfo({commit}) {
- const {data} = await axios.get('/2/self/');
+ async loadUserInfo({commit, state}) {
+ const {data} = await http.get('/2/self/', state.user.token);
commit('setPermissions', data.permissions);
},
- async loadEvents({commit}) {
- const {data} = await axios.get('/2/events/');
+ async loadEvents({commit, state}) {
+ const {data} = await http.get('/2/events/', state.user.token);
commit('replaceEvents', data);
},
- async fetchTicketStates({commit}) {
- const {data} = await axios.get('/2/tickets/states/');
+ async fetchTicketStates({commit, state}) {
+ const {data} = await http.get('/2/tickets/states/', state.user.token);
commit('replaceTicketStates', data);
},
changeEvent({dispatch, getters, commit}, eventName) {
@@ -310,94 +257,94 @@ const store = createStore({
if (slug in state.itemCache) {
commit('replaceLoadedItems', state.itemCache[slug]);
}
- const {data} = await axios.get(`/2/${slug}/items/`);
+ const {data} = await http.get(`/2/${slug}/items/`, state.user.token);
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}/`);
+ const {data} = await http.get(`/2/${getters.getEventSlug}/items/${bar}/`, state.user.token);
commit('replaceLoadedItems', data);
},
- async loadBoxes({commit}) {
- const {data} = await axios.get('/2/boxes/');
+ async loadBoxes({commit, state}) {
+ const {data} = await http.get('/2/boxes/', state.user.token);
commit('replaceBoxes', data);
},
- async createBox({commit, dispatch}, box) {
- const {data} = await axios.post('/2/boxes/', box);
+ async createBox({commit, dispatch, state}, box) {
+ const {data} = 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} = 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} = await http.post(`/2/${getters.getEventSlug}/item/`, item, state.user.token);
commit('appendItem', data);
},
- async loadTickets({commit}) {
- const {data} = await axios.get('/2/tickets/');
+ async loadTickets({commit, state}) {
+ const {data} = await http.get('/2/tickets/', state.user.token);
commit('replaceTickets', data);
},
- async sendMail({commit, dispatch}, {id, message}) {
- const {data} = await axios.post(`/2/tickets/${id}/reply/`, {message});
+ async sendMail({commit, dispatch, state}, {id, message}) {
+ const {data} = await http.post(`/2/tickets/${id}/reply/`, {message}, state.user.token);
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} = 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});
+ async postComment({commit, dispatch, staee}, {id, message}) {
+ const {data} = await http.post(`/2/tickets/${id}/comment/`, {comment: message}, state.user.token);
await dispatch('loadTickets');
},
- async loadUsers({commit}) {
- const {data} = await axios.get('/2/users/');
+ async loadUsers({commit, state}) {
+ const {data} = await http.get('/2/users/', state.user.token);
commit('replaceUsers', data);
},
- async loadGroups({commit}) {
- const {data} = await axios.get('/2/groups/');
+ async loadGroups({commit, state}) {
+ const {data} = await http.get('/2/groups/', state.user.token);
commit('replaceGroups', data);
},
- async updateTicket({commit}, ticket) {
- const {data} = await axios.put(`/2/tickets/${ticket.id}/`, ticket);
+ async updateTicket({commit, state}, ticket) {
+ const {data} = 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} = await http.patch(`/2/tickets/${id}/`, ticket, state.user.token);
commit('updateTicket', data);
}
},
plugins: [
persistentStatePlugin({ // TODO change remember to some kind of enable field
prefix: "lf_",
- debug: false,
+ debug: true,
isLoadedKey: "persistent_loaded",
state: [
"remember",
@@ -405,24 +352,57 @@ const store = createStore({
]
}),
sharedStatePlugin({
- debug: false,
+ debug: true,
isLoadedKey: "shared_loaded",
clearingMutation: "logout",
state: [
"test",
+ "state_options",
+ "events",
+ "fetchData",
"tickets",
+ ],
+ watch: [
+ "test",
"state_options",
"events",
"fetchData",
],
- watch: [
- "test",
- ],
mutations: [
- "replaceTickets",
+ //"replaceTickets",
],
}),
],
});
+// watch: {
+// user: function (user) {
+// console.log('user changed', user);
+// if (user.token) {
+// }
+// //if(token && this.state.route.name === 'login') {
+// //if (state.route.name !== 'login')
+// // router.push('/login');
+// //if (state.route.name === 'login' && state.route.query.redirect)
+// // router.push(state.route.query.redirect);
+// },
+// },
+
+store.watch((state) => state.user, (user) => {
+ console.log('user changed', user);
+ if (store.getters.isLoggedIn) {
+ if (store.state.route.name === 'login' && store.state.route.query.redirect)
+ router.push(store.state.route.query.redirect);
+ else if (store.state.route.name === 'login')
+ router.push('/');
+ } else {
+ if (store.state.route.name !== 'login') {
+ router.push({
+ name: 'login',
+ query: {redirect: store.state.route.fullPath},
+ });
+ }
+ }
+});
+
export default store;
diff --git a/web/src/utils.js b/web/src/utils.js
index 3464224..6f8ec9c 100644
--- a/web/src/utils.js
+++ b/web/src/utils.js
@@ -24,4 +24,74 @@ function ticketStateIconLookup(ticket) {
return 'exclamation';
}
-export {ticketStateColorLookup, ticketStateIconLookup};
\ No newline at end of file
+const http = {
+ post: async (url, data, token) => {
+ if (!token) {
+ return null;
+ }
+ const response = await fetch('/api' + url, {
+ method: 'POST',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Token ${data.token}`,
+ },
+ body: JSON.stringify(data),
+ });
+ return {data: await response.json()};
+ }, get: async (url, token) => {
+ if (!token) {
+ return null;
+ }
+ const response = await fetch('/api' + url, {
+ method: 'GET',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Token ${token}`,
+ },
+ });
+ return {data: await response.json()};
+ },
+ put: async (url, data, token) => {
+ if (!token) {
+ return null;
+ }
+ const response = await fetch('/api' + url, {
+ method: 'PUT',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Token ${data.token}`,
+ },
+ body: JSON.stringify(data),
+ });
+ return {data: await response.json()};
+ },
+ patch: async (url, data, token) => {
+ if (!token) {
+ return null;
+ }
+ const response = await fetch('/api' + url, {
+ method: 'PATCH',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Token ${data.token}`,
+ },
+ body: JSON.stringify(data),
+ });
+ return {data: await response.json()};
+ },
+ delete: async (url, token) => {
+ if (!token) {
+ return null;
+ }
+ const response = await fetch('/api' + url, {
+ method: 'DELETE',
+ headers: {
+ "Content-Type": "application/json",
+ "Authorization": `Token ${token}`,
+ },
+ });
+ return {data: await response.json()};
+ }
+}
+
+export {ticketStateColorLookup, ticketStateIconLookup, http};
\ No newline at end of file
diff --git a/web/src/views/Login.vue b/web/src/views/Login.vue
index abe3989..8cff6c2 100644
--- a/web/src/views/Login.vue
+++ b/web/src/views/Login.vue
@@ -100,7 +100,7 @@ export default {