mirror of
https://gitea.mueller.network/extern/django-helpdesk.git
synced 2024-11-24 00:43:21 +01:00
Merge pull request #1185 from jorge-leon/reverse-dependencies
Add list of 'parent' tickets to ticket description table, solves #1184
This commit is contained in:
commit
437287edbc
@ -589,7 +589,26 @@ class TicketDependencyForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = TicketDependency
|
||||
exclude = ('ticket',)
|
||||
fields = ('depends_on',)
|
||||
|
||||
def __init__(self, ticket, *args, **kwargs):
|
||||
super(TicketDependencyForm,self).__init__(*args, **kwargs)
|
||||
|
||||
# Only open tickets except myself, existing dependencies and parents
|
||||
self.fields['depends_on'].queryset = Ticket.objects.filter(status__in=Ticket.OPEN_STATUSES).exclude(id=ticket.id).exclude(depends_on__ticket=ticket).exclude(ticketdependency__depends_on=ticket)
|
||||
|
||||
class TicketResolvesForm(forms.ModelForm):
|
||||
''' Adds this ticket as a dependency for a different ticket '''
|
||||
|
||||
class Meta:
|
||||
model = TicketDependency
|
||||
fields = ('ticket',)
|
||||
|
||||
def __init__(self, ticket, *args, **kwargs):
|
||||
super(TicketResolvesForm,self).__init__(*args, **kwargs)
|
||||
|
||||
# Only open tickets except myself, existing dependencies and parents
|
||||
self.fields['ticket'].queryset = Ticket.objects.exclude(status__in=Ticket.OPEN_STATUSES).exclude(id=ticket.id).exclude(depends_on__ticket=ticket).exclude(ticketdependency__depends_on=ticket)
|
||||
|
||||
|
||||
class MultipleTicketSelectForm(forms.Form):
|
||||
|
@ -12,7 +12,7 @@
|
||||
<thead class="thead-light">
|
||||
<tr class=''>
|
||||
<th colspan='4'>
|
||||
<h3>{{ ticket.queue.slug }}-{{ ticket.id }}. {{ ticket.title }} [{{ ticket.get_status }}]</h3>
|
||||
<h3>{{ ticket.queue.slug }}-{{ ticket.id }}. {{ ticket.title }}</h3>
|
||||
{% blocktrans with ticket.queue as queue %}Queue: {{ queue }}{% endblocktrans %}
|
||||
<span class='ticket_toolbar float-right'>
|
||||
<a href="{% url 'helpdesk:edit' ticket.id %}" class="btn btn-warning btn-sm ticket-edit">
|
||||
@ -117,24 +117,9 @@
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if helpdesk_settings.HELPDESK_ENABLE_DEPENDENCIES_ON_TICKET != False and helpdesk_settings.HELPDESK_ENABLE_TIME_SPENT_ON_TICKET != False %}
|
||||
<tr>
|
||||
{% if helpdesk_settings.HELPDESK_ENABLE_DEPENDENCIES_ON_TICKET %}
|
||||
<th class="table-active">{% trans "Dependencies" %}</th>
|
||||
<td>
|
||||
<a data-toggle='tooltip' href='{% url 'helpdesk:ticket_dependency_add' ticket.id %}' title="{% trans "Click on 'Add Dependency', if you want to make this ticket dependent on another ticket. A ticket may not be closed until all tickets it depends on are closed." %}"><button type="button" class="btn btn-primary btn-sm float-right"><i class="fas fa-link"></i></button></a>
|
||||
{% for dep in ticket.ticketdependency.all %}
|
||||
{% if forloop.first %}<p>{% trans "This ticket cannot be resolved until the following ticket(s) are resolved" %}</p><ul>{% endif %}
|
||||
<li><a href='{{ dep.depends_on.get_absolute_url }}'>{{ dep.depends_on.ticket }} {{ dep.depends_on.title }}</a> ({{ dep.depends_on.get_status_display }}) <a href='{% url 'helpdesk:ticket_dependency_del' ticket.id dep.id %}'><button type="button" class="btn btn-warning btn-sm"><i class="fas fa-trash"></i></button></a></li>
|
||||
{% if forloop.last %}</ul>{% endif %}
|
||||
{% empty %}
|
||||
{% trans "This ticket has no dependencies." %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
{% else %}
|
||||
<th class="table-active"></th>
|
||||
<td></td>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th class="table-active">{% trans "Status" %}</th>
|
||||
<td>{{ ticket.get_status }}</td>
|
||||
{% if helpdesk_settings.HELPDESK_ENABLE_TIME_SPENT_ON_TICKET %}
|
||||
<th class="table-active">{% trans "Total time spent" %}</th>
|
||||
<td>{{ ticket.time_spent_formated }}</td>
|
||||
@ -142,8 +127,64 @@
|
||||
<th class="table-active"></th>
|
||||
<td></td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% if helpdesk_settings.HELPDESK_ENABLE_DEPENDENCIES_ON_TICKET != False %}
|
||||
<tr>
|
||||
<th class="table-active">
|
||||
{% trans "Resolves" %}
|
||||
<a data-toggle='tooltip' href='{% url 'helpdesk:ticket_resolves_add' ticket.id %}'
|
||||
title='{% trans "Make this ticket resolve another ticket." %}'>
|
||||
<button type="button" class="btn btn-primary btn-sm float-right"><i class="fas fa-link"></i></button></a>
|
||||
</th>
|
||||
<td colspan="3" class="p-0">
|
||||
{% for resolves in ticket.depends_on.all %}
|
||||
{% if forloop.first %}<table class="table table-borderless table-responsive m-0">{% endif %}
|
||||
<tr>
|
||||
<td>
|
||||
<a data-toggle='tooltip' href='{% url 'helpdesk:ticket_resolves_del' resolves.ticket.id resolves.id %}'
|
||||
title='{% trans "Drop the dependency on this ticket. A ticket may not be closed until all tickets it depends on are closed or removed." %}'>
|
||||
<button type="button" class="btn btn-warning btn-sm"><i class="fas fa-trash"></i></button></a>
|
||||
</td>
|
||||
<td>{{ resolves.ticket.get_status_display }}</td>
|
||||
<td>
|
||||
<a href='{{ resolves.ticket.get_absolute_url }}'>{{ resolves.ticket.ticket }} {{ resolves.ticket.title }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% if forloop.last %}</table>{% endif %}
|
||||
{% empty %}
|
||||
<small class="p-2">{% trans "This ticket does not resolve any other" %}</small>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="table-active">
|
||||
{% trans "Depends" %}
|
||||
<a data-toggle='tooltip' href='{% url 'helpdesk:ticket_dependency_add' ticket.id %}'
|
||||
title='{% trans "Make this ticket dependent on another ticket. A ticket may not be closed until all tickets it depends on are closed or removed." %}'>
|
||||
<button type="button" class="btn btn-primary btn-sm float-right"><i class="fas fa-link"></i></button></a>
|
||||
|
||||
</th>
|
||||
<td colspan="3" class="p-0">
|
||||
{% for dep in dependencies %}
|
||||
{% if forloop.first %}<table class="table table-borderless table-hover table-responsive m-0">{% endif %}
|
||||
<tr>
|
||||
<td>
|
||||
<a data-toggle='tooltip' href='{% url 'helpdesk:ticket_dependency_del' ticket.id dep.id %}'
|
||||
title='{% trans "Drop the dependency on this ticket. A ticket may not be closed until all tickets it depends on are closed or removed." %}'>
|
||||
<button type="button" class="btn btn-warning btn-sm"><i class="fas fa-trash"></i></button></a>
|
||||
</td>
|
||||
<td>{{ dep.depends_on.get_status_display }}</td>
|
||||
<td>
|
||||
<a href='{{ dep.depends_on.get_absolute_url }}'>{{ dep.depends_on.ticket }} {{ dep.depends_on.title }}</a>
|
||||
|
||||
</td>
|
||||
{% if forloop.last %}</table>{% endif %}
|
||||
{% empty %}
|
||||
<small class="p-2">{% trans "This ticket has no dependencies." %}</small>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if ticket.kbitem %}
|
||||
<tr>
|
||||
<th class="table-active">{% trans "Knowlegebase item" %}</th>
|
||||
|
37
helpdesk/templates/helpdesk/ticket_resolves_add.html
Normal file
37
helpdesk/templates/helpdesk/ticket_resolves_add.html
Normal file
@ -0,0 +1,37 @@
|
||||
{% extends "helpdesk/base.html" %}{% load i18n %}
|
||||
|
||||
{% block helpdesk_title %}{% trans "Add Ticket as Dependency" %}{% endblock %}
|
||||
|
||||
{% block helpdesk_breadcrumb %}
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{% url 'helpdesk:list' %}">{% trans "Tickets" %}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{% url 'helpdesk:list' %}{{ depends_on.id }}/">{{ depends_on.queue.slug }}-{{ depends_on.id }}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">{% trans "Add Ticket as Dependency" %}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block helpdesk_body %}{% blocktrans %}
|
||||
<h2>Add Ticket as Dependency</h2>
|
||||
|
||||
<p>Ticket: {{ depends_on }} </p>
|
||||
|
||||
<p>Adding this ticket as dependency will stop you resolving the selected ticket until this ticket has been resolved or closed.</p>{% endblocktrans %}
|
||||
|
||||
<form method='post' action='./'>
|
||||
|
||||
<fieldset>
|
||||
<dl>{% for field in form %}
|
||||
<dt><label for='id_{{ field.name }}'>{{ field.label }}</label></dt>
|
||||
<dd>{{ field }}</dd>
|
||||
{% if field.errors %}<dd class='error'>{{ field.errors }}</dd>{% endif %}
|
||||
{% if field.help_text %}<dd class='form_help_text'>{{ field.help_text }}</dd>{% endif %}
|
||||
{% endfor %}</dl>
|
||||
</fieldset>
|
||||
|
||||
<input class="btn btn-primary" type='submit' value='{% trans "Save Ticket Dependency" %}' />
|
||||
|
||||
{% csrf_token %}</form>
|
||||
|
||||
{% endblock %}
|
@ -88,6 +88,16 @@ urlpatterns = [
|
||||
staff.ticket_dependency_del,
|
||||
name="ticket_dependency_del",
|
||||
),
|
||||
path(
|
||||
"tickets/<int:ticket_id>/resolves/add/",
|
||||
staff.ticket_resolves_add,
|
||||
name="ticket_resolves_add",
|
||||
),
|
||||
path(
|
||||
"tickets/<int:ticket_id>/resolves/delete/<int:dependency_id>/",
|
||||
staff.ticket_resolves_del,
|
||||
name="ticket_resolves_del",
|
||||
),
|
||||
path(
|
||||
"tickets/<int:ticket_id>/attachment_delete/<int:attachment_id>/",
|
||||
staff.attachment_del,
|
||||
|
@ -20,7 +20,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
|
||||
from django.db.models import Q
|
||||
from django.db.models import Q, Case, When
|
||||
from django.forms import HiddenInput, inlineformset_factory, TextInput
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
@ -54,6 +54,7 @@ from helpdesk.forms import (
|
||||
TicketCCUserForm,
|
||||
TicketDependencyForm,
|
||||
TicketForm,
|
||||
TicketResolvesForm,
|
||||
UserSettingsForm
|
||||
)
|
||||
from helpdesk.lib import queue_template_context, safe_template_context
|
||||
@ -422,8 +423,16 @@ def view_ticket(request, ticket_id):
|
||||
|
||||
return redirect('helpdesk:edit_ticket_checklist', ticket.id, checklist.id)
|
||||
|
||||
# List open tickets on top
|
||||
dependencies = ticket.ticketdependency.annotate(
|
||||
rank=Case(
|
||||
When(depends_on__status__in=Ticket.OPEN_STATUSES, then=1),
|
||||
default=2
|
||||
)).order_by('rank')
|
||||
|
||||
return render(request, 'helpdesk/ticket.html', {
|
||||
'ticket': ticket,
|
||||
'dependencies': dependencies,
|
||||
'submitter_userprofile_url': submitter_userprofile_url,
|
||||
'form': form,
|
||||
'active_users': users,
|
||||
@ -1664,15 +1673,15 @@ def ticket_dependency_add(request, ticket_id):
|
||||
ticket = get_object_or_404(Ticket, id=ticket_id)
|
||||
ticket_perm_check(request, ticket)
|
||||
if request.method == 'POST':
|
||||
form = TicketDependencyForm(request.POST)
|
||||
form = TicketDependencyForm(ticket, request.POST)
|
||||
if form.is_valid():
|
||||
ticketdependency = form.save(commit=False)
|
||||
ticketdependency.ticket = ticket
|
||||
if ticketdependency.ticket != ticketdependency.depends_on:
|
||||
ticketdependency.save()
|
||||
return HttpResponseRedirect(reverse('helpdesk:view', args=[ticket.id]))
|
||||
return redirect(ticket.get_absolute_url())
|
||||
else:
|
||||
form = TicketDependencyForm()
|
||||
form = TicketDependencyForm(ticket)
|
||||
return render(request, 'helpdesk/ticket_dependency_add.html', {
|
||||
'ticket': ticket,
|
||||
'form': form,
|
||||
@ -1695,6 +1704,42 @@ def ticket_dependency_del(request, ticket_id, dependency_id):
|
||||
ticket_dependency_del = staff_member_required(ticket_dependency_del)
|
||||
|
||||
|
||||
@helpdesk_staff_member_required
|
||||
def ticket_resolves_add(request, ticket_id):
|
||||
depends_on = get_object_or_404(Ticket, id=ticket_id)
|
||||
ticket_perm_check(request, depends_on)
|
||||
if request.method == 'POST':
|
||||
form = TicketResolvesForm(depends_on, request.POST)
|
||||
if form.is_valid():
|
||||
ticketdependency = form.save(commit=False)
|
||||
ticketdependency.depends_on = depends_on
|
||||
if ticketdependency.ticket != ticketdependency.depends_on:
|
||||
ticketdependency.save()
|
||||
return redirect(depends_on.get_absolute_url())
|
||||
else:
|
||||
form = TicketResolvesForm(depends_on)
|
||||
return render(request, 'helpdesk/ticket_resolves_add.html', {
|
||||
'depends_on': depends_on,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
|
||||
ticket_resolves_add = staff_member_required(ticket_resolves_add)
|
||||
|
||||
|
||||
@helpdesk_staff_member_required
|
||||
def ticket_resolves_del(request, ticket_id, dependency_id):
|
||||
dependency = get_object_or_404(
|
||||
TicketDependency, ticket__id=ticket_id, id=dependency_id)
|
||||
depends_on_id = dependency.depends_on.id
|
||||
if request.method == 'POST':
|
||||
dependency.delete()
|
||||
return HttpResponseRedirect(reverse('helpdesk:view', args=[depends_on_id]))
|
||||
return render(request, 'helpdesk/ticket_dependency_del.html', {'dependency': dependency})
|
||||
|
||||
ticket_resolves_del = staff_member_required(ticket_resolves_del)
|
||||
|
||||
|
||||
@helpdesk_staff_member_required
|
||||
def attachment_del(request, ticket_id, attachment_id):
|
||||
ticket = get_object_or_404(Ticket, id=ticket_id)
|
||||
|
Loading…
Reference in New Issue
Block a user