forked from extern/django-helpdesk
Add timeline view for ticket queries
This commit is contained in:
parent
c4a1b9ed66
commit
6eee6d196c
@ -30,58 +30,110 @@
|
||||
{% block helpdesk_body %}
|
||||
{% load in_list %}
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-table"></i>
|
||||
{% trans "Query Results" %}
|
||||
<ul class="nav nav-tabs">
|
||||
<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 class="card-body">
|
||||
{{ search_message|safe }}
|
||||
<form method='post' action='{% url 'helpdesk:mass_update' %}' id="ticket_mass_update">
|
||||
<table width="100%" class="table table-sm table-striped table-bordered table-hover" id="ticketTable" data-page-length='{{ default_tickets_per_page }}'>
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>{% trans "Ticket" %}</th>
|
||||
<th>{% trans "Prority" %}</th>
|
||||
<th>{% trans "Queue" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "Created" %}</th>
|
||||
<th>{% trans "Due Date" %}</th>
|
||||
<th>{% trans "Owner" %}</th>
|
||||
<th>{% trans "Time Spent" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="datatabletabcontents" role="tabpanel" aria-labelledby="datatabletabcontents-tab">
|
||||
<form method='post' action='{% url 'helpdesk:mass_update' %}' id="ticket_mass_update">
|
||||
<table width="100%" class="table table-sm table-striped table-bordered table-hover" id="ticketTable" data-page-length='{{ default_tickets_per_page }}'>
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>{% trans "Ticket" %}</th>
|
||||
<th>{% trans "Prority" %}</th>
|
||||
<th>{% trans "Queue" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "Created" %}</th>
|
||||
<th>{% trans "Due Date" %}</th>
|
||||
<th>{% trans "Owner" %}</th>
|
||||
<th>{% trans "Time Spent" %}</th>
|
||||
</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" />
|
||||
<i class="fas fa-check-circle"></i> {% trans "All" %}
|
||||
<button id="select_all_btn" type="button" class="btn btn-primary btn-sm" />
|
||||
<i class="fas fa-check-circle"></i> {% trans "All" %}
|
||||
</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>
|
||||
</p>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for='id_mass_action'>{% trans "With Selected Tickets:" %}</label>
|
||||
<select name='action' id='id_mass_action'>
|
||||
<option value='take'>{% trans "Take (Assign to me)" %}</option>
|
||||
<option value='delete'>{% trans "Delete" %}</option>
|
||||
<optgroup label='{% trans "Close" %}'>
|
||||
<option value='close'>{% trans "Close (Don't Send E-Mail)" %}</option>
|
||||
<option value='close_public'>{% trans "Close (Send E-Mail)" %}</option>
|
||||
</optgroup>
|
||||
<optgroup label='{% trans "Assign To" %}'>
|
||||
<option value='unassign'>{% trans "Nobody (Unassign)" %}</option>
|
||||
{% for u in user_choices %}<option value='assign_{{ u.id }}'>{{ u.get_username }}</option>{% endfor %}
|
||||
</optgroup>
|
||||
</select>
|
||||
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-arrow-circle-right"></i> {% trans "Go" %}</button>
|
||||
</p>
|
||||
{% csrf_token %}</form>
|
||||
<p>
|
||||
<label for='id_mass_action'>{% trans "With Selected Tickets:" %}</label>
|
||||
<select name='action' id='id_mass_action'>
|
||||
<option value='take'>{% trans "Take (Assign to me)" %}</option>
|
||||
<option value='delete'>{% trans "Delete" %}</option>
|
||||
<optgroup label='{% trans "Close" %}'>
|
||||
<option value='close'>{% trans "Close (Don't Send E-Mail)" %}</option>
|
||||
<option value='close_public'>{% trans "Close (Send E-Mail)" %}</option>
|
||||
</optgroup>
|
||||
<optgroup label='{% trans "Assign To" %}'>
|
||||
<option value='unassign'>{% trans "Nobody (Unassign)" %}</option>
|
||||
{% for u in user_choices %}<option value='assign_{{ u.id }}'>{{ u.get_username }}</option>{% endfor %}
|
||||
</optgroup>
|
||||
</select>
|
||||
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-arrow-circle-right"></i> {% trans "Go" %}</button>
|
||||
</p>
|
||||
{% 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>
|
||||
<!-- /.panel-body -->
|
||||
</div>
|
||||
|
@ -151,6 +151,11 @@ urlpatterns = [
|
||||
url(r'^datatables_ticket_list/(?P<query>{})$'.format(base64_pattern),
|
||||
staff.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 += [
|
||||
|
@ -975,6 +975,46 @@ def datatables_ticket_list(request, query):
|
||||
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
|
||||
def edit_ticket(request, ticket_id):
|
||||
ticket = get_object_or_404(Ticket, id=ticket_id)
|
||||
|
Loading…
Reference in New Issue
Block a user