mirror of
https://gitea.mueller.network/extern/django-helpdesk.git
synced 2024-11-22 07:53:19 +01:00
* Create new help page for comment template context variables
( see /help/context/; also linked from comment form) * Refactor API help page to share template with context help * Allow a limited number of Ticket & Queue model fields to be accessible in comments, as per 'Help' page. * New function in lib.py to build a dict of 'safe' fields from ticket & queue, to prevent the power of the Django model API from exposing things like passwords (imagine if a user typed a comment containing {{ ticket.queue.email_box_password }} !!!! * When accessing the ticket list with no filter params (eg by clicking on the "Tickets" button in the menu), the default search is for tickets that aren't closed, rather than showing all tickets. * Updated English locale with changed message strings.
This commit is contained in:
parent
0068eccbf4
commit
a162d77d70
46
lib.py
46
lib.py
@ -279,3 +279,49 @@ def apply_query(queryset, params):
|
||||
queryset = queryset.order_by(params['sorting'])
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
def safe_template_context(ticket):
|
||||
"""
|
||||
Return a dictionary that can be used as a template context to render
|
||||
comments and other details with ticket or queue paramaters. Note that
|
||||
we don't just provide the Ticket & Queue objects to the template as
|
||||
they could reveal confidential information. Just imagine these two options:
|
||||
* {{ ticket.queue.email_box_password }}
|
||||
* {{ ticket.assigned_to.password }}
|
||||
|
||||
Ouch!
|
||||
|
||||
The downside to this is that if we make changes to the model, we will also
|
||||
have to update this code. Perhaps we can find a better way in the future.
|
||||
"""
|
||||
|
||||
context = {
|
||||
'queue': {},
|
||||
'ticket': {},
|
||||
}
|
||||
queue = ticket.queue
|
||||
|
||||
for field in ( 'title', 'slug', 'email_address', 'from_address'):
|
||||
attr = getattr(queue, field, None)
|
||||
if callable(attr):
|
||||
context['queue'][field] = attr()
|
||||
else:
|
||||
context['queue'][field] = attr
|
||||
|
||||
for field in ( 'title', 'created', 'modified', 'submitter_email',
|
||||
'status', 'get_status_display', 'on_hold', 'description',
|
||||
'resolution', 'priority', 'get_priority_display',
|
||||
'last_escalation', 'ticket', 'ticket_for_url',
|
||||
'get_status', 'ticket_url', 'staff_url', '_get_assigned_to'
|
||||
):
|
||||
attr = getattr(ticket, field, None)
|
||||
if callable(attr):
|
||||
context['ticket'][field] = '%s' % attr()
|
||||
else:
|
||||
context['ticket'][field] = attr
|
||||
|
||||
context['ticket']['queue'] = context['queue']
|
||||
context['ticket']['assigned_to'] = context['ticket']['_get_assigned_to']
|
||||
|
||||
return context
|
||||
|
Binary file not shown.
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2008-08-28 02:50+0000\n"
|
||||
"POT-Creation-Date: 2008-08-29 05:10+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -54,7 +54,7 @@ msgstr ""
|
||||
#: forms.py:58 models.py:301 management/commands/escalate_tickets.py:152
|
||||
#: templates/helpdesk/public_view_ticket.html:29
|
||||
#: templates/helpdesk/ticket.html:67 templates/helpdesk/ticket.html.py:159
|
||||
#: templates/helpdesk/ticket_list.html:43 views/staff.py:186
|
||||
#: templates/helpdesk/ticket_list.html:43 views/staff.py:192
|
||||
msgid "Priority"
|
||||
msgstr ""
|
||||
|
||||
@ -108,7 +108,7 @@ msgstr ""
|
||||
#: models.py:29 models.py:239 models.py:446 models.py:740 models.py:771
|
||||
#: templates/helpdesk/dashboard.html:26 templates/helpdesk/dashboard.html:41
|
||||
#: templates/helpdesk/ticket.html:153 templates/helpdesk/ticket_list.html:40
|
||||
#: templates/helpdesk/ticket_list.html:115 views/staff.py:176
|
||||
#: templates/helpdesk/ticket_list.html:115 views/staff.py:182
|
||||
msgid "Title"
|
||||
msgstr ""
|
||||
|
||||
@ -378,7 +378,7 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: models.py:321 templates/helpdesk/ticket.html:58 views/feeds.py:91
|
||||
#: views/feeds.py:117 views/feeds.py:171 views/staff.py:153
|
||||
#: views/feeds.py:117 views/feeds.py:171 views/staff.py:159
|
||||
msgid "Unassigned"
|
||||
msgstr ""
|
||||
|
||||
@ -390,7 +390,7 @@ msgstr ""
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:453 views/staff.py:167
|
||||
#: models.py:453 views/staff.py:173
|
||||
msgid "Comment"
|
||||
msgstr ""
|
||||
|
||||
@ -1079,8 +1079,8 @@ msgstr ""
|
||||
|
||||
#: templates/helpdesk/ticket.html:119
|
||||
msgid ""
|
||||
"You can use the {{ ticket }} and {{ queue }} template variables in your "
|
||||
"message."
|
||||
"You can insert ticket and queue details in your message. For more "
|
||||
"information, see the <a href='../../help/context/'>context help page</a>."
|
||||
msgstr ""
|
||||
|
||||
#: templates/helpdesk/ticket.html:142
|
||||
@ -1289,19 +1289,19 @@ msgstr ""
|
||||
msgid "Accepted resolution and closed ticket"
|
||||
msgstr ""
|
||||
|
||||
#: views/staff.py:147
|
||||
#: views/staff.py:153
|
||||
#, python-format
|
||||
msgid "Assigned to %(username)s"
|
||||
msgstr ""
|
||||
|
||||
#: views/staff.py:169
|
||||
#: views/staff.py:175
|
||||
msgid "Updated"
|
||||
msgstr ""
|
||||
|
||||
#: views/staff.py:401
|
||||
#: views/staff.py:422
|
||||
msgid "Ticket taken off hold"
|
||||
msgstr ""
|
||||
|
||||
#: views/staff.py:404
|
||||
#: views/staff.py:425
|
||||
msgid "Ticket placed on hold"
|
||||
msgstr ""
|
||||
|
@ -1,46 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<style type='text/css'>
|
||||
body {
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
font: 10pt "Trebuchet MS", Arial, sans-serif;
|
||||
}
|
||||
{% extends "helpdesk/help_base.html" %}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-family: Garamond, Times, serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #00c;
|
||||
font-size: 18pt;
|
||||
border-bottom: solid 1px #00c;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #c00;
|
||||
font-size: 17pt;
|
||||
border-bottom: solid 1px #c00;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14pt;
|
||||
border-bottom: solid 1px #ccc;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 13pt;
|
||||
}
|
||||
|
||||
dl {
|
||||
padding-left: 2em;
|
||||
}
|
||||
</style>
|
||||
<title>Jutda Helpdesk API Documentation</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Jutda Helpdesk API Documentation</h1>
|
||||
{% block title %}Jutda Helpdesk API Documentation{% endblock %}
|
||||
{% block heading %}Jutda Helpdesk API Documentation{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
@ -305,5 +268,4 @@ echo $result;
|
||||
<p>This method responds with <strong>plain-text</strong>.</p>
|
||||
|
||||
<p>If you receive a 200 OK <a href='#response'>response</a>, then the content of the response will be the users ID.</p>
|
||||
</body>
|
||||
</html>
|
||||
{% endblock %}
|
46
templates/helpdesk/help_base.html
Normal file
46
templates/helpdesk/help_base.html
Normal file
@ -0,0 +1,46 @@
|
||||
<html>
|
||||
<head>
|
||||
<style type='text/css'>
|
||||
body {
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
font: 10pt "Trebuchet MS", Arial, sans-serif;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-family: Garamond, Times, serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #00c;
|
||||
font-size: 18pt;
|
||||
border-bottom: solid 1px #00c;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #c00;
|
||||
font-size: 17pt;
|
||||
border-bottom: solid 1px #c00;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14pt;
|
||||
border-bottom: solid 1px #ccc;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 13pt;
|
||||
}
|
||||
|
||||
dl {
|
||||
padding-left: 2em;
|
||||
}
|
||||
</style>
|
||||
<title>{% block title %}Jutda Helpdesk Help{% endblock %}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{% block heading %}Jutda Helpdesk Help{% endblock %}</h1>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
139
templates/helpdesk/help_context.html
Normal file
139
templates/helpdesk/help_context.html
Normal file
@ -0,0 +1,139 @@
|
||||
{% extends "helpdesk/help_base.html" %}
|
||||
|
||||
{% block title %}Jutda Helpdesk Context Listing{% endblock %}
|
||||
{% block heading %}Jutda Helpdesk Context Listing{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href='#introduction'>Introduction</a></li>
|
||||
<li><a href='#usage'>Inserting Fields</a></li>
|
||||
<li><a href='#queue'>Queue Fields</a>
|
||||
<ul>
|
||||
<li><a href='#queue_title'>queue.title</a></li>
|
||||
<li><a href='#queue_slug'>queue.slug</a></li>
|
||||
<li><a href='#queue_email_address'>queue.email_address</a></li>
|
||||
<li><a href='#queue_from_address'>queue.from_address</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href='#ticket'>Ticket Fields</a>
|
||||
<ul>
|
||||
<li><a href='#ticket_title'>ticket.title</a></li>
|
||||
<li><a href='#ticket_created'>ticket.created</a></li>
|
||||
<li><a href='#ticket_modified'>ticket.modified</a></li>
|
||||
<li><a href='#ticket_submitter_email'>ticket.submitter_email</a></li>
|
||||
<li><a href='#ticket_status'>ticket.status</a></li>
|
||||
<li><a href='#ticket_get_status_display'>ticket.get_status_display</a></li>
|
||||
<li><a href='#ticket_on_hold'>ticket.on_hold</a></li>
|
||||
<li><a href='#ticket_description'>ticket.description</a></li>
|
||||
<li><a href='#ticket_resolution'>ticket.resolution</a></li>
|
||||
<li><a href='#ticket_priority'>ticket.priority</a></li>
|
||||
<li><a href='#ticket_get_priority_display'>ticket.get_priority_display</a></li>
|
||||
<li><a href='#ticket_last_escalation'>ticket.last_escalation</a></li>
|
||||
<li><a href='#ticket_ticket'>ticket.ticket</a></li>
|
||||
<li><a href='#ticket_ticket_for_url'>ticket.ticket_for_url</a></li>
|
||||
<li><a href='#ticket_get_status'>ticket.get_status</a></li>
|
||||
<li><a href='#ticket_ticket_url'>ticket.ticket_url</a></li>
|
||||
<li><a href='#ticket_staff_url'>ticket.staff_url</a></li>
|
||||
<li><a href='#ticket_assigned_to'>ticket.assigned_to</a></li>
|
||||
<li><a href='#ticket_queue'>ticket.queue</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id='introduction'>Introduction</h2>
|
||||
|
||||
<p>Jutda Helpdesk provides a powerful way for you to embed fields from the current ticket into your comments and ticket resolutions using a template language.</p>
|
||||
|
||||
<p>For example, you may want to place the last escalation date into a ticket comment, or reproduce the original description sent to you by the submitter.</p>
|
||||
|
||||
<p><strong>Tech Note:</strong> This system uses the <a href='http://docs.djangoproject.com/en/dev/topics/templates/#variables'>Django templating system</a> with a sandboxed template context.</p>
|
||||
|
||||
<h2 id='usage'>Inserting Fields</h2>
|
||||
|
||||
<p>In your comment, enter the field name surrounded by double curly braces. For example, to get the ticket title, use:</p>
|
||||
|
||||
<pre>{{ ticket.title }}</pre>
|
||||
|
||||
<h2 id='queue'>Queue Fields</h2>
|
||||
|
||||
<p>The following fields are available in the template context to display the details of the queue to which this ticket belongs:</p>
|
||||
|
||||
<dl>
|
||||
<dt id='queue_title'>queue.title</dt>
|
||||
<dd>The display title of the queue</dd>
|
||||
|
||||
<dt id='queue_slug'>queue.slug</dt>
|
||||
<dd>The 'slug' of the queue, a single-word lowercase identifier used in URL's and e-mail subjects.</dd>
|
||||
|
||||
<dt id='queue_email_address'>queue.email_address</dt>
|
||||
<dd>The e-mail address to which users can send an e-mail to open a new ticket automatically.</dd>
|
||||
|
||||
<dt id='queue_from_address'>queue.from_address</dt>
|
||||
<dd>The e-mail address from which the queue will send e-mails to submitters.</dd>
|
||||
</dl>
|
||||
|
||||
<h2 id='ticket'>Ticket Fields</h2>
|
||||
|
||||
<dl>
|
||||
|
||||
<dt id='ticket_title'>ticket.title</dt>
|
||||
<dd>Title of the ticket, as provided by the submitter. A single line of text.</dd>
|
||||
|
||||
<dt id='ticket_created'>ticket.created</dt>
|
||||
<dd>The time/date this ticket was first opened</dd>
|
||||
|
||||
<dt id='ticket_modified'>ticket.modified</dt>
|
||||
<dd>The time/date this ticket was most recently changed</dd>
|
||||
|
||||
<dt id='ticket_submitter_email'>ticket.submitter_email</dt>
|
||||
<dd>E-Mail address of the ticket submitter</dd>
|
||||
|
||||
<dt id='ticket_status'>ticket.status</dt>
|
||||
<dd>Status of this ticket (Integer)</dd>
|
||||
|
||||
<dt id='ticket_get_status_display'>ticket.get_status_display</dt>
|
||||
<dd>Status of this ticket (Text-based)</dd>
|
||||
|
||||
<dt id='ticket_get_status'>ticket.get_status</dt>
|
||||
<dd>Status of this ticket (Text-based, includes 'On Hold' if required)</dd>
|
||||
|
||||
<dt id='ticket_on_hold'>ticket.on_hold</dt>
|
||||
<dd>Indicates whether this ticket is on hold (True/False)</dd>
|
||||
|
||||
<dt id='ticket_description'>ticket.description</dt>
|
||||
<dd>The description of the ticket, eg the body of the e-mail sent or the problem entered by the submitter</dd>
|
||||
|
||||
<dt id='ticket_resolution'>ticket.resolution</dt>
|
||||
<dd>The resolution of the ticket provided by staff. This may be blank.</dd>
|
||||
|
||||
<dt id='ticket_priority'>ticket.priority</dt>
|
||||
<dd>The priority of this ticket (1-5, Integer only)</dd>
|
||||
|
||||
<dt id='ticket_get_priority_display'>ticket.get_priority_display</dt>
|
||||
<dd>The priority of this ticket (Text-based)</dd>
|
||||
|
||||
<dt id='ticket_last_escalation'>ticket.last_escalation</dt>
|
||||
<dd>The time/date this ticket was last escalated</dd>
|
||||
|
||||
<dt id='ticket_ticket'>ticket.ticket</dt>
|
||||
<dd>The ticket ID in form '[queue_slug-id]', used in e-mail subjects.</dd>
|
||||
|
||||
<dt id='ticket_ticket_for_url'>ticket.ticket_for_url</dt>
|
||||
<dd>The ticket ID in form 'queue_slug-id', used in URLs</dd>
|
||||
|
||||
<dt id='ticket_ticket_url'>ticket.ticket_url</dt>
|
||||
<dd>Public URL for this ticket</dd>
|
||||
|
||||
<dt id='ticket_staff_url'>ticket.staff_url</dt>
|
||||
<dd>Staff-only URL for this ticket</dd>
|
||||
|
||||
<dt id='ticket_assigned_to'>ticket.assigned_to</dt>
|
||||
<dd>Name of the staff member assigned to this ticket, or 'Unassigned' if it is unassigned.</dd>
|
||||
|
||||
<dt id='ticket_queue'>ticket.queue</dt>
|
||||
<dd>Another dictionary of queue information, identical to <a href='#queue'>queue</a> above. For example, use ticket.queue.title.</dd>
|
||||
</dl>
|
||||
|
||||
{% endblock %}
|
@ -116,7 +116,7 @@
|
||||
|
||||
<dt><label for='commentBox'>{% trans "Comment / Resolution" %}</label></dt>
|
||||
<dd><textarea rows='8' cols='70' name='comment' id='commentBox'></textarea></dd>
|
||||
<dd class='form_help_text'>{% trans "You can use the {{ ticket }} and {{ queue }} template variables in your message." %}</dd>
|
||||
<dd class='form_help_text'>{% trans "You can insert ticket and queue details in your message. For more information, see the <a href='../../help/context/'>context help page</a>." %}</dd>
|
||||
|
||||
<dt><label>{% trans "New Status" %}</label></dt>
|
||||
{% ifequal ticket.status 1 %}
|
||||
|
17
urls.py
17
urls.py
@ -91,11 +91,6 @@ urlpatterns += patterns('',
|
||||
'helpdesk.views.api.api',
|
||||
name='helpdesk_api'),
|
||||
|
||||
url(r'^api/$',
|
||||
'django.views.generic.simple.direct_to_template',
|
||||
{'template': 'helpdesk/api_help.html',},
|
||||
name='helpdesk_api_help'),
|
||||
|
||||
url(r'^login/$',
|
||||
'django.contrib.auth.views.login',
|
||||
name='login'),
|
||||
@ -118,3 +113,15 @@ urlpatterns += patterns('helpdesk.views.kb',
|
||||
url(r'^kb/(?P<item>[0-9]+)/vote/$',
|
||||
'vote', name='helpdesk_kb_vote'),
|
||||
)
|
||||
|
||||
urlpatterns += patterns('',
|
||||
url(r'^api/$',
|
||||
'django.views.generic.simple.direct_to_template',
|
||||
{'template': 'helpdesk/help_api.html',},
|
||||
name='helpdesk_api_help'),
|
||||
|
||||
url(r'^help/context/$',
|
||||
'django.views.generic.simple.direct_to_template',
|
||||
{'template': 'helpdesk/help_context.html',},
|
||||
name='helpdesk_help_context'),
|
||||
)
|
||||
|
@ -8,7 +8,7 @@ api.py - Wrapper around API calls, and core functions to provide complete
|
||||
|
||||
The API documentation can be accessed by visiting http://helpdesk/api/help/
|
||||
(obviously, substitute helpdesk for your Jutda Helpdesk URI), or by reading
|
||||
through templates/helpdesk/api_help.html.
|
||||
through templates/helpdesk/help_api.html.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
@ -47,7 +47,7 @@ def api(request, method):
|
||||
"""
|
||||
|
||||
if method == 'help':
|
||||
return render_to_response('helpdesk/api_help.html')
|
||||
return render_to_response('helpdesk/help_api.html')
|
||||
|
||||
if request.method != 'POST':
|
||||
return api_return(STATUS_ERROR_BADMETHOD)
|
||||
|
@ -21,7 +21,7 @@ from django.template import loader, Context, RequestContext
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from helpdesk.forms import TicketForm
|
||||
from helpdesk.lib import send_templated_mail, line_chart, bar_chart, query_to_dict, apply_query
|
||||
from helpdesk.lib import send_templated_mail, line_chart, bar_chart, query_to_dict, apply_query, safe_template_context
|
||||
from helpdesk.models import Ticket, Queue, FollowUp, TicketChange, PreSetReply, Attachment, SavedSearch
|
||||
|
||||
|
||||
@ -133,6 +133,12 @@ def update_ticket(request, ticket_id):
|
||||
owner = int(request.POST.get('owner', None))
|
||||
priority = int(request.POST.get('priority', ticket.priority))
|
||||
|
||||
# We need to allow the 'ticket' and 'queue' contexts to be applied to the
|
||||
# comment.
|
||||
from django.template import loader, Context
|
||||
context = Context(safe_template_context(ticket))
|
||||
comment = loader.get_template_from_string(comment).render(context)
|
||||
|
||||
if not owner and ticket.assigned_to:
|
||||
owner = ticket.assigned_to.id
|
||||
|
||||
@ -284,6 +290,8 @@ def ticket_list(request):
|
||||
'other_filter': None,
|
||||
}
|
||||
|
||||
from_saved_query = False
|
||||
|
||||
if request.GET.get('saved_query', None):
|
||||
from_saved_query = True
|
||||
try:
|
||||
@ -295,8 +303,21 @@ def ticket_list(request):
|
||||
|
||||
import base64, cPickle
|
||||
query_params = cPickle.loads(base64.urlsafe_b64decode(str(saved_query.query)))
|
||||
elif not ( request.GET.has_key('queue')
|
||||
or request.GET.has_key('assigned_to')
|
||||
or request.GET.has_key('status')
|
||||
or request.GET.has_key('q')
|
||||
or request.GET.has_key('sort') ):
|
||||
|
||||
# Fall-back if no querying is being done, force the list to only
|
||||
# show open/reopened/resolved (not closed) cases sorted by creation
|
||||
# date.
|
||||
|
||||
query_params = {
|
||||
'filtering': {'status__in': [1, 2, 3]},
|
||||
'sorting': 'created',
|
||||
}
|
||||
else:
|
||||
from_saved_query = False
|
||||
queues = request.GET.getlist('queue')
|
||||
if queues:
|
||||
queues = [int(q) for q in queues]
|
||||
|
Loading…
Reference in New Issue
Block a user