mirror of
https://gitea.mueller.network/extern/django-helpdesk.git
synced 2024-11-26 01:43:10 +01:00
Add timeline view for ticket queries
This commit is contained in:
parent
c4a1b9ed66
commit
6eee6d196c
@ -30,58 +30,110 @@
|
|||||||
{% block helpdesk_body %}
|
{% block helpdesk_body %}
|
||||||
{% load in_list %}
|
{% load in_list %}
|
||||||
|
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<i class="fas fa-table"></i>
|
<ul class="nav nav-tabs">
|
||||||
{% trans "Query Results" %}
|
<li class="nav-item" style="width: 200px;">
|
||||||
|
{% trans "Query Results" %}:
|
||||||
|
</li>
|
||||||
|
<li class="nav-item"">
|
||||||
|
<a class="nav-link active" href="#datatabletabcontents" id="datatabletabcontents-tab" data-toggle="tab" role="tab" aria-controls="datatabletabcontents" aria-selected=true>
|
||||||
|
<i class="fas fa-th-list"></i>
|
||||||
|
{% trans "Table" %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#timelinetabcontents" id="timelinetabcontents-tab" data-toggle="tab" role="tab" aria-controls="timelinetabcontents" aria-selected=false>
|
||||||
|
<i class="fas fa-history"></i>
|
||||||
|
{% trans "Timeline" %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{{ search_message|safe }}
|
{{ search_message|safe }}
|
||||||
<form method='post' action='{% url 'helpdesk:mass_update' %}' id="ticket_mass_update">
|
<div class="tab-content" id="myTabContent">
|
||||||
<table width="100%" class="table table-sm table-striped table-bordered table-hover" id="ticketTable" data-page-length='{{ default_tickets_per_page }}'>
|
<div class="tab-pane fade show active" id="datatabletabcontents" role="tabpanel" aria-labelledby="datatabletabcontents-tab">
|
||||||
<thead class="thead-light">
|
<form method='post' action='{% url 'helpdesk:mass_update' %}' id="ticket_mass_update">
|
||||||
<tr>
|
<table width="100%" class="table table-sm table-striped table-bordered table-hover" id="ticketTable" data-page-length='{{ default_tickets_per_page }}'>
|
||||||
<th> </th>
|
<thead class="thead-light">
|
||||||
<th>{% trans "Ticket" %}</th>
|
<tr>
|
||||||
<th>{% trans "Prority" %}</th>
|
<th> </th>
|
||||||
<th>{% trans "Queue" %}</th>
|
<th>{% trans "Ticket" %}</th>
|
||||||
<th>{% trans "Status" %}</th>
|
<th>{% trans "Prority" %}</th>
|
||||||
<th>{% trans "Created" %}</th>
|
<th>{% trans "Queue" %}</th>
|
||||||
<th>{% trans "Due Date" %}</th>
|
<th>{% trans "Status" %}</th>
|
||||||
<th>{% trans "Owner" %}</th>
|
<th>{% trans "Created" %}</th>
|
||||||
<th>{% trans "Time Spent" %}</th>
|
<th>{% trans "Due Date" %}</th>
|
||||||
</tr>
|
<th>{% trans "Owner" %}</th>
|
||||||
</thead>
|
<th>{% trans "Time Spent" %}</th>
|
||||||
</table>
|
</tr>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
|
||||||
<p><label>{% trans "Select:" %} </label>
|
<p><label>{% trans "Select:" %} </label>
|
||||||
|
|
||||||
<button id="select_all_btn" type="button" class="btn btn-primary btn-sm" />
|
<button id="select_all_btn" type="button" class="btn btn-primary btn-sm" />
|
||||||
<i class="fas fa-check-circle"></i> {% trans "All" %}
|
<i class="fas fa-check-circle"></i> {% trans "All" %}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button id='select_none_btn' type="button" class="btn btn-primary btn-sm"><i class="fas fa-times-circle"></i> {% trans "None" %}</button>
|
<button id='select_none_btn' type="button" class="btn btn-primary btn-sm"><i class="fas fa-times-circle"></i> {% trans "None" %}</button>
|
||||||
|
|
||||||
<button id='select_inverse_btn' type="button" class="btn btn-primary btn-sm"><i class="fas fa-expand-arrows-alt"></i> {% trans "Invert" %}</button>
|
<button id='select_inverse_btn' type="button" class="btn btn-primary btn-sm"><i class="fas fa-expand-arrows-alt"></i> {% trans "Invert" %}</button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<label for='id_mass_action'>{% trans "With Selected Tickets:" %}</label>
|
<label for='id_mass_action'>{% trans "With Selected Tickets:" %}</label>
|
||||||
<select name='action' id='id_mass_action'>
|
<select name='action' id='id_mass_action'>
|
||||||
<option value='take'>{% trans "Take (Assign to me)" %}</option>
|
<option value='take'>{% trans "Take (Assign to me)" %}</option>
|
||||||
<option value='delete'>{% trans "Delete" %}</option>
|
<option value='delete'>{% trans "Delete" %}</option>
|
||||||
<optgroup label='{% trans "Close" %}'>
|
<optgroup label='{% trans "Close" %}'>
|
||||||
<option value='close'>{% trans "Close (Don't Send E-Mail)" %}</option>
|
<option value='close'>{% trans "Close (Don't Send E-Mail)" %}</option>
|
||||||
<option value='close_public'>{% trans "Close (Send E-Mail)" %}</option>
|
<option value='close_public'>{% trans "Close (Send E-Mail)" %}</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label='{% trans "Assign To" %}'>
|
<optgroup label='{% trans "Assign To" %}'>
|
||||||
<option value='unassign'>{% trans "Nobody (Unassign)" %}</option>
|
<option value='unassign'>{% trans "Nobody (Unassign)" %}</option>
|
||||||
{% for u in user_choices %}<option value='assign_{{ u.id }}'>{{ u.get_username }}</option>{% endfor %}
|
{% for u in user_choices %}<option value='assign_{{ u.id }}'>{{ u.get_username }}</option>{% endfor %}
|
||||||
</optgroup>
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-arrow-circle-right"></i> {% trans "Go" %}</button>
|
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-arrow-circle-right"></i> {% trans "Go" %}</button>
|
||||||
</p>
|
</p>
|
||||||
{% csrf_token %}</form>
|
{% csrf_token %}</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="timelinetabcontents" role="tabpanel" aria-labelledby="timelinetabcontents-tab">
|
||||||
|
<div id='timeline-embed' style="width: 100%; height: 80vh"></div>
|
||||||
|
<!-- 1 -->
|
||||||
|
<link title="timeline-styles" rel="stylesheet" href="https://cdn.knightlab.com/libs/timeline3/latest/css/timeline.css">
|
||||||
|
|
||||||
|
<!-- 2 -->
|
||||||
|
<script src="https://cdn.knightlab.com/libs/timeline3/latest/js/timeline.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 3 -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
// The TL.Timeline constructor takes at least two arguments:
|
||||||
|
// the id of the Timeline container (no '#'), and
|
||||||
|
// the URL to your JSON data file or Google spreadsheet.
|
||||||
|
// the id must refer to an element "above" this code,
|
||||||
|
// and the element must have CSS styling to give it width and height
|
||||||
|
// optionally, a third argument with configuration options can be passed.
|
||||||
|
// See below for more about options.
|
||||||
|
var timeline_loaded = false;
|
||||||
|
$(function () {
|
||||||
|
$('#timelinetabcontents-tab').on('shown.bs.tab', function (e) {
|
||||||
|
if(!timeline_loaded){
|
||||||
|
timeline = new TL.Timeline(
|
||||||
|
'timeline-embed',
|
||||||
|
'{% url 'helpdesk:timeline_ticket_list' urlsafe_query %}',
|
||||||
|
)
|
||||||
|
timeline_loaded = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.panel-body -->
|
<!-- /.panel-body -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -151,6 +151,11 @@ urlpatterns = [
|
|||||||
url(r'^datatables_ticket_list/(?P<query>{})$'.format(base64_pattern),
|
url(r'^datatables_ticket_list/(?P<query>{})$'.format(base64_pattern),
|
||||||
staff.datatables_ticket_list,
|
staff.datatables_ticket_list,
|
||||||
name="datatables_ticket_list"),
|
name="datatables_ticket_list"),
|
||||||
|
|
||||||
|
url(r'^timeline_ticket_list/(?P<query>{})$'.format(base64_pattern),
|
||||||
|
staff.timeline_ticket_list,
|
||||||
|
name="timeline_ticket_list"),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
urlpatterns += [
|
urlpatterns += [
|
||||||
|
@ -975,6 +975,46 @@ def datatables_ticket_list(request, query):
|
|||||||
return (JsonResponse(result, status=status.HTTP_200_OK))
|
return (JsonResponse(result, status=status.HTTP_200_OK))
|
||||||
|
|
||||||
|
|
||||||
|
@helpdesk_staff_member_required
|
||||||
|
@api_view(['GET'])
|
||||||
|
def timeline_ticket_list(request, query):
|
||||||
|
"""
|
||||||
|
Datatable on ticket_list.html uses this view from to get objects to display
|
||||||
|
on the table. query_tickets_by_args is at lib.py, DatatablesTicketSerializer is in
|
||||||
|
serializers.py. The serializers and this view use django-rest_framework methods
|
||||||
|
"""
|
||||||
|
tickets = get_query(query, HelpdeskUser(request.user))
|
||||||
|
events = []
|
||||||
|
|
||||||
|
def mk_timeline_date(date):
|
||||||
|
return {
|
||||||
|
'year': date.year,
|
||||||
|
'month': date.month,
|
||||||
|
'day': date.day,
|
||||||
|
'hour': date.hour,
|
||||||
|
'minute': date.minute,
|
||||||
|
'second': date.second,
|
||||||
|
'second': date.second,
|
||||||
|
}
|
||||||
|
for ticket in tickets:
|
||||||
|
for followup in ticket.followup_set.all():
|
||||||
|
event = {
|
||||||
|
'start_date': mk_timeline_date(followup.date),
|
||||||
|
'text': {
|
||||||
|
'headline': ticket.title + '<br/>' + followup.title,
|
||||||
|
'text': (followup.comment if followup.comment else _('No text')) + '<br/> <a href="%s" class="btn" role="button">%s</a>' %
|
||||||
|
(reverse('helpdesk:view', kwargs={'ticket_id': ticket.pk}), _("View ticket")),
|
||||||
|
},
|
||||||
|
'group': _('Messages'),
|
||||||
|
}
|
||||||
|
events.append(event)
|
||||||
|
|
||||||
|
result = {
|
||||||
|
'events': events,
|
||||||
|
}
|
||||||
|
return (JsonResponse(result, status=status.HTTP_200_OK))
|
||||||
|
|
||||||
|
|
||||||
@helpdesk_staff_member_required
|
@helpdesk_staff_member_required
|
||||||
def edit_ticket(request, ticket_id):
|
def edit_ticket(request, ticket_id):
|
||||||
ticket = get_object_or_404(Ticket, id=ticket_id)
|
ticket = get_object_or_404(Ticket, id=ticket_id)
|
||||||
|
Loading…
Reference in New Issue
Block a user