stash
This commit is contained in:
parent
4645a2f48c
commit
be96901129
10 changed files with 272 additions and 111 deletions
|
@ -52,11 +52,6 @@ export default {
|
|||
},
|
||||
created: function () {
|
||||
document.title = document.location.hostname;
|
||||
this.loadEvents().then(() => {
|
||||
/*if (this.isLoggedIn) {
|
||||
this.afterLogin();
|
||||
}*/
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<script>
|
||||
|
||||
import {mapActions} from "vuex";
|
||||
import {mapActions, mapGetters, mapMutations} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "AuthenticatedImage",
|
||||
|
@ -16,6 +16,7 @@ export default {
|
|||
type: String,
|
||||
required: true
|
||||
},
|
||||
cached: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -23,8 +24,12 @@ export default {
|
|||
servers: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['getThumbnail']),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['fetchImage']),
|
||||
...mapMutations(['setThumbnail']),
|
||||
async loadImage() {
|
||||
const response = await this.fetchImage(this.src);
|
||||
const mime_type = response.headers.get("content-type");
|
||||
|
@ -32,10 +37,22 @@ export default {
|
|||
const base64 = btoa(new Uint8Array(buf)
|
||||
.reduce((data, byte) => data + String.fromCharCode(byte), ""));
|
||||
this.image_data = "data:" + mime_type + ";base64," + base64;
|
||||
if (this.cached)
|
||||
this.setThumbnail({
|
||||
url: this.src,
|
||||
data: this.image_data
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
if (this.cached) {
|
||||
const c = this.getThumbnail(this.src);
|
||||
if (c) {
|
||||
this.image_data = c;
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.loadImage();
|
||||
}, 0);
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
<ul>
|
||||
<li v-for="attachment in item.attachments" @click="openLightboxModalWith(attachment)">
|
||||
<AuthenticatedImage :src="`/media/2/256/${attachment.hash}/`" :alt="attachment.name"
|
||||
v-if="attachment.mime_type.startsWith('image/')"/>
|
||||
<AuthenticatedDataLink :href="`/media/2/256/${attachment.hash}/`" :download="attachment.name"
|
||||
v-if="attachment.mime_type.startsWith('image/')" cached/>
|
||||
<AuthenticatedDataLink :href="`/media/2/${attachment.hash}/`" :download="attachment.name"
|
||||
v-else/>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -25,7 +25,15 @@ export default {
|
|||
computed: {
|
||||
...mapState(['state_options']),
|
||||
lookupState: function () {
|
||||
return this.state_options.find(state => state.value === this.item.state);
|
||||
try {
|
||||
if (this.item.state)
|
||||
return this.state_options.find(state => state.value === this.item.state);
|
||||
} catch (e) {
|
||||
}
|
||||
return {
|
||||
text: 'Unknown',
|
||||
value: 'unknown'
|
||||
};
|
||||
},
|
||||
colorLookup: function () {
|
||||
if (this.item.state.startsWith('closed_')) {
|
||||
|
|
|
@ -4,10 +4,71 @@ export default (config) => {
|
|||
if (!('isLoadedKey' in config)) {
|
||||
throw new Error("isLoadedKey not defined in config");
|
||||
}
|
||||
if (('asyncFetch' in config) && !('lastfetched' in config)) {
|
||||
throw new Error("asyncFetch defined but lastfetched not defined in config");
|
||||
}
|
||||
|
||||
if (config.debug) console.log('plugin created');
|
||||
|
||||
/** may only be called from worker */
|
||||
|
||||
const clone = (obj) => {
|
||||
if (isProxy(obj)) {
|
||||
obj = toRaw(obj);
|
||||
}
|
||||
if (obj === null || typeof obj !== 'object') {
|
||||
return obj;
|
||||
}
|
||||
if (obj.__proto__ === ({}).__proto__) {
|
||||
return Object.assign({}, obj);
|
||||
}
|
||||
if (obj.__proto__ === [].__proto__) {
|
||||
return obj.slice();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
const deepEqual = (a, b) => {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a === null || b === null) {
|
||||
return false;
|
||||
}
|
||||
if (a.__proto__ === ({}).__proto__ && b.__proto__ === ({}).__proto__) {
|
||||
|
||||
if (Object.keys(a).length !== Object.keys(b).length) {
|
||||
return false;
|
||||
}
|
||||
for (let key in b) {
|
||||
if (!(key in a)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (let key in a) {
|
||||
if (!(key in b)) {
|
||||
return false;
|
||||
}
|
||||
if (!deepEqual(a[key], b[key])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (a.__proto__ === [].__proto__ && b.__proto__ === [].__proto__) {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (!deepEqual(a[i], b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const worker_fun = function (self, ctx) {
|
||||
/* globals WebSocket, SharedWorker, onconnect, onmessage, postMessage, close, location */
|
||||
|
||||
|
@ -18,32 +79,32 @@ export default (config) => {
|
|||
|
||||
const tryConnect = () => {
|
||||
if (self.WebSocket === undefined) {
|
||||
if(ctx.debug) console.log("no websocket support");
|
||||
if (ctx.debug) console.log("no websocket support");
|
||||
return;
|
||||
}
|
||||
if (!notify_socket || notify_socket.readyState !== WebSocket.OPEN) {
|
||||
// global location is not useful in worker loaded from data url
|
||||
const scheme = ctx.location.protocol === "https:" ? "wss" : "ws";
|
||||
if(ctx.debug) console.log("connecting to", scheme + '://' + ctx.location.host + '/ws/2/notify/');
|
||||
if (ctx.debug) console.log("connecting to", scheme + '://' + ctx.location.host + '/ws/2/notify/');
|
||||
notify_socket = new WebSocket(scheme + '://' + ctx.location.host + '/ws/2/notify/');
|
||||
notify_socket.onopen = (e) => {
|
||||
if(ctx.debug) console.log("open", JSON.stringify(e));
|
||||
if (ctx.debug) console.log("open", JSON.stringify(e));
|
||||
};
|
||||
notify_socket.onclose = (e) => {
|
||||
if(ctx.debug) console.log("close", JSON.stringify(e));
|
||||
if (ctx.debug) console.log("close", JSON.stringify(e));
|
||||
setTimeout(() => {
|
||||
tryConnect();
|
||||
}, 1000);
|
||||
};
|
||||
notify_socket.onerror = (e) => {
|
||||
if(ctx.debug) console.log("error", JSON.stringify(e));
|
||||
if (ctx.debug) console.log("error", JSON.stringify(e));
|
||||
setTimeout(() => {
|
||||
tryConnect();
|
||||
}, 1000);
|
||||
};
|
||||
notify_socket.onmessage = (e) => {
|
||||
let data = JSON.parse(e.data);
|
||||
if(ctx.debug) console.log("message", data);
|
||||
if (ctx.debug) console.log("message", data);
|
||||
//this.loadEventItems()
|
||||
//this.loadTickets()
|
||||
}
|
||||
|
@ -105,15 +166,14 @@ export default (config) => {
|
|||
case 'state_diff':
|
||||
if (message_data.key in state) {
|
||||
if (!deepEqual(state[message_data.key], message_data.old_value)) {
|
||||
if (ctx.debug) console.log("state diff old value mismatch | state:",
|
||||
state[message_data.key], " old:", message_data.old_value);
|
||||
if (ctx.debug) console.log("state diff old value mismatch | state:", state[message_data.key], " old:", message_data.old_value);
|
||||
}
|
||||
if (!deepEqual(state[message_data.key], message_data.new_value)) {
|
||||
if (ctx.debug) console.log("state diff changed | state:", state[message_data.key], " new:", message_data.new_value);
|
||||
state[message_data.key] = message_data.new_value;
|
||||
others(message_data);
|
||||
} else {
|
||||
if (ctx.debug) console.log("state diff no change | state:",
|
||||
state[message_data.key], " new:", message_data.new_value);
|
||||
if (ctx.debug) console.log("state diff no change | state:", state[message_data.key], " new:", message_data.new_value);
|
||||
}
|
||||
} else {
|
||||
if (ctx.debug) console.log("state diff key not found", message_data.key);
|
||||
|
@ -150,12 +210,13 @@ export default (config) => {
|
|||
tryConnect();
|
||||
}
|
||||
|
||||
if(ctx.debug) console.log("worker loaded");
|
||||
if (ctx.debug) console.log("worker loaded");
|
||||
}
|
||||
|
||||
const worker_context = {
|
||||
location: {...location},
|
||||
debug: config.debug
|
||||
location: {
|
||||
protocol: location.protocol, host: location.host
|
||||
}, bug: config.debug
|
||||
}
|
||||
const worker_code = '(' + worker_fun.toString() + ')(self,' + JSON.stringify(worker_context) + ')';
|
||||
const worker_url = 'data:application/javascript;base64,' + btoa(worker_code);
|
||||
|
@ -165,7 +226,7 @@ export default (config) => {
|
|||
if (config.debug) console.log('worker started');
|
||||
|
||||
const updateWorkerState = (key, new_value, old_value = null) => {
|
||||
if(new_value === old_value) {
|
||||
if (new_value === old_value) {
|
||||
if (config.debug) console.log('updateWorkerState: no change', key, new_value);
|
||||
return;
|
||||
}
|
||||
|
@ -203,19 +264,26 @@ export default (config) => {
|
|||
} else {
|
||||
for (let key in e.data.state) {
|
||||
if (key in store.state) {
|
||||
if (config.debug) console.log('worker state init received', key, e.data.state[key]);
|
||||
store.state[key] = e.data.state[key];
|
||||
if (config.debug) console.log('worker state init received', key, clone(e.data.state[key]));
|
||||
if (!deepEqual(store.state[key], e.data.state[key])) {
|
||||
store.state[key] = e.data.state[key];
|
||||
}
|
||||
} else {
|
||||
if (config.debug) console.log("state init key not found", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
store[config.isLoadedKey] = true;
|
||||
store.state[config.isLoadedKey] = true;
|
||||
if ('afterInit' in config) {
|
||||
setTimeout(() => {
|
||||
store.dispatch(config.afterInit);
|
||||
}, 0);
|
||||
}
|
||||
break;
|
||||
case 'state_diff':
|
||||
if (config.debug) console.log('state_diff', e.data);
|
||||
if (e.data.key in store.state) {
|
||||
if (config.debug) console.log('worker state update', e.data.key, e.data.new_value);
|
||||
if (config.debug) console.log('worker state update', e.data.key, clone(e.data.new_value));
|
||||
//TODO this triggers the watcher again, but we don't want that
|
||||
store.state[e.data.key] = e.data.new_value;
|
||||
} else {
|
||||
|
@ -248,7 +316,7 @@ export default (config) => {
|
|||
if ('state' in config) {
|
||||
config.watch.forEach((member) => {
|
||||
store.watch((state, getters) => state[member], (newValue, oldValue) => {
|
||||
if (config.debug) console.log('watch', member, newValue, oldValue);
|
||||
if (config.debug) console.log('watch', member, clone(newValue), clone(oldValue));
|
||||
updateWorkerState(member, newValue, oldValue);
|
||||
});
|
||||
});
|
||||
|
|
176
web/src/store.js
176
web/src/store.js
|
@ -31,9 +31,19 @@ const store = createStore({
|
|||
expiry: null,
|
||||
},
|
||||
|
||||
fetchedData: {},
|
||||
shared_loaded: false,
|
||||
thumbnailCache: {},
|
||||
fetchedData: {
|
||||
events: 0,
|
||||
items: 0,
|
||||
boxes: 0,
|
||||
tickets: 0,
|
||||
users: 0,
|
||||
groups: 0,
|
||||
states: 0,
|
||||
},
|
||||
persistent_loaded: false,
|
||||
shared_loaded: false,
|
||||
afterInitHandlers: [],
|
||||
|
||||
showAddBoxModal: false,
|
||||
},
|
||||
|
@ -75,6 +85,12 @@ const store = createStore({
|
|||
isLoggedIn(state) {
|
||||
return state.user && state.user.username !== null && state.user.token !== null;
|
||||
},
|
||||
getThumbnail: (state) => (url) => {
|
||||
if (!url) return null;
|
||||
if (!(url in state.thumbnailCache))
|
||||
return null;
|
||||
return state.thumbnailCache[url];
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
updateLastEvent(state, slug) {
|
||||
|
@ -82,21 +98,25 @@ const store = createStore({
|
|||
},
|
||||
replaceEvents(state, events) {
|
||||
state.events = events;
|
||||
state.fetchedData = {...state.fetchedData, events: Date.now()};
|
||||
},
|
||||
replaceTicketStates(state, states) {
|
||||
state.state_options = states;
|
||||
state.fetchedData = {...state.fetchedData, states: Date.now()};
|
||||
},
|
||||
changeView(state, {view, slug}) {
|
||||
router.push({path: `/${slug}/${view}`});
|
||||
},
|
||||
replaceLoadedItems(state, newItems) {
|
||||
state.loadedItems = newItems;
|
||||
state.fetchedData = {...state.fetchedData, items: Date.now()}; // TODO: manage caching items for different events and search results correctly
|
||||
},
|
||||
setItemCache(state, {slug, items}) {
|
||||
state.itemCache[slug] = items;
|
||||
},
|
||||
replaceBoxes(state, loadedBoxes) {
|
||||
state.loadedBoxes = loadedBoxes;
|
||||
state.fetchedData = {...state.fetchedData, boxes: Date.now()};
|
||||
},
|
||||
updateItem(state, updatedItem) {
|
||||
const item = state.loadedItems.filter(({uid}) => uid === updatedItem.uid)[0];
|
||||
|
@ -110,12 +130,15 @@ const store = createStore({
|
|||
},
|
||||
replaceTickets(state, tickets) {
|
||||
state.tickets = tickets;
|
||||
state.fetchedData = {...state.fetchedData, tickets: Date.now()};
|
||||
},
|
||||
replaceUsers(state, users) {
|
||||
state.users = users;
|
||||
state.fetchedData = {...state.fetchedData, users: Date.now()};
|
||||
},
|
||||
replaceGroups(state, groups) {
|
||||
state.groups = groups;
|
||||
state.fetchedData = {...state.fetchedData, groups: Date.now()};
|
||||
},
|
||||
updateTicket(state, updatedTicket) {
|
||||
const ticket = state.tickets.filter(({id}) => id === updatedTicket.id)[0];
|
||||
|
@ -169,6 +192,9 @@ const store = createStore({
|
|||
setTest(state, test) {
|
||||
state.test = test;
|
||||
},
|
||||
setThumbnail(state, {url, data}) {
|
||||
state.thumbnailCache[url] = data;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async login({commit}, {username, password, remember}) {
|
||||
|
@ -213,32 +239,50 @@ const store = createStore({
|
|||
store.commit('logout');
|
||||
},
|
||||
//async verifyToken({commit, state}) {
|
||||
/*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]);
|
||||
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) {
|
||||
const user = dispatch('loadUserInfo');
|
||||
await Promise.all([user]);
|
||||
promises.push(dispatch('loadUserInfo'));
|
||||
}
|
||||
},*/
|
||||
await Promise.all(promises);
|
||||
},
|
||||
async afterSharedInit({dispatch, state}) {
|
||||
const handlers = state.afterInitHandlers;
|
||||
state.afterInitHandlers = [];
|
||||
await Promise.all(handlers.map(h => h()).flat());
|
||||
},
|
||||
scheduleAfterInit({dispatch, state}, handler) {
|
||||
if (state.shared_loaded) {
|
||||
Promise.all(handler()).then(() => {
|
||||
});
|
||||
} else {
|
||||
state.afterInitHandlers.push(handler);
|
||||
}
|
||||
},
|
||||
async fetchImage({state}, url) {
|
||||
return await fetch(url, {headers: {'Authorization': `Token ${state.user.token}`}});
|
||||
},
|
||||
async loadUserInfo({commit, state}) {
|
||||
const {data} = await http.get('/2/self/', state.user.token);
|
||||
const {data, success} = await http.get('/2/self/', state.user.token);
|
||||
commit('setPermissions', data.permissions);
|
||||
},
|
||||
async loadEvents({commit, state}) {
|
||||
const {data} = await http.get('/2/events/', state.user.token);
|
||||
commit('replaceEvents', data);
|
||||
if (!state.user.token) return;
|
||||
if (state.fetchedData.events > Date.now() - 1000 * 60 * 60 * 24) return;
|
||||
const {data, success} = await http.get('/2/events/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceEvents', data);
|
||||
},
|
||||
async fetchTicketStates({commit, state}) {
|
||||
const {data} = await http.get('/2/tickets/states/', state.user.token);
|
||||
commit('replaceTicketStates', data);
|
||||
if (!state.user.token) return;
|
||||
if (state.fetchedData.states > Date.now() - 1000 * 60 * 60 * 24) return;
|
||||
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}/`});
|
||||
|
@ -251,15 +295,19 @@ const store = createStore({
|
|||
router.push({path: `/${getters.getEventSlug}/items/`, query: {box}});
|
||||
},
|
||||
async loadEventItems({commit, getters, state}) {
|
||||
if (!state.user.token) return;
|
||||
if (state.fetchedData.items > Date.now() - 1000 * 60 * 60 * 24) return;
|
||||
try {
|
||||
commit('replaceLoadedItems', []);
|
||||
const slug = getters.getEventSlug;
|
||||
if (slug in state.itemCache) {
|
||||
commit('replaceLoadedItems', state.itemCache[slug]);
|
||||
}
|
||||
const {data} = await http.get(`/2/${slug}/items/`, state.user.token);
|
||||
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");
|
||||
}
|
||||
|
@ -268,15 +316,19 @@ const store = createStore({
|
|||
const foo = utf8.encode(query);
|
||||
const bar = base64.encode(foo);
|
||||
|
||||
const {data} = await http.get(`/2/${getters.getEventSlug}/items/${bar}/`, state.user.token);
|
||||
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, state}) {
|
||||
const {data} = await http.get('/2/boxes/', state.user.token);
|
||||
commit('replaceBoxes', data);
|
||||
if (!state.user.token) return;
|
||||
if (state.fetchedData.boxes > Date.now() - 1000 * 60 * 60 * 24) return;
|
||||
const {data, success} = await http.get('/2/boxes/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceBoxes', data);
|
||||
},
|
||||
async createBox({commit, dispatch, state}, box) {
|
||||
const {data} = await http.post('/2/boxes/', box, state.user.token);
|
||||
const {data, success} = await http.post('/2/boxes/', box, state.user.token);
|
||||
commit('replaceBoxes', data);
|
||||
dispatch('loadBoxes').then(() => {
|
||||
commit('closeAddBoxModal');
|
||||
|
@ -287,7 +339,10 @@ const store = createStore({
|
|||
dispatch('loadBoxes');
|
||||
},
|
||||
async updateItem({commit, getters, state}, item) {
|
||||
const {data} = await http.put(`/2/${getters.getEventSlug}/item/${item.uid}/`, item, state.user.token);
|
||||
const {
|
||||
data,
|
||||
success
|
||||
} = await http.put(`/2/${getters.getEventSlug}/item/${item.uid}/`, item, state.user.token);
|
||||
commit('updateItem', data);
|
||||
},
|
||||
async markItemReturned({commit, getters, state}, item) {
|
||||
|
@ -300,19 +355,22 @@ const store = createStore({
|
|||
},
|
||||
async postItem({commit, getters, state}, item) {
|
||||
commit('updateLastUsed', {box: item.box, cid: item.cid});
|
||||
const {data} = await http.post(`/2/${getters.getEventSlug}/item/`, item, state.user.token);
|
||||
const {data, success} = await http.post(`/2/${getters.getEventSlug}/item/`, item, state.user.token);
|
||||
commit('appendItem', data);
|
||||
},
|
||||
async loadTickets({commit, state}) {
|
||||
const {data} = await http.get('/2/tickets/', state.user.token);
|
||||
commit('replaceTickets', data);
|
||||
if (!state.user.token) return;
|
||||
if (state.fetchedData.tickets > Date.now() - 1000 * 60 * 60 * 24) return;
|
||||
const {data, success} = await http.get('/2/tickets/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceTickets', data);
|
||||
},
|
||||
async sendMail({commit, dispatch, state}, {id, message}) {
|
||||
const {data} = await http.post(`/2/tickets/${id}/reply/`, {message}, state.user.token);
|
||||
const {data, success} = await http.post(`/2/tickets/${id}/reply/`, {message}, state.user.token);
|
||||
await dispatch('loadTickets');
|
||||
},
|
||||
async postManualTicket({commit, dispatch, state}, {sender, message, title,}) {
|
||||
const {data} = await http.post(`/2/tickets/manual/`, {
|
||||
const {data, success} = await http.post(`/2/tickets/manual/`, {
|
||||
name: title,
|
||||
sender,
|
||||
body: message,
|
||||
|
@ -320,53 +378,68 @@ const store = createStore({
|
|||
}, state.user.token);
|
||||
await dispatch('loadTickets');
|
||||
},
|
||||
async postComment({commit, dispatch, staee}, {id, message}) {
|
||||
const {data} = await http.post(`/2/tickets/${id}/comment/`, {comment: message}, state.user.token);
|
||||
async postComment({commit, dispatch, state}, {id, message}) {
|
||||
const {data, success} = await http.post(`/2/tickets/${id}/comment/`, {comment: message}, state.user.token);
|
||||
await dispatch('loadTickets');
|
||||
},
|
||||
async loadUsers({commit, state}) {
|
||||
const {data} = await http.get('/2/users/', state.user.token);
|
||||
commit('replaceUsers', data);
|
||||
if (!state.user.token) return;
|
||||
if (state.fetchedData.users > Date.now() - 1000 * 60 * 60 * 24) return;
|
||||
const {data, success} = await http.get('/2/users/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceUsers', data);
|
||||
},
|
||||
async loadGroups({commit, state}) {
|
||||
const {data} = await http.get('/2/groups/', state.user.token);
|
||||
commit('replaceGroups', data);
|
||||
if (!state.user.token) return;
|
||||
if (state.fetchedData.groups > Date.now() - 1000 * 60 * 60 * 24) return;
|
||||
const {data, success} = await http.get('/2/groups/', state.user.token);
|
||||
if (data && success)
|
||||
commit('replaceGroups', data);
|
||||
},
|
||||
async updateTicket({commit, state}, ticket) {
|
||||
const {data} = await http.put(`/2/tickets/${ticket.id}/`, ticket, state.user.token);
|
||||
const {data, success} = await http.put(`/2/tickets/${ticket.id}/`, ticket, state.user.token);
|
||||
commit('updateTicket', data);
|
||||
},
|
||||
async updateTicketPartial({commit, state}, {id, ...ticket}) {
|
||||
const {data} = await http.patch(`/2/tickets/${id}/`, ticket, state.user.token);
|
||||
const {data, success} = 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: true,
|
||||
debug: false,
|
||||
isLoadedKey: "persistent_loaded",
|
||||
state: [
|
||||
"remember",
|
||||
"user",
|
||||
"events",
|
||||
]
|
||||
}),
|
||||
sharedStatePlugin({
|
||||
debug: true,
|
||||
debug: false,
|
||||
isLoadedKey: "shared_loaded",
|
||||
clearingMutation: "logout",
|
||||
afterInit: "afterSharedInit",
|
||||
state: [
|
||||
"test",
|
||||
"state_options",
|
||||
"events",
|
||||
"fetchData",
|
||||
"fetchedData",
|
||||
"tickets",
|
||||
"users",
|
||||
"groups",
|
||||
"loadedBoxes",
|
||||
"loadedItems",
|
||||
],
|
||||
watch: [
|
||||
"test",
|
||||
"state_options",
|
||||
"events",
|
||||
"fetchData",
|
||||
"fetchedData",
|
||||
"tickets",
|
||||
"users",
|
||||
"groups",
|
||||
"loadedBoxes",
|
||||
"loadedItems",
|
||||
],
|
||||
mutations: [
|
||||
//"replaceTickets",
|
||||
|
@ -375,19 +448,6 @@ const store = createStore({
|
|||
],
|
||||
});
|
||||
|
||||
// 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) {
|
||||
|
|
|
@ -25,6 +25,20 @@ function ticketStateIconLookup(ticket) {
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -37,19 +51,8 @@ const http = {
|
|||
},
|
||||
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()};
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
},
|
||||
put: async (url, data, token) => {
|
||||
if (!token) {
|
||||
|
@ -63,7 +66,8 @@ const http = {
|
|||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
return {data: await response.json()};
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
},
|
||||
patch: async (url, data, token) => {
|
||||
if (!token) {
|
||||
|
@ -77,7 +81,8 @@ const http = {
|
|||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
return {data: await response.json()};
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
},
|
||||
delete: async (url, token) => {
|
||||
if (!token) {
|
||||
|
@ -90,7 +95,8 @@ const http = {
|
|||
"Authorization": `Token ${token}`,
|
||||
},
|
||||
});
|
||||
return {data: await response.json()};
|
||||
const success = response.status === 200 || response.status === 201;
|
||||
return {data: await response.json() || {}, success};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,13 +23,15 @@
|
|||
>
|
||||
<template #actions="{ item }">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-success" @click.stop="confirm('return Item?') && markItemReturned(item)" title="returned">
|
||||
<button class="btn btn-success"
|
||||
@click.stop="confirm('return Item?') && markItemReturned(item)" title="returned">
|
||||
<font-awesome-icon icon="check"/>
|
||||
</button>
|
||||
<button class="btn btn-secondary" @click.stop="openEditingModalWith(item)" title="edit">
|
||||
<font-awesome-icon icon="edit"/>
|
||||
</button>
|
||||
<button class="btn btn-danger" @click.stop="confirm('delete Item?') && deleteItem(item)" title="delete">
|
||||
<button class="btn btn-danger" @click.stop="confirm('delete Item?') && deleteItem(item)"
|
||||
title="delete">
|
||||
<font-awesome-icon icon="trash"/>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -45,7 +47,7 @@
|
|||
v-slot="{ item }"
|
||||
@itemActivated="openLightboxModalWith($event)"
|
||||
>
|
||||
<AuthenticatedImage v-if="item.file"
|
||||
<AuthenticatedImage v-if="item.file" cached
|
||||
:src="`/media/2/256/${item.file}/`"
|
||||
class="card-img-top img-fluid"
|
||||
/>
|
||||
|
@ -93,7 +95,7 @@ export default {
|
|||
...mapGetters(['layout']),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['deleteItem', 'markItemReturned']),
|
||||
...mapActions(['deleteItem', 'markItemReturned', 'loadEventItems', 'scheduleAfterInit']),
|
||||
openLightboxModalWith(item) {
|
||||
this.lightboxHash = item.file;
|
||||
},
|
||||
|
@ -113,6 +115,9 @@ export default {
|
|||
confirm(message) {
|
||||
return window.confirm(message);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.scheduleAfterInit(() => [this.loadEventItems()]);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -62,6 +62,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
...mapActions(['deleteItem', 'markItemReturned', 'sendMail', 'updateTicketPartial', 'postComment']),
|
||||
...mapActions(['loadTickets', 'fetchTicketStates', 'loadUsers', 'scheduleAfterInit']),
|
||||
handleMail(mail) {
|
||||
this.sendMail({
|
||||
id: this.ticket.id,
|
||||
|
@ -87,7 +88,9 @@ export default {
|
|||
})
|
||||
}
|
||||
},
|
||||
created() {}
|
||||
mounted() {
|
||||
this.scheduleAfterInit(() => [this.fetchTicketStates(), this.loadTickets(), this.loadUsers()]);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ export default {
|
|||
...mapGetters(['stateInfo', 'getEventSlug', 'layout']),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['loadTickets', 'fetchTicketStates']),
|
||||
...mapActions(['loadTickets', 'fetchTicketStates', 'scheduleAfterInit']),
|
||||
gotoDetail(ticket) {
|
||||
this.$router.push({name: 'ticket', params: {id: ticket.id}});
|
||||
},
|
||||
|
@ -80,9 +80,8 @@ export default {
|
|||
};
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.fetchTicketStates();
|
||||
this.loadTickets();
|
||||
mounted() {
|
||||
this.scheduleAfterInit(() => [this.fetchTicketStates(), this.loadTickets()]);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
Loading…
Reference in a new issue