SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 7b6246a8 authored by Jean-Sébastien Caux's avatar Jean-Sébastien Caux
Browse files

Work on Tickets

parent c0f8a9ea
No related branches found
No related tags found
No related merge requests found
......@@ -16,12 +16,20 @@ TICKET_PRIORITIES = [
TICKET_STATUS_UNASSIGNED = 'unassigned'
TICKET_STATUS_ASSIGNED = 'assigned'
TICKET_STATUS_PASSED_ON = 'passedon'
TICKET_STATUS_PICKEDUP = 'pickedup'
TICKET_STATUS_AWAITING_RESPONSE_ASSIGNEE = 'awaitingassignee'
TICKET_STATUS_AWAITING_RESPONSE_USER = 'awaitinguser'
TICKET_STATUS_RESOLVED = 'resolved'
TICKET_STATUS_CLOSED = 'closed'
TICKET_STATUSES = [
(TICKET_STATUS_UNASSIGNED, 'Unassigned'),
(TICKET_STATUS_ASSIGNED, 'Assigned'),
(TICKET_STATUS_PASSED_ON, 'Passed on'),
(TICKET_STATUS_PICKEDUP, 'Picked up'),
(TICKET_STATUS_AWAITING_RESPONSE_ASSIGNEE, 'Awaiting response from SciPost'),
(TICKET_STATUS_AWAITING_RESPONSE_USER, 'Awaiting response from user'),
(TICKET_STATUS_RESOLVED, 'Resolved'),
(TICKET_STATUS_CLOSED, 'Closed')
]
......@@ -4,7 +4,7 @@ __license__ = "AGPL v3"
from django import forms
from .models import Queue
from .models import Queue, Ticket
class QueueForm(forms.ModelForm):
......@@ -13,3 +13,25 @@ class QueueForm(forms.ModelForm):
fields = ['name', 'slug', 'description',
'managing_group', 'response_groups',
'parent_queue']
class TicketForm(forms.ModelForm):
class Meta:
model = Ticket
fields = ['queue', 'title', 'description', 'publicly_visible',
'defined_on', 'defined_by', 'priority',
'deadline', 'status',
'concerning_object_type', 'concerning_object_id']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['defined_on'].widget = forms.HiddenInput()
self.fields['defined_on'].disabled = True
self.fields['defined_by'].widget = forms.HiddenInput()
self.fields['defined_by'].disabled = True
self.fields['status'].widget = forms.HiddenInput()
self.fields['status'].disabled = True
self.fields['concerning_object_type'].widget = forms.HiddenInput()
self.fields['concerning_object_type'].disabled=True
self.fields['concerning_object_id'].widget = forms.HiddenInput()
self.fields['concerning_object_id'].disabled = True
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2019-03-14 08:55
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('helpdesk', '0003_auto_20190312_1707'),
]
operations = [
migrations.AlterModelOptions(
name='ticket',
options={'ordering': ['queue', 'priority'], 'permissions': [('can_view_ticket', 'Can view Ticket')]},
),
migrations.AddField(
model_name='ticket',
name='title',
field=models.CharField(default='', max_length=64),
),
migrations.AlterField(
model_name='ticket',
name='status',
field=models.CharField(choices=[('unassigned', 'Unassigned'), ('assigned', 'Assigned'), ('passedon', 'Passed on'), ('pickedup', 'Picked up'), ('awaitingassignee', 'Awaiting response from SciPost'), ('awaitinguser', 'Awaiting response from user'), ('resolved', 'Resolved'), ('closed', 'Closed')], max_length=32),
),
]
......@@ -67,6 +67,7 @@ class Ticket(models.Model):
"""
queue = models.ForeignKey('helpdesk.Queue', on_delete=models.CASCADE,
related_name='tickets')
title = models.CharField(max_length=64, default='')
description = models.TextField(
help_text=(
'You can use ReStructuredText, see a '
......@@ -93,6 +94,12 @@ class Ticket(models.Model):
class Meta:
ordering = ['queue', 'priority']
permissions = [
('can_view_ticket', 'Can view Ticket'),
]
def __str__(self):
return '%s - %s' % (self.queue, self.pk)
return '%s-%s %s' % (self.queue, self.pk, self.title)
def get_absolute_url(self):
return reverse('helpdesk:ticket_detail', kwargs={'pk': self.id})
......@@ -18,6 +18,12 @@
<div class="col-12">
<h2 class="highlight">Helpdesk</h2>
<ul>
<li><a href="{% url 'helpdesk:ticket_create' %}">Open a new Ticket</a></li>
</ul>
<h3 class="highlight">Your Tickets</h3>
{% include 'helpdesk/tickets_table.html' with tickets=request.user.ticket_set.all %}
<h3 class="highlight">Queues</h3>
{% if perms.helpdesk.add_queue %}
......
......@@ -48,7 +48,7 @@
{{ queue.description|restructuredtext }}
<h3 class="highlight">Tickets in this Queue</h3>
{% include 'helpdesk/tickets_table.html' with queue=queue %}
{% include 'helpdesk/tickets_table.html' with tickets=queue.tickets.all %}
</div>
</div>
......
{% load bootstrap %}
{% load restructuredtext %}
<div class="card">
<div class="card-header">
<div class="d-flex flex-wrap justify-content-between">
<a href="{{ ticket.get_absolute_url }}">{{ ticket }}</a>
{% if ticket.concerning_object %}
<span>
Re: <a href="{{ ticket.concerning_object.get_absolute_url }}">{{ concerning_object }}</a>
</span>
{% endif %}
</div>
</div>
<div class="card-content">
<table class="table table-bordered">
<tbody>
<tr>
<th colspan="2">Description</th>
</tr>
<tr>
<td colspan="2">{{ ticket.description|restructuredtext }}</td>
</tr>
<tr>
<th>Defined on</th>
<td>{{ ticket.defined_on }}</td>
</tr>
<tr>
<th>Defined by</th>
<td>{{ ticket.defined_by }}</td>
</tr>
<tr>
<th>Priority</th>
<td>{{ ticket.priority }}</td>
</tr>
<tr>
<th>Status</th>
<td>{{ ticket.status }}</td>
</tr>
<tr>
<th>Assigned to</th>
<td>{{ ticket.assigned_to }}</td>
</tr>
</tbody>
</table>
</div>
</div>
{% extends 'helpdesk/base.html' %}
{% load bootstrap %}
{% load guardian_tags %}
{% load restructuredtext %}
{% block breadcrumb_items %}
{{ block.super }}
<span class="breadcrumb-item">Ticket details</span>
{% endblock %}
{% block pagetitle %}: Ticket details{% endblock pagetitle %}
{% get_obj_perms request.user for queue as "user_perms" %}
{% block content %}
<div class="row">
<div class="col-12">
{% include 'helpdesk/ticket_card.html' with ticket=ticket %}
</div>
</div>
{% endblock content %}
{% extends 'helpdesk/base.html' %}
{% load bootstrap %}
{% block breadcrumb_items %}
{{ block.super }}
<span class="breadcrumb-item">{% if form.instance.id %}Update {{ form.instance }}{% else %}Add new Ticket{% endif %}</span>
{% endblock %}
{% block pagetitle %}: Ticket{% endblock pagetitle %}
{% block content %}
<div class="row">
<div class="col-12">
<form action="" method="post">
{% csrf_token %}
{{ form|bootstrap }}
<input type="submit" value="Submit" class="btn btn-primary">
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ field.name }} - {{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
{{ request.user }}
</div>
</div>
{% endblock content %}
......@@ -8,9 +8,9 @@
</tr>
</thead>
<tbody>
{% for ticket in queue.tickets.all %}
{% for ticket in tickets %}
<tr>
<td>{{ ticket }}</td>
<td><a href="{{ ticket.get_absolute_url }}">{{ ticket }}</a></td>
<td>{{ ticket.defined_on|date:"Y-m-d" }}</td>
<td>{{ ticket.get_status_display }}</td>
<td>{% if ticket.assigned_to %}{{ ticket.assigned_to }}{% else %}Nobody{% endif %}</td>
......
......@@ -37,4 +37,19 @@ urlpatterns = [
views.QueueDetailView.as_view(),
name='queue_detail'
),
url(
r'^ticket/add/(?P<concerning_type_id>[0-9]+)/(?P<concerning_object_id>[0-9]+)/$',
views.TicketCreateView.as_view(),
name='ticket_create'
),
url(
r'^ticket/add/$',
views.TicketCreateView.as_view(),
name='ticket_create'
),
url(
r'^ticket/(?P<pk>[0-9]+)/$',
views.TicketDetailView.as_view(),
name='ticket_detail'
),
]
......@@ -2,11 +2,12 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"
import datetime
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse_lazy
from django.utils import timezone
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic.list import ListView
......@@ -15,8 +16,9 @@ from guardian.mixins import PermissionRequiredMixin
from guardian.shortcuts import get_groups_with_perms, get_objects_for_user, remove_perm
from scipost.mixins import PermissionsMixin
from .models import Queue
from .forms import QueueForm
from .constants import TICKET_STATUS_UNASSIGNED
from .models import Queue, Ticket
from .forms import QueueForm, TicketForm
class HelpdeskView(ListView):
......@@ -84,3 +86,36 @@ class QueueDetailView(PermissionRequiredMixin, DetailView):
permission_required = 'helpdesk.can_view_queue'
model = Queue
template_name = 'helpdesk/queue_detail.html'
class TicketCreateView(LoginRequiredMixin, CreateView):
model = Ticket
form_class = TicketForm
template_name = 'helpdesk/ticket_form.html'
def get_initial(self, *args, **kwargs):
initial = super().get_initial(*args, **kwargs)
initial.update({
'defined_on': timezone.now(),
'defined_by': self.request.user,
'status': TICKET_STATUS_UNASSIGNED,
})
try:
concerning_type_id = self.kwargs.get('concerning_type_id')
concerning_object_id = self.kwargs.get('concerning_object_id')
if concerning_type_id and concerning_object_id:
concerning_object_type = ContentType.objects.get_for_id(concerning_type_id)
initial.update({
'concerning_object_type': concerning_object_type,
'concerning_object_id': concerning_object_id,
})
except KeyError:
pass
return initial
class TicketDetailView(PermissionRequiredMixin, DetailView):
permission_required = 'helpdesk.can_view_ticket'
model = Ticket
template_name = 'helpdesk/ticket_detail.html'
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment