From 4645a2f48c92652047b63c8f1a7aa43c6c790cfb Mon Sep 17 00:00:00 2001 From: jedi Date: Fri, 26 Jan 2024 01:03:00 +0100 Subject: [PATCH] stash --- web/src/App.vue | 6 +- web/src/shared-state-plugin/index.js | 8 ++ web/src/store.js | 198 ++++++++++++--------------- web/src/utils.js | 72 +++++++++- web/src/views/Login.vue | 2 +- 5 files changed, 172 insertions(+), 114 deletions(-) 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 {