diff --git a/core/authentication/admin.py b/core/authentication/admin.py index 0024cb0..ed88ace 100644 --- a/core/authentication/admin.py +++ b/core/authentication/admin.py @@ -10,5 +10,8 @@ class ExtendedUserAdmin(UserAdmin): ordering = ('username',) filter_horizontal = ('groups', 'user_permissions', 'permissions') + def permissions(self, obj): + return ', '.join(obj.get_all_permissions()) + admin.site.register(ExtendedUser, ExtendedUserAdmin) diff --git a/core/files/media_v2.py b/core/files/media_v2.py index 9cc8f23..d62ee98 100644 --- a/core/files/media_v2.py +++ b/core/files/media_v2.py @@ -33,7 +33,7 @@ def media_urls(request, hash): headers={ 'X-Accel-Redirect': f'/redirect_media/{hash_path}', 'Access-Control-Allow-Origin': '*', - 'Cache-Control': 'max-age=31536000, private, immutable', + 'Cache-Control': 'max-age=31536000, private', 'Expires': datetime.utcnow() + timedelta(days=365), 'Age': 0, 'ETag': file.hash, @@ -74,7 +74,7 @@ def thumbnail_urls(request, size, hash): headers={ 'X-Accel-Redirect': f'/redirect_thumbnail/{size}/{hash_path}', 'Access-Control-Allow-Origin': '*', - 'Cache-Control': 'max-age=31536000, private, immutable', + 'Cache-Control': 'max-age=31536000, private', 'Expires': datetime.utcnow() + timedelta(days=365), 'Age': 0, 'ETag': file.hash + "_" + str(size), diff --git a/core/files/models.py b/core/files/models.py index 33a6265..df46fd3 100644 --- a/core/files/models.py +++ b/core/files/models.py @@ -90,6 +90,4 @@ class AbstractFile(models.Model): class File(AbstractFile): item = models.ForeignKey(Item, models.CASCADE, db_column='iid', null=True, blank=True, related_name='files') - - def __str__(self): - return self.hash + pass diff --git a/core/inventory/api_v1.py b/core/inventory/api_v1.py index d5a1e29..52c6ed0 100644 --- a/core/inventory/api_v1.py +++ b/core/inventory/api_v1.py @@ -1,4 +1,5 @@ -from django.utils import timezone +from datetime import datetime + from django.urls import re_path from rest_framework import routers, viewsets, serializers from rest_framework.decorators import api_view, permission_classes, authentication_classes @@ -86,7 +87,7 @@ class ItemSerializer(serializers.ModelSerializer): def update(self, instance, validated_data): if 'returned' in validated_data: if validated_data['returned']: - validated_data['returned_at'] = timezone.now() + validated_data['returned_at'] = datetime.now() validated_data.pop('returned') if 'dataImage' in validated_data: file = File.objects.create(data=validated_data['dataImage']) diff --git a/core/inventory/models.py b/core/inventory/models.py index 8b3d018..ca0aeb7 100644 --- a/core/inventory/models.py +++ b/core/inventory/models.py @@ -35,9 +35,6 @@ class Item(SoftDeleteModel): ('match_item', 'Can match item') ] - def __str__(self): - return '[' + str(self.uid) + ']' + self.description - class Container(SoftDeleteModel): cid = models.AutoField(primary_key=True) @@ -45,9 +42,6 @@ class Container(SoftDeleteModel): created_at = models.DateTimeField(blank=True, null=True) updated_at = models.DateTimeField(blank=True, null=True) - def __str__(self): - return '[' + str(self.cid) + ']' + self.name - class Event(models.Model): eid = models.AutoField(primary_key=True) @@ -59,6 +53,3 @@ class Event(models.Model): post_end = models.DateTimeField(blank=True, null=True) created_at = models.DateTimeField(null=True, auto_now_add=True) updated_at = models.DateTimeField(blank=True, null=True) - - def __str__(self): - return '[' + str(self.slug) + ']' + self.name diff --git a/core/inventory/tests/v2/test_items.py b/core/inventory/tests/v2/test_items.py index 056b38c..ef61333 100644 --- a/core/inventory/tests/v2/test_items.py +++ b/core/inventory/tests/v2/test_items.py @@ -1,4 +1,5 @@ -from django.utils import timezone +from datetime import datetime + from django.test import TestCase, Client from django.contrib.auth.models import Permission from knox.models import AuthToken @@ -163,7 +164,7 @@ class ItemTestCase(TestCase): response = self.client.get(f'/api/2/{self.event.slug}/item/') self.assertEqual(response.status_code, 200) self.assertEqual(len(response.json()), 2) - item2.returned_at = timezone.now() + item2.returned_at = datetime.now() item2.save() response = self.client.get(f'/api/2/{self.event.slug}/item/') self.assertEqual(response.status_code, 200) diff --git a/core/mail/protocol.py b/core/mail/protocol.py index cfd25ce..bc83230 100644 --- a/core/mail/protocol.py +++ b/core/mail/protocol.py @@ -1,8 +1,8 @@ import logging import aiosmtplib +from asgiref.sync import sync_to_async from channels.layers import get_channel_layer -from channels.db import database_sync_to_async from django.core.files.base import ContentFile from mail.models import Email, EventAddress, EmailAttachment @@ -82,7 +82,8 @@ def make_reply(reply_email, references=None, event=None): return reply -async def send_smtp(message): +async def send_smtp(message, log): + log.info('Sending message to %s' % message['To']) await aiosmtplib.send(message, hostname="127.0.0.1", port=25, use_tls=False, start_tls=False) @@ -147,9 +148,9 @@ def parse_email_body(raw, log=None): attachments.append(attachment) if 'inline' in cdispo: body = body + f'' - log.info("Image %s %s", ctype, attachment.id) + log.info("Image", ctype, attachment.id) else: - log.info("Attachment %s %s", ctype, cdispo) + log.info("Attachment", ctype, cdispo) else: if parsed.get_content_type() == 'text/plain': body = parsed.get_payload() @@ -160,7 +161,7 @@ def parse_email_body(raw, log=None): soup = BeautifulSoup(body, 'html.parser') body = re.sub(r'([\r\n]+.?)*[\r\n]', r'\n', soup.get_text()).strip('\n') else: - log.warning("Unknown content type %s", parsed.get_content_type()) + log.warning("Unknown content type", parsed.get_content_type()) body = "Unknown content type" body = unescape_and_decode_quoted_printable(body) body = unescape_and_decode_base64(body) @@ -171,7 +172,6 @@ def parse_email_body(raw, log=None): return parsed, body, attachments -@database_sync_to_async def receive_email(envelope, log=None): parsed, body, attachments = parse_email_body(envelope.content, log) @@ -255,10 +255,9 @@ class LMTPHandler: content = None try: content = envelope.content - email, new, reply = await receive_email(envelope, log) + email, new, reply = await sync_to_async(receive_email)(envelope, log) log.info(f"Created email {email.id}") - systemevent = await database_sync_to_async(SystemEvent.objects.create)(type='email received', - reference=email.id) + systemevent = await sync_to_async(SystemEvent.objects.create)(type='email received', reference=email.id) log.info(f"Created system event {systemevent.id}") channel_layer = get_channel_layer() await channel_layer.group_send( @@ -267,15 +266,14 @@ class LMTPHandler: ) log.info(f"Sent message to frontend") if new and reply: - log.info('Sending message to %s' % reply['To']) - await send_smtp(reply) + await send_smtp(reply, log) log.info("Sent auto reply") return '250 Message accepted for delivery' except Exception as e: - from hashlib import sha256 - random_filename = 'mail-' + sha256(content).hexdigest() + import uuid + random_filename = 'mail-' + str(uuid.uuid4()) with open(random_filename, 'wb') as f: f.write(content) - log.error(f"Saved email to {random_filename} because of error %s (%s)", e, type(e)) + log.error(type(e), e, f"Saved email to {random_filename}") return '451 Internal server error' diff --git a/core/tickets/api_v2.py b/core/tickets/api_v2.py index 6557a98..9b9855d 100644 --- a/core/tickets/api_v2.py +++ b/core/tickets/api_v2.py @@ -47,7 +47,8 @@ def reply(request, pk): body=request.data['message'], in_reply_to=first_mail.reference, ) - async_to_sync(send_smtp)(make_reply(mail, references)) + log = logging.getLogger('mail.log') + async_to_sync(send_smtp)(make_reply(mail, references), log) return Response({'status': 'ok'}, status=status.HTTP_201_CREATED) diff --git a/core/tickets/models.py b/core/tickets/models.py index 6dd42c3..7d90052 100644 --- a/core/tickets/models.py +++ b/core/tickets/models.py @@ -64,9 +64,6 @@ class IssueThread(SoftDeleteModel): return self.assignments.create(assigned_to=value) - def __str__(self): - return '[' + str(self.id) + '][' + self.short_uuid() + '] ' + self.name - class Meta: permissions = [ ('send_mail', 'Can send mail'), @@ -94,9 +91,6 @@ class Comment(models.Model): comment = models.TextField() timestamp = models.DateTimeField(auto_now_add=True) - def __str__(self): - return str(self.issue_thread) + ' comment #' + str(self.id) - class StateChange(models.Model): id = models.AutoField(primary_key=True) @@ -104,15 +98,9 @@ class StateChange(models.Model): state = models.CharField(max_length=255, choices=STATE_CHOICES, default='pending_new') timestamp = models.DateTimeField(auto_now_add=True) - def __str__(self): - return str(self.issue_thread) + ' state change to ' + self.state - class Assignment(models.Model): id = models.AutoField(primary_key=True) issue_thread = models.ForeignKey(IssueThread, on_delete=models.CASCADE, related_name='assignments') assigned_to = models.ForeignKey(ExtendedUser, on_delete=models.CASCADE, related_name='assigned_tickets') timestamp = models.DateTimeField(auto_now_add=True) - - def __str__(self): - return str(self.issue_thread) + ' assigned to ' + self.assigned_to.username diff --git a/web/src/App.vue b/web/src/App.vue index 83a3bb2..ede1d16 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -28,7 +28,7 @@ export default { }), methods: { ...mapMutations(['removeToast', 'createToast', 'closeAddBoxModal', 'openAddBoxModal']), - ...mapActions(['loadEvents', 'scheduleAfterInit']), + ...mapActions(['loadEvents']), openAddItemModal() { this.addItemModalOpen = true; }, @@ -44,7 +44,6 @@ export default { }, created: function () { document.title = document.location.hostname; - this.scheduleAfterInit(() => [this.loadEvents()]); } }; diff --git a/web/src/components/AddItemModal.vue b/web/src/components/AddItemModal.vue index a3c23fd..c90829f 100644 --- a/web/src/components/AddItemModal.vue +++ b/web/src/components/AddItemModal.vue @@ -27,19 +27,16 @@ export default { computed: { ...mapState(['lastUsed']) }, + created() { + this.item = {box: this.lastUsed.box || '', cid: this.lastUsed.cid || ''}; + }, methods: { - ...mapActions(['postItem', 'loadBoxes', 'scheduleAfterInit']), + ...mapActions(['postItem']), saveNewItem() { this.postItem(this.item).then(() => { this.$emit('close'); }); } - }, - created() { - this.item = {box: this.lastUsed.box || '', cid: this.lastUsed.cid || ''}; - }, - mounted() { - this.scheduleAfterInit(() => [this.loadBoxes()]); } }; diff --git a/web/src/shared-state-plugin/index.js b/web/src/shared-state-plugin/index.js deleted file mode 100644 index 67397d0..0000000 --- a/web/src/shared-state-plugin/index.js +++ /dev/null @@ -1,345 +0,0 @@ -import {isProxy, toRaw} from 'vue'; - -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'); - - 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 toRawRecursive = (obj) => { - if (isProxy(obj)) { - obj = toRaw(obj); - } - if (obj === null || typeof obj !== 'object') { - return obj; - } - if (obj.__proto__ === ({}).__proto__) { - const new_obj = {}; - for (let key in obj) { - new_obj[key] = toRawRecursive(obj[key]); - } - return new_obj; - } - if (obj.__proto__ === [].__proto__) { - return obj.map((item) => toRawRecursive(item)); - } - return obj; - } - - /** may only be called from worker */ - const worker_fun = function (self, ctx) { - /* globals WebSocket, SharedWorker, onconnect, onmessage, postMessage, close, location */ - - let intialized = false; - let state = {}; - let ports = []; - let notify_socket; - - const tryConnect = () => { - if (self.WebSocket === undefined) { - 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/'); - notify_socket = new WebSocket(scheme + '://' + ctx.location.host + '/ws/2/notify/'); - notify_socket.onopen = (e) => { - if (ctx.debug) console.log("open", JSON.stringify(e)); - }; - notify_socket.onclose = (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)); - setTimeout(() => { - tryConnect(); - }, 1000); - }; - notify_socket.onmessage = (e) => { - let data = JSON.parse(e.data); - if (ctx.debug) console.log("message", data); - //this.loadEventItems() - //this.loadTickets() - } - } - } - - 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 handle_message = (message_data, reply, others, all) => { - switch (message_data.type) { - case 'state_init': - if (!intialized) { - intialized = true; - state = message_data.state; - reply({type: 'state_init', first: true}); - } else { - reply({type: 'state_init', first: false, state: state}); - } - break; - 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 (!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); - } - } else { - if (ctx.debug) console.log("state diff key not found", message_data.key); - } - break; - default: - if (ctx.debug) console.log("unknown message", message_data); - } - } - - onconnect = (connect_event) => { - const port = connect_event.ports[0]; - ports.push(port); - port.onmessage = (message_event) => { - const reply = (message_data) => { - port.postMessage(message_data); - } - const others = (message_data) => { - for (let i = 0; i < ports.length; i++) { - if (ports[i] !== port) { - ports[i].postMessage(message_data); - } - } - } - const all = (message_data) => { - for (let i = 0; i < ports.length; i++) { - ports[i].postMessage(message_data); - } - } - handle_message(message_event.data, reply, others, all); - } - port.start(); - if (ctx.debug) console.log("worker connected", JSON.stringify(connect_event)); - tryConnect(); - } - - if (ctx.debug) console.log("worker loaded"); - } - - const worker_context = { - 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); - - const worker = new SharedWorker(worker_url, 'vuex-shared-state-plugin'); - worker.port.start(); - 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, - new_value: isProxy(new_value) ? toRawRecursive(new_value) : new_value, - old_value: isProxy(old_value) ? toRawRecursive(old_value) : old_value - }); - } - - const registerInitialState = (keys, local_state) => { - const value = keys.reduce((obj, key) => { - obj[key] = isProxy(local_state[key]) ? toRawRecursive(local_state[key]) : local_state[key]; - return obj; - }, {}); - if (config.debug) console.log('registerInitilState', value); - worker.port.postMessage({ - type: 'state_init', state: value - }); - } - - return (store) => { - - worker.port.onmessage = function (e) { - switch (e.data.type) { - case 'state_init': - if (config.debug) console.log('state_init', e.data); - if (e.data.first) { - if (config.debug) console.log('worker state initialized'); - } else { - for (let key in e.data.state) { - if (key in store.state) { - 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.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, 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 { - if (config.debug) console.log("state diff key not found", e.data.key); - } - break; - default: - if (config.debug) console.log("unknown message", e.data); - } - }; - - registerInitialState(config.state, store.state); - - if ('mutations' in config) { - store.subscribe((mutation, state) => { - if (mutation.type in config.mutations) { - console.log(mutation.type, mutation.payload); - console.log(state); - } - }); - } - /*if ('actions' in config) { - store.subscribeAction((action, state) => { - if (action.type in config.actions) { - console.log(action.type, action.payload); - console.log(state); - } - }); - }*/ - if ('state' in config) { - config.watch.forEach((member) => { - store.watch((state, getters) => state[member], (newValue, oldValue) => { - if (config.debug) console.log('watch', member, clone(newValue), clone(oldValue)); - updateWorkerState(member, newValue, oldValue); - }); - }); - } - }; -} \ No newline at end of file diff --git a/web/src/store.js b/web/src/store.js index 7ee6614..94bfc70 100644 --- a/web/src/store.js +++ b/web/src/store.js @@ -4,9 +4,8 @@ import router from './router'; import * as base64 from 'base-64'; import * as utf8 from 'utf8'; import {ticketStateColorLookup, ticketStateIconLookup, http} from "@/utils"; -import sharedStatePlugin from "@/shared-state-plugin"; + import persistentStatePlugin from "@/persistent-state-plugin"; -import {triggerRef} from "vue"; const store = createStore({ state: { @@ -21,7 +20,6 @@ const store = createStore({ groups: [], state_options: [], lastEvent: '37C3', - lastUsed: {}, remember: false, user: { username: null, @@ -32,19 +30,7 @@ const store = createStore({ }, 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, }, getters: { @@ -94,33 +80,26 @@ const store = createStore({ }, }, mutations: { - updateLastUsed(state, diff) { - state.lastUsed = {...state.lastUsed, ...diff}; - }, updateLastEvent(state, slug) { state.lastEvent = slug; }, 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]; @@ -134,21 +113,16 @@ const store = createStore({ }, replaceTickets(state, tickets) { state.tickets = tickets; - state.fetchedData = {...state.fetchedData, tickets: Date.now()}; + }, + replaceUsers(state, users) { + state.users = users; + }, + replaceGroups(state, groups) { + state.groups = groups; }, updateTicket(state, updatedTicket) { const ticket = state.tickets.filter(({id}) => id === updatedTicket.id)[0]; Object.assign(ticket, updatedTicket); - //triggerRef(state.tickets); - state.tickets = [...state.tickets]; - }, - 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()}; }, openAddBoxModal(state) { state.showAddBoxModal = true; @@ -253,19 +227,6 @@ const store = createStore({ } 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}`}}); }, @@ -274,15 +235,11 @@ const store = createStore({ commit('setPermissions', data.permissions); }, async loadEvents({commit, state}) { - 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}) { - 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); @@ -298,8 +255,6 @@ 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; @@ -324,8 +279,6 @@ const store = createStore({ commit('replaceLoadedItems', data); }, async loadBoxes({commit, state}) { - 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); @@ -362,8 +315,6 @@ const store = createStore({ commit('appendItem', data); }, async loadTickets({commit, state}) { - 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); @@ -371,7 +322,6 @@ const store = createStore({ async sendMail({commit, dispatch, state}, {id, message}) { const {data, success} = await http.post(`/2/tickets/${id}/reply/`, {message}, state.user.token); if (data && success) { - state.fetchedData.tickets = 0; await dispatch('loadTickets'); } }, @@ -387,20 +337,15 @@ const store = createStore({ async postComment({commit, dispatch, state}, {id, message}) { const {data, success} = await http.post(`/2/tickets/${id}/comment/`, {comment: message}, state.user.token); if (data && success) { - state.fetchedData.tickets = 0; await dispatch('loadTickets'); } }, async loadUsers({commit, state}) { - 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}) { - 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); @@ -423,38 +368,8 @@ const store = createStore({ "remember", "user", "events", - "lastUsed", ] }), - sharedStatePlugin({ - debug: true, - isLoadedKey: "shared_loaded", - clearingMutation: "logout", - afterInit: "afterSharedInit", - state: [ - "test", - "state_options", - "fetchedData", - "tickets", - "users", - "groups", - "loadedBoxes", - "loadedItems", - ], - watch: [ - "test", - "state_options", - "fetchedData", - "tickets", - "users", - "groups", - "loadedBoxes", - "loadedItems", - ], - mutations: [ - //"replaceTickets", - ], - }), ], }); diff --git a/web/src/views/Items.vue b/web/src/views/Items.vue index 5824999..2eec96f 100644 --- a/web/src/views/Items.vue +++ b/web/src/views/Items.vue @@ -93,7 +93,7 @@ export default { ...mapGetters(['layout']), }, methods: { - ...mapActions(['deleteItem', 'markItemReturned', 'loadEventItems', 'updateItem', 'scheduleAfterInit']), + ...mapActions(['deleteItem', 'markItemReturned', 'loadEventItems', 'updateItem']), openLightboxModalWith(item) { this.lightboxHash = item.file; }, @@ -115,7 +115,7 @@ export default { } }, mounted() { - this.scheduleAfterInit(() => [this.loadEventItems()]); + this.loadEventItems(); } }; diff --git a/web/src/views/Ticket.vue b/web/src/views/Ticket.vue index b4d1e0e..b8c0cf9 100644 --- a/web/src/views/Ticket.vue +++ b/web/src/views/Ticket.vue @@ -62,7 +62,7 @@ export default { }, methods: { ...mapActions(['deleteItem', 'markItemReturned', 'sendMail', 'updateTicketPartial', 'postComment']), - ...mapActions(['loadTickets', 'fetchTicketStates', 'loadUsers', 'scheduleAfterInit']), + ...mapActions(['loadTickets', 'loadUsers', 'fetchTicketStates']), handleMail(mail) { this.sendMail({ id: this.ticket.id, @@ -86,10 +86,12 @@ export default { id: ticket.id, assigned_to: ticket.assigned_to }) - }, + } }, - mounted() { - this.scheduleAfterInit(() => [this.fetchTicketStates(), this.loadTickets(), this.loadUsers()]); + created() { + this.fetchTicketStates() + this.loadTickets() + this.loadUsers() } }; diff --git a/web/src/views/Tickets.vue b/web/src/views/Tickets.vue index 40b2a9c..0b31e4d 100644 --- a/web/src/views/Tickets.vue +++ b/web/src/views/Tickets.vue @@ -65,7 +65,7 @@ export default { ...mapGetters(['stateInfo', 'getEventSlug', 'layout']), }, methods: { - ...mapActions(['loadTickets', 'fetchTicketStates', 'scheduleAfterInit']), + ...mapActions(['loadTickets', 'fetchTicketStates']), gotoDetail(ticket) { this.$router.push({name: 'ticket', params: {id: ticket.id}}); }, @@ -80,8 +80,9 @@ export default { }; } }, - mounted() { - this.scheduleAfterInit(() => [this.fetchTicketStates(), this.loadTickets()]); + created() { + this.fetchTicketStates(); + this.loadTickets(); } };