mirror of
https://github.com/django-helpdesk/django-helpdesk.git
synced 2025-08-16 19:01:21 +02:00
make django-helpdesk more customizable + bug fixes:
- look at settings.py for all new options regarding customization. - settings can be accessed inside the templates via the new templatetag 'load_helpdesk_settings' - allow editing of personal followups, but only if followup does not contain any ticketchanges - otherwise this information is lost after the editing. - add 'delete' link to attachments - link to list of closed tickets in queue overview - add 'closed & resolved' section to dashboard - hide 'pre-set reply' box if no pre-set replies are found. - use 'SelectDateWidget' for custom DateField - fix how we update followups so that attachments don't get deleted - fix bug where resolution emails contained the solution 'None' - fix stats crashing bug - fix locale bug
This commit is contained in:
@ -28,14 +28,20 @@ from helpdesk.forms import TicketForm, UserSettingsForm, EmailIgnoreForm, EditTi
|
||||
from helpdesk.lib import send_templated_mail, query_to_dict, apply_query, safe_template_context
|
||||
from helpdesk.models import Ticket, Queue, FollowUp, TicketChange, PreSetReply, Attachment, SavedSearch, IgnoreEmail, TicketCC, TicketDependency
|
||||
from helpdesk.settings import HAS_TAG_SUPPORT
|
||||
from helpdesk import settings as helpdesk_settings
|
||||
|
||||
if HAS_TAG_SUPPORT:
|
||||
from tagging.models import Tag, TaggedItem
|
||||
|
||||
staff_member_required = user_passes_test(lambda u: u.is_authenticated() and u.is_active and u.is_staff)
|
||||
superuser_required = user_passes_test(lambda u: u.is_authenticated() and u.is_active and u.is_superuser)
|
||||
if helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE:
|
||||
# treat 'normal' users like 'staff'
|
||||
staff_member_required = user_passes_test(lambda u: u.is_authenticated() and u.is_active)
|
||||
else:
|
||||
staff_member_required = user_passes_test(lambda u: u.is_authenticated() and u.is_active and u.is_staff)
|
||||
|
||||
|
||||
superuser_required = user_passes_test(lambda u: u.is_authenticated() and u.is_active and u.is_superuser)
|
||||
|
||||
|
||||
def dashboard(request):
|
||||
"""
|
||||
@ -44,12 +50,18 @@ def dashboard(request):
|
||||
with options for them to 'Take' ownership of said tickets.
|
||||
"""
|
||||
|
||||
# open & reopened tickets
|
||||
tickets = Ticket.objects.filter(
|
||||
assigned_to=request.user,
|
||||
).exclude(
|
||||
status=Ticket.CLOSED_STATUS,
|
||||
status__in = [Ticket.CLOSED_STATUS, Ticket.RESOLVED_STATUS],
|
||||
)
|
||||
|
||||
# closed & resolved tickets
|
||||
tickets_closed_resolved = Ticket.objects.filter(
|
||||
assigned_to=request.user,
|
||||
status__in = [Ticket.CLOSED_STATUS, Ticket.RESOLVED_STATUS])
|
||||
|
||||
unassigned_tickets = Ticket.objects.filter(
|
||||
assigned_to__isnull=True,
|
||||
).exclude(
|
||||
@ -67,7 +79,8 @@ def dashboard(request):
|
||||
SELECT q.id as queue,
|
||||
q.title AS name,
|
||||
COUNT(CASE t.status WHEN '1' THEN t.id WHEN '2' THEN t.id END) AS open,
|
||||
COUNT(CASE t.status WHEN '3' THEN t.id END) AS resolved
|
||||
COUNT(CASE t.status WHEN '3' THEN t.id END) AS resolved,
|
||||
COUNT(CASE t.status WHEN '4' THEN t.id END) AS closed
|
||||
FROM helpdesk_ticket t,
|
||||
helpdesk_queue q
|
||||
WHERE q.id = t.queue_id
|
||||
@ -79,6 +92,7 @@ def dashboard(request):
|
||||
return render_to_response('helpdesk/dashboard.html',
|
||||
RequestContext(request, {
|
||||
'user_tickets': tickets,
|
||||
'user_tickets_closed_resolved': tickets_closed_resolved,
|
||||
'unassigned_tickets': unassigned_tickets,
|
||||
'dash_tickets': dash_tickets,
|
||||
}))
|
||||
@ -127,9 +141,18 @@ def followup_edit(request, ticket_id, followup_id, ):
|
||||
new_status = form.cleaned_data['new_status']
|
||||
#will save previous date
|
||||
old_date = followup.date
|
||||
followup.delete()
|
||||
new_followup = FollowUp(title=title, date=old_date, ticket=_ticket, comment=comment, public=public, new_status=new_status, )
|
||||
# keep old user if one did exist before.
|
||||
if followup.user:
|
||||
new_followup.user = followup.user
|
||||
new_followup.save()
|
||||
# get list of old attachments & link them to new_followup
|
||||
attachments = Attachment.objects.filter(followup = followup)
|
||||
for attachment in attachments:
|
||||
attachment.followup = new_followup
|
||||
attachment.save()
|
||||
# delete old followup
|
||||
followup.delete()
|
||||
return HttpResponseRedirect(reverse('helpdesk_view', args=[ticket.id]))
|
||||
|
||||
def view_ticket(request, ticket_id):
|
||||
@ -169,7 +192,7 @@ def view_ticket(request, ticket_id):
|
||||
return render_to_response('helpdesk/ticket.html',
|
||||
RequestContext(request, {
|
||||
'ticket': ticket,
|
||||
'active_users': User.objects.filter(is_active=True).filter(is_staff=True).order_by('username'),
|
||||
'active_users': User.objects.filter(is_active=True).order_by('username'),
|
||||
'priorities': Ticket.PRIORITY_CHOICES,
|
||||
'preset_replies': PreSetReply.objects.filter(Q(queues=ticket.queue) | Q(queues__isnull=True)),
|
||||
'tags_enabled': HAS_TAG_SUPPORT,
|
||||
@ -178,7 +201,7 @@ view_ticket = staff_member_required(view_ticket)
|
||||
|
||||
|
||||
def update_ticket(request, ticket_id, public=False):
|
||||
if not (public or (request.user.is_authenticated() and request.user.is_active and request.user.is_staff)):
|
||||
if not (public or (request.user.is_authenticated() and request.user.is_active and (request.user.is_staff or helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE))):
|
||||
return HttpResponseForbidden(_('Sorry, you need to login to do that.'))
|
||||
|
||||
ticket = get_object_or_404(Ticket, id=ticket_id)
|
||||
@ -195,6 +218,10 @@ def update_ticket(request, ticket_id, public=False):
|
||||
# comment.
|
||||
from django.template import loader, Context
|
||||
context = safe_template_context(ticket)
|
||||
# this line sometimes creates problems if code is sent as a comment.
|
||||
# if comment contains some django code, like "why does {% if bla %} crash",
|
||||
# then the following line will give us a crash, since django expects {% if %}
|
||||
# to be closed with an {% endif %} tag.
|
||||
comment = loader.get_template_from_string(comment).render(Context(context))
|
||||
|
||||
if owner is None and ticket.assigned_to:
|
||||
@ -202,7 +229,7 @@ def update_ticket(request, ticket_id, public=False):
|
||||
|
||||
f = FollowUp(ticket=ticket, date=datetime.now(), comment=comment)
|
||||
|
||||
if request.user.is_staff:
|
||||
if request.user.is_staff or helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE:
|
||||
f.user = request.user
|
||||
|
||||
f.public = public
|
||||
@ -217,9 +244,11 @@ def update_ticket(request, ticket_id, public=False):
|
||||
}
|
||||
ticket.assigned_to = new_user
|
||||
reassigned = True
|
||||
elif owner == 0 and ticket.assigned_to is not None:
|
||||
f.title = _('Unassigned')
|
||||
ticket.assigned_to = None
|
||||
# This makes no sense to me. Why should we ever remove the 'assigned to'
|
||||
# value?
|
||||
#elif owner == 0 and ticket.assigned_to is not None:
|
||||
# f.title = _('Unassigned')
|
||||
# ticket.assigned_to = None
|
||||
|
||||
if new_status != ticket.status:
|
||||
ticket.status = new_status
|
||||
@ -289,7 +318,7 @@ def update_ticket(request, ticket_id, public=False):
|
||||
c.save()
|
||||
ticket.tags = tags
|
||||
|
||||
if f.new_status == Ticket.RESOLVED_STATUS:
|
||||
if new_status == Ticket.RESOLVED_STATUS:
|
||||
ticket.resolution = comment
|
||||
|
||||
messages_sent_to = []
|
||||
@ -377,7 +406,7 @@ def update_ticket(request, ticket_id, public=False):
|
||||
|
||||
ticket.save()
|
||||
|
||||
if request.user.is_staff:
|
||||
if request.user.is_staff or helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE:
|
||||
return HttpResponseRedirect(ticket.get_absolute_url())
|
||||
else:
|
||||
return HttpResponseRedirect(ticket.ticket_url)
|
||||
@ -419,11 +448,11 @@ def mass_update(request):
|
||||
f = FollowUp(ticket=t, date=datetime.now(), title=_('Closed in bulk update'), public=True, user=request.user, new_status=Ticket.CLOSED_STATUS)
|
||||
f.save()
|
||||
# Send email to Submitter, Owner, Queue CC
|
||||
context = {
|
||||
'ticket': t,
|
||||
'queue': t.queue,
|
||||
'resolution': t.resolution,
|
||||
}
|
||||
context = safe_template_context(t)
|
||||
context.update(
|
||||
resolution = t.resolution,
|
||||
queue = t.queue,
|
||||
)
|
||||
|
||||
messages_sent_to = []
|
||||
|
||||
@ -833,7 +862,7 @@ def run_report(request, report):
|
||||
month = 1
|
||||
if (year > last_year) or (month > last_month and year >= last_year):
|
||||
working = False
|
||||
periods.append("%s %s" % (months[month], year))
|
||||
periods.append("%s %s" % (months[month - 1], year))
|
||||
|
||||
if report == 'userpriority':
|
||||
title = _('User by Priority')
|
||||
@ -1087,3 +1116,10 @@ def ticket_dependency_del(request, ticket_id, dependency_id):
|
||||
}))
|
||||
ticket_dependency_del = staff_member_required(ticket_dependency_del)
|
||||
|
||||
def attachment_del(request, ticket_id, attachment_id):
|
||||
ticket = get_object_or_404(Ticket, id=ticket_id)
|
||||
attachment = get_object_or_404(Attachment, id=attachment_id)
|
||||
attachment.delete()
|
||||
return HttpResponseRedirect(reverse('helpdesk_view', args=[ticket_id]))
|
||||
attachment_del = staff_member_required(attachment_del)
|
||||
|
||||
|
Reference in New Issue
Block a user