format tickets in Tickets.vue
This commit is contained in:
parent
6dad675d1e
commit
3a5f35fa5d
7 changed files with 79 additions and 8 deletions
|
@ -102,11 +102,12 @@ class LMTPHandlerTestCase(TestCase): # TODO replace with less hacky test
|
||||||
self.assertTrue(Email.objects.all()[1].reference.endswith("@localhost>"))
|
self.assertTrue(Email.objects.all()[1].reference.endswith("@localhost>"))
|
||||||
self.assertEqual("<1@test>", Email.objects.all()[1].in_reply_to)
|
self.assertEqual("<1@test>", Email.objects.all()[1].in_reply_to)
|
||||||
self.assertEqual('test', IssueThread.objects.all()[0].name)
|
self.assertEqual('test', IssueThread.objects.all()[0].name)
|
||||||
#self.assertEqual('pending_new', IssueThread.objects.all()[0].state)
|
self.assertEqual('pending_new', IssueThread.objects.all()[0].state)
|
||||||
self.assertEqual(None, IssueThread.objects.all()[0].assigned_to)
|
self.assertEqual(None, IssueThread.objects.all()[0].assigned_to)
|
||||||
states = StateChange.objects.filter(issue_thread=IssueThread.objects.all()[0])
|
states = StateChange.objects.filter(issue_thread=IssueThread.objects.all()[0])
|
||||||
self.assertEqual(1, len(states))
|
self.assertEqual(1, len(states))
|
||||||
self.assertEqual('pending_new', states[0].state)
|
self.assertEqual('pending_new', states[0].state)
|
||||||
|
|
||||||
def test_handle_quoted_printable(self):
|
def test_handle_quoted_printable(self):
|
||||||
from aiosmtpd.smtp import Envelope
|
from aiosmtpd.smtp import Envelope
|
||||||
from asgiref.sync import async_to_sync
|
from asgiref.sync import async_to_sync
|
||||||
|
@ -295,8 +296,8 @@ class LMTPHandlerTestCase(TestCase): # TODO replace with less hacky test
|
||||||
self.assertEqual("<1@test>", Email.objects.all()[1].in_reply_to)
|
self.assertEqual("<1@test>", Email.objects.all()[1].in_reply_to)
|
||||||
self.assertEqual('test', IssueThread.objects.all()[0].name)
|
self.assertEqual('test', IssueThread.objects.all()[0].name)
|
||||||
self.assertEqual(None, IssueThread.objects.all()[0].assigned_to)
|
self.assertEqual(None, IssueThread.objects.all()[0].assigned_to)
|
||||||
|
self.assertEqual(1, len(IssueThread.objects.all()))
|
||||||
|
self.assertEqual('pending_new', IssueThread.objects.all()[0].state)
|
||||||
states = StateChange.objects.filter(issue_thread=IssueThread.objects.all()[0])
|
states = StateChange.objects.filter(issue_thread=IssueThread.objects.all()[0])
|
||||||
self.assertEqual(1, len(states))
|
self.assertEqual(1, len(states))
|
||||||
self.assertEqual('pending_new', states[0].state)
|
self.assertEqual('pending_new', states[0].state)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ class IssueSerializer(serializers.ModelSerializer):
|
||||||
if attrs['state'] not in [x[0] for x in STATE_CHOICES]:
|
if attrs['state'] not in [x[0] for x in STATE_CHOICES]:
|
||||||
raise serializers.ValidationError('invalid state')
|
raise serializers.ValidationError('invalid state')
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_timeline(obj):
|
def get_timeline(obj):
|
||||||
timeline = []
|
timeline = []
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 4.2.7 on 2023-12-29 22:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tickets', '0003_alter_issuethread_state'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='issuethread',
|
||||||
|
name='state',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='statechange',
|
||||||
|
name='state',
|
||||||
|
field=models.CharField(choices=[('pending_new', 'New'), ('pending_open', 'Open'), ('pending_shipping', 'Needs to be shipped'), ('pending_physical_confirmation', 'Needs to be confirmed physically'), ('pending_return', 'Needs to be returned'), ('waiting_details', 'Waiting for details'), ('waiting_pre_shipping', 'Waiting for Address/Shipping Info'), ('closed_returned', 'Closed: Returned'), ('closed_shipped', 'Closed: Shipped'), ('closed_not_found', 'Closed: Not found'), ('closed_not_our_problem', 'Closed: Not our problem'), ('closed_duplicate', 'Closed: Duplicate'), ('closed_timeout', 'Closed: Timeout'), ('closed_spam', 'Closed: Spam')], default='pending_new', max_length=255),
|
||||||
|
),
|
||||||
|
]
|
|
@ -74,7 +74,7 @@ export default {
|
||||||
// message: JSON.stringify(e),
|
// message: JSON.stringify(e),
|
||||||
// color: "success"
|
// color: "success"
|
||||||
//});
|
//});
|
||||||
console.log(e);
|
//console.log(e);
|
||||||
};
|
};
|
||||||
this.notify_socket.onclose = (e) => {
|
this.notify_socket.onclose = (e) => {
|
||||||
//if (this.socket_toast) {
|
//if (this.socket_toast) {
|
||||||
|
@ -86,7 +86,7 @@ export default {
|
||||||
// message: JSON.stringify(e),
|
// message: JSON.stringify(e),
|
||||||
// color: "danger"
|
// color: "danger"
|
||||||
//});
|
//});
|
||||||
console.log(e);
|
//console.log(e);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.tryConnect();
|
this.tryConnect();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
@ -101,7 +101,7 @@ export default {
|
||||||
// message: JSON.stringify(e),
|
// message: JSON.stringify(e),
|
||||||
// color: "danger"
|
// color: "danger"
|
||||||
//});
|
//});
|
||||||
console.log(e);
|
//console.log(e);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.tryConnect();
|
this.tryConnect();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {default as BoxesAdmin} from "@/views/admin/Boxes.vue"
|
||||||
Vue.use(VueRouter);
|
Vue.use(VueRouter);
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{path: '/', redirect: '/Camp23/items', meta: {requiresAuth: false}},
|
{path: '/', redirect: '/37C3/items', meta: {requiresAuth: false}},
|
||||||
{path: '/login/', name: 'login', component: Login, meta: {requiresAuth: false}},
|
{path: '/login/', name: 'login', component: Login, meta: {requiresAuth: false}},
|
||||||
{path: '/register/', name: 'register', component: Register, meta: {requiresAuth: false}},
|
{path: '/register/', name: 'register', component: Register, meta: {requiresAuth: false}},
|
||||||
{path: '/howto/', name: 'howto', component: HowTo, meta: {requiresAuth: true}},
|
{path: '/howto/', name: 'howto', component: HowTo, meta: {requiresAuth: true}},
|
||||||
|
|
|
@ -6,6 +6,7 @@ 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";
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
const axios = AxiosBootstrap.create({
|
const axios = AxiosBootstrap.create({
|
||||||
|
@ -69,7 +70,7 @@ const store = new Vuex.Store({
|
||||||
tickets: [],
|
tickets: [],
|
||||||
users: [],
|
users: [],
|
||||||
groups: [],
|
groups: [],
|
||||||
lastEvent: localStorage.getItem('lf_lastEvent') || '36C3',
|
lastEvent: localStorage.getItem('lf_lastEvent') || '37C3',
|
||||||
lastUsed: JSON.parse(localStorage.getItem('lf_lastUsed') || '{}'),
|
lastUsed: JSON.parse(localStorage.getItem('lf_lastUsed') || '{}'),
|
||||||
remember: false,
|
remember: false,
|
||||||
user: null,
|
user: null,
|
||||||
|
@ -88,6 +89,25 @@ const store = new Vuex.Store({
|
||||||
getBoxes: state => state.loadedBoxes,
|
getBoxes: state => state.loadedBoxes,
|
||||||
checkPermission: state => (event, perm) => state.userPermissions.includes(`${event}:${perm}`) || state.userPermissions.includes(`*:${perm}`),
|
checkPermission: state => (event, perm) => state.userPermissions.includes(`${event}:${perm}`) || state.userPermissions.includes(`*:${perm}`),
|
||||||
hasPermissions: state => state.userPermissions.length > 0,
|
hasPermissions: state => state.userPermissions.length > 0,
|
||||||
|
stateInfo: state => (slug) => {
|
||||||
|
const obj = state.state_options.filter((s) => s.value === slug)[0];
|
||||||
|
if (obj) {
|
||||||
|
return {
|
||||||
|
color: ticketStateColorLookup(obj.value),
|
||||||
|
icon: ticketStateIconLookup(obj.value),
|
||||||
|
slug: obj.value,
|
||||||
|
text: obj.text,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
color: 'danger',
|
||||||
|
icon: 'exclamation',
|
||||||
|
slug: slug,
|
||||||
|
text: 'Unknown'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
isLoggedIn(state) {
|
isLoggedIn(state) {
|
||||||
if (!state.local_loaded) {
|
if (!state.local_loaded) {
|
||||||
state.remember = localStorage.getItem('remember') === 'true'
|
state.remember = localStorage.getItem('remember') === 'true'
|
||||||
|
|
27
web/src/utils.js
Normal file
27
web/src/utils.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
function ticketStateColorLookup(ticket) {
|
||||||
|
if (ticket.startsWith('closed_')) {
|
||||||
|
return 'secondary';
|
||||||
|
}
|
||||||
|
if (ticket.startsWith('pending_')) {
|
||||||
|
return 'warning';
|
||||||
|
}
|
||||||
|
if (ticket.startsWith('waiting_')) {
|
||||||
|
return 'primary';
|
||||||
|
}
|
||||||
|
return 'danger';
|
||||||
|
}
|
||||||
|
|
||||||
|
function ticketStateIconLookup(ticket) {
|
||||||
|
if (ticket.startsWith('closed_')) {
|
||||||
|
return 'check';
|
||||||
|
}
|
||||||
|
if (ticket.startsWith('pending_')) {
|
||||||
|
return 'exclamation';
|
||||||
|
}
|
||||||
|
if (ticket.startsWith('waiting_')) {
|
||||||
|
return 'hourglass';
|
||||||
|
}
|
||||||
|
return 'exclamation';
|
||||||
|
}
|
||||||
|
|
||||||
|
export {ticketStateColorLookup, ticketStateIconLookup};
|
Loading…
Reference in a new issue