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: {
...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();
}
}*/
});
}
};

View file

@ -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,

View file

@ -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 = `
<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({
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;

View file

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