This commit is contained in:
j3d1 2024-01-26 01:03:00 +01:00
parent 30cddebdc8
commit 4645a2f48c
5 changed files with 172 additions and 114 deletions

View file

@ -36,7 +36,7 @@ export default {
}), }),
methods: { methods: {
...mapMutations(['removeToast', 'createToast', 'closeAddBoxModal', 'openAddBoxModal']), ...mapMutations(['removeToast', 'createToast', 'closeAddBoxModal', 'openAddBoxModal']),
...mapActions(['loadEvents', 'afterLogin']), ...mapActions(['loadEvents']),
openAddItemModal() { openAddItemModal() {
this.addItemModalOpen = true; this.addItemModalOpen = true;
}, },
@ -53,9 +53,9 @@ export default {
created: function () { created: function () {
document.title = document.location.hostname; document.title = document.location.hostname;
this.loadEvents().then(() => { this.loadEvents().then(() => {
if (this.isLoggedIn) { /*if (this.isLoggedIn) {
this.afterLogin(); this.afterLogin();
} }*/
}); });
} }
}; };

View file

@ -165,6 +165,14 @@ export default (config) => {
if (config.debug) console.log('worker started'); if (config.debug) console.log('worker started');
const updateWorkerState = (key, new_value, old_value = null) => { 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({ worker.port.postMessage({
type: 'state_diff', type: 'state_diff',
key: key, key: key,

View file

@ -1,60 +1,12 @@
import {createStore} from 'vuex'; import {createStore} from 'vuex';
import AxiosBootstrap from 'axios';
import router from './router'; import router from './router';
import * as base64 from 'base-64'; import * as base64 from 'base-64';
import * as utf8 from 'utf8'; import * as utf8 from 'utf8';
import {ticketStateColorLookup, ticketStateIconLookup} from "@/utils"; import {ticketStateColorLookup, ticketStateIconLookup, http} from "@/utils";
import sharedStatePlugin from "@/shared-state-plugin"; import sharedStatePlugin from "@/shared-state-plugin";
import persistentStatePlugin from "@/persistent-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 = `
<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 = createStore({ const store = createStore({
state: { state: {
keyIncrement: 0, keyIncrement: 0,
@ -213,8 +165,6 @@ const store = createStore({
user.expiry = null; user.expiry = null;
user.permissions = null; user.permissions = null;
state.user = user; state.user = user;
if (state.route.name !== 'login')
router.push('/login');
}, },
setTest(state, test) { setTest(state, test) {
state.test = test; state.test = test;
@ -231,8 +181,7 @@ const store = createStore({
credentials: 'omit' credentials: 'omit'
}).then(r => r.json()) }).then(r => r.json())
if (data && data.token) { if (data && data.token) {
axios.defaults.headers.common['Authorization'] = `Token ${data.token}`; const {data: {permissions}} = await http.get('/2/self/', data.token);
const {data: {permissions}} = await axios.get('/2/self/');
commit('setUserInfo', {...data, permissions, username, password}); commit('setUserInfo', {...data, permissions, username, password});
return true; return true;
} else { } else {
@ -254,7 +203,6 @@ const store = createStore({
}).then(r => r.json()).catch(e => console.error(e)) }).then(r => r.json()).catch(e => console.error(e))
if (data && data.token) { if (data && data.token) {
commit('setToken', data); commit('setToken', data);
axios.defaults.headers.common['Authorization'] = `Token ${data.token}`;
return true; return true;
} }
} }
@ -265,32 +213,31 @@ const store = createStore({
store.commit('logout'); store.commit('logout');
}, },
//async verifyToken({commit, state}) { //async verifyToken({commit, state}) {
async afterLogin({dispatch, state}) { /*async afterLogin({dispatch, state}) {
axios.defaults.headers.common['Authorization'] = `Token ${state.user.token}`; //const boxes = dispatch('loadBoxes');
/*const boxes = dispatch('loadBoxes'); //const states = dispatch('fetchTicketStates');
const states = dispatch('fetchTicketStates'); //const items = dispatch('loadEventItems');
const items = dispatch('loadEventItems'); //const tickets = dispatch('loadTickets');
const tickets = dispatch('loadTickets'); //const user = dispatch('loadUserInfo');
const user = dispatch('loadUserInfo'); //await Promise.all([boxes, items, tickets, user, states]);
await Promise.all([boxes, items, tickets, user, states]);*/
if (!state.user.permissions) { if (!state.user.permissions) {
const user = dispatch('loadUserInfo'); const user = dispatch('loadUserInfo');
await Promise.all([user]); await Promise.all([user]);
} }
}, },*/
async fetchImage({state}, url) { async fetchImage({state}, url) {
return await fetch(url, {headers: {'Authorization': `Token ${state.user.token}`}}); return await fetch(url, {headers: {'Authorization': `Token ${state.user.token}`}});
}, },
async loadUserInfo({commit}) { async loadUserInfo({commit, state}) {
const {data} = await axios.get('/2/self/'); const {data} = await http.get('/2/self/', state.user.token);
commit('setPermissions', data.permissions); commit('setPermissions', data.permissions);
}, },
async loadEvents({commit}) { async loadEvents({commit, state}) {
const {data} = await axios.get('/2/events/'); const {data} = await http.get('/2/events/', state.user.token);
commit('replaceEvents', data); commit('replaceEvents', data);
}, },
async fetchTicketStates({commit}) { async fetchTicketStates({commit, state}) {
const {data} = await axios.get('/2/tickets/states/'); const {data} = await http.get('/2/tickets/states/', state.user.token);
commit('replaceTicketStates', data); commit('replaceTicketStates', data);
}, },
changeEvent({dispatch, getters, commit}, eventName) { changeEvent({dispatch, getters, commit}, eventName) {
@ -310,94 +257,94 @@ const store = createStore({
if (slug in state.itemCache) { if (slug in state.itemCache) {
commit('replaceLoadedItems', state.itemCache[slug]); 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('replaceLoadedItems', data);
commit('setItemCache', {slug, items: data}); commit('setItemCache', {slug, items: data});
} catch (e) { } catch (e) {
console.error("Error loading items"); console.error("Error loading items");
} }
}, },
async searchEventItems({commit, getters}, query) { async searchEventItems({commit, getters, state}, query) {
const foo = utf8.encode(query); const foo = utf8.encode(query);
const bar = base64.encode(foo); 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); commit('replaceLoadedItems', data);
}, },
async loadBoxes({commit}) { async loadBoxes({commit, state}) {
const {data} = await axios.get('/2/boxes/'); const {data} = await http.get('/2/boxes/', state.user.token);
commit('replaceBoxes', data); commit('replaceBoxes', data);
}, },
async createBox({commit, dispatch}, box) { async createBox({commit, dispatch, state}, box) {
const {data} = await axios.post('/2/boxes/', box); const {data} = await http.post('/2/boxes/', box, state.user.token);
commit('replaceBoxes', data); commit('replaceBoxes', data);
dispatch('loadBoxes').then(() => { dispatch('loadBoxes').then(() => {
commit('closeAddBoxModal'); commit('closeAddBoxModal');
}); });
}, },
async deleteBox({commit, dispatch}, box_id) { async deleteBox({commit, dispatch, state}, box_id) {
await axios.delete(`/2/boxes/${box_id}/`); await http.delete(`/2/boxes/${box_id}/`, state.user.token);
dispatch('loadBoxes'); dispatch('loadBoxes');
}, },
async updateItem({commit, getters}, item) { async updateItem({commit, getters, state}, item) {
const {data} = await axios.put(`/2/${getters.getEventSlug}/item/${item.uid}/`, item); const {data} = await http.put(`/2/${getters.getEventSlug}/item/${item.uid}/`, item, state.user.token);
commit('updateItem', data); commit('updateItem', data);
}, },
async markItemReturned({commit, getters}, item) { async markItemReturned({commit, getters, state}, item) {
await axios.patch(`/2/${getters.getEventSlug}/item/${item.uid}/`, {returned: true}); await http.patch(`/2/${getters.getEventSlug}/item/${item.uid}/`, {returned: true}, state.user.token);
commit('removeItem', item); commit('removeItem', item);
}, },
async deleteItem({commit, getters}, item) { async deleteItem({commit, getters, state}, item) {
await axios.delete(`/2/${getters.getEventSlug}/item/${item.uid}/`, item); await http.delete(`/2/${getters.getEventSlug}/item/${item.uid}/`, item, state.user.token);
commit('removeItem', item); commit('removeItem', item);
}, },
async postItem({commit, getters}, item) { async postItem({commit, getters, state}, item) {
commit('updateLastUsed', {box: item.box, cid: item.cid}); 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); commit('appendItem', data);
}, },
async loadTickets({commit}) { async loadTickets({commit, state}) {
const {data} = await axios.get('/2/tickets/'); const {data} = await http.get('/2/tickets/', state.user.token);
commit('replaceTickets', data); commit('replaceTickets', data);
}, },
async sendMail({commit, dispatch}, {id, message}) { async sendMail({commit, dispatch, state}, {id, message}) {
const {data} = await axios.post(`/2/tickets/${id}/reply/`, {message}); const {data} = await http.post(`/2/tickets/${id}/reply/`, {message}, state.user.token);
await dispatch('loadTickets'); await dispatch('loadTickets');
}, },
async postManualTicket({commit, dispatch}, {sender, message, title,}) { async postManualTicket({commit, dispatch, state}, {sender, message, title,}) {
const {data} = await axios.post(`/2/tickets/manual/`, { const {data} = await http.post(`/2/tickets/manual/`, {
name: title, name: title,
sender, sender,
body: message, body: message,
recipient: 'mail@c3lf.de' recipient: 'mail@c3lf.de'
}); }, state.user.token);
await dispatch('loadTickets'); await dispatch('loadTickets');
}, },
async postComment({commit, dispatch}, {id, message}) { async postComment({commit, dispatch, staee}, {id, message}) {
const {data} = await axios.post(`/2/tickets/${id}/comment/`, {comment: message}); const {data} = await http.post(`/2/tickets/${id}/comment/`, {comment: message}, state.user.token);
await dispatch('loadTickets'); await dispatch('loadTickets');
}, },
async loadUsers({commit}) { async loadUsers({commit, state}) {
const {data} = await axios.get('/2/users/'); const {data} = await http.get('/2/users/', state.user.token);
commit('replaceUsers', data); commit('replaceUsers', data);
}, },
async loadGroups({commit}) { async loadGroups({commit, state}) {
const {data} = await axios.get('/2/groups/'); const {data} = await http.get('/2/groups/', state.user.token);
commit('replaceGroups', data); commit('replaceGroups', data);
}, },
async updateTicket({commit}, ticket) { async updateTicket({commit, state}, ticket) {
const {data} = await axios.put(`/2/tickets/${ticket.id}/`, ticket); const {data} = await http.put(`/2/tickets/${ticket.id}/`, ticket, state.user.token);
commit('updateTicket', data); commit('updateTicket', data);
}, },
async updateTicketPartial({commit}, {id, ...ticket}) { async updateTicketPartial({commit, state}, {id, ...ticket}) {
const {data} = await axios.patch(`/2/tickets/${id}/`, ticket); const {data} = await http.patch(`/2/tickets/${id}/`, ticket, state.user.token);
commit('updateTicket', data); commit('updateTicket', data);
} }
}, },
plugins: [ plugins: [
persistentStatePlugin({ // TODO change remember to some kind of enable field persistentStatePlugin({ // TODO change remember to some kind of enable field
prefix: "lf_", prefix: "lf_",
debug: false, debug: true,
isLoadedKey: "persistent_loaded", isLoadedKey: "persistent_loaded",
state: [ state: [
"remember", "remember",
@ -405,24 +352,57 @@ const store = createStore({
] ]
}), }),
sharedStatePlugin({ sharedStatePlugin({
debug: false, debug: true,
isLoadedKey: "shared_loaded", isLoadedKey: "shared_loaded",
clearingMutation: "logout", clearingMutation: "logout",
state: [ state: [
"test", "test",
"state_options",
"events",
"fetchData",
"tickets", "tickets",
],
watch: [
"test",
"state_options", "state_options",
"events", "events",
"fetchData", "fetchData",
], ],
watch: [
"test",
],
mutations: [ 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; export default store;

View file

@ -24,4 +24,74 @@ function ticketStateIconLookup(ticket) {
return 'exclamation'; return 'exclamation';
} }
export {ticketStateColorLookup, ticketStateIconLookup}; 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};