forked from extern/django-helpdesk
Initial shot at custom fields on Ticket model. Manage these fields via Django admin.
This commit is contained in:
parent
723b4f1881
commit
ebe0382725
@ -2,6 +2,7 @@ from django.contrib import admin
|
|||||||
from helpdesk.models import Queue, Ticket, FollowUp, PreSetReply, KBCategory
|
from helpdesk.models import Queue, Ticket, FollowUp, PreSetReply, KBCategory
|
||||||
from helpdesk.models import EscalationExclusion, EmailTemplate, KBItem
|
from helpdesk.models import EscalationExclusion, EmailTemplate, KBItem
|
||||||
from helpdesk.models import TicketChange, Attachment, IgnoreEmail
|
from helpdesk.models import TicketChange, Attachment, IgnoreEmail
|
||||||
|
from helpdesk.models import CustomField
|
||||||
|
|
||||||
class QueueAdmin(admin.ModelAdmin):
|
class QueueAdmin(admin.ModelAdmin):
|
||||||
list_display = ('title', 'slug', 'email_address')
|
list_display = ('title', 'slug', 'email_address')
|
||||||
@ -24,6 +25,9 @@ class KBItemAdmin(admin.ModelAdmin):
|
|||||||
list_display = ('category', 'title', 'last_updated',)
|
list_display = ('category', 'title', 'last_updated',)
|
||||||
list_display_links = ('title',)
|
list_display_links = ('title',)
|
||||||
|
|
||||||
|
class CustomFieldAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('name', 'label', 'data_type')
|
||||||
|
|
||||||
admin.site.register(Ticket, TicketAdmin)
|
admin.site.register(Ticket, TicketAdmin)
|
||||||
admin.site.register(Queue, QueueAdmin)
|
admin.site.register(Queue, QueueAdmin)
|
||||||
admin.site.register(FollowUp, FollowUpAdmin)
|
admin.site.register(FollowUp, FollowUpAdmin)
|
||||||
@ -33,3 +37,4 @@ admin.site.register(EmailTemplate)
|
|||||||
admin.site.register(KBCategory)
|
admin.site.register(KBCategory)
|
||||||
admin.site.register(KBItem, KBItemAdmin)
|
admin.site.register(KBItem, KBItemAdmin)
|
||||||
admin.site.register(IgnoreEmail)
|
admin.site.register(IgnoreEmail)
|
||||||
|
admin.site.register(CustomField, CustomFieldAdmin)
|
||||||
|
@ -15,7 +15,7 @@ from django.contrib.auth.models import User
|
|||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from helpdesk.lib import send_templated_mail
|
from helpdesk.lib import send_templated_mail
|
||||||
from helpdesk.models import Ticket, Queue, FollowUp, Attachment, IgnoreEmail, TicketCC
|
from helpdesk.models import Ticket, Queue, FollowUp, Attachment, IgnoreEmail, TicketCC, CustomField, TicketCustomFieldValue
|
||||||
from helpdesk.settings import HAS_TAG_SUPPORT
|
from helpdesk.settings import HAS_TAG_SUPPORT
|
||||||
|
|
||||||
class EditTicketForm(forms.ModelForm):
|
class EditTicketForm(forms.ModelForm):
|
||||||
@ -93,6 +93,56 @@ class TicketForm(forms.Form):
|
|||||||
'ticket'),
|
'ticket'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Add any custom fields that are defined to the form
|
||||||
|
"""
|
||||||
|
super(TicketForm, self).__init__(*args, **kwargs)
|
||||||
|
for field in CustomField.objects.all():
|
||||||
|
instanceargs = {
|
||||||
|
'label': field.label,
|
||||||
|
'help_text': field.help_text,
|
||||||
|
'required': field.required,
|
||||||
|
}
|
||||||
|
if field.data_type == 'varchar':
|
||||||
|
fieldclass = forms.CharField
|
||||||
|
instanceargs['max_length'] = field.max_length
|
||||||
|
elif field.data_type == 'text':
|
||||||
|
fieldclass = forms.CharField
|
||||||
|
instanceargs['widget'] = forms.Textarea
|
||||||
|
instanceargs['max_length'] = field.max_length
|
||||||
|
elif field.data_type == 'integer':
|
||||||
|
fieldclass = forms.IntegerField
|
||||||
|
elif field.data_type == 'decimal':
|
||||||
|
fieldclass = forms.DecimalField
|
||||||
|
instanceargs['decimal_places'] = field.decimal_places
|
||||||
|
instanceargs['max_digits'] = field.max_length
|
||||||
|
elif field.data_type == 'list':
|
||||||
|
fieldclass = forms.ChoiceField
|
||||||
|
choices = []
|
||||||
|
for line in field.list_values.split("\n"):
|
||||||
|
choices.append((line, line))
|
||||||
|
instanceargs['choices'] = choices
|
||||||
|
elif field.data_type == 'boolean':
|
||||||
|
fieldclass = forms.BooleanField
|
||||||
|
elif field.data_type == 'date':
|
||||||
|
fieldclass = forms.DateField
|
||||||
|
elif field.data_type == 'time':
|
||||||
|
fieldclass = forms.TimeField
|
||||||
|
elif field.data_type == 'datetime':
|
||||||
|
fieldclass = forms.DateTimeField
|
||||||
|
elif field.data_type == 'email':
|
||||||
|
fieldclass = forms.EmailField
|
||||||
|
elif field.data_type == 'url':
|
||||||
|
fieldclass = forms.URLField
|
||||||
|
elif field.data_type == 'ipaddress':
|
||||||
|
fieldclass = forms.IPAddressField
|
||||||
|
elif field.data_type == 'slug':
|
||||||
|
fieldclass = forms.SlugField
|
||||||
|
|
||||||
|
self.fields['custom_%s' % field.name] = fieldclass(**instanceargs)
|
||||||
|
|
||||||
|
|
||||||
def save(self, user):
|
def save(self, user):
|
||||||
"""
|
"""
|
||||||
Writes and returns a Ticket() object
|
Writes and returns a Ticket() object
|
||||||
@ -120,6 +170,15 @@ class TicketForm(forms.Form):
|
|||||||
t.assigned_to = None
|
t.assigned_to = None
|
||||||
t.save()
|
t.save()
|
||||||
|
|
||||||
|
for field, value in self.cleaned_data.items():
|
||||||
|
if field.startswith('custom_'):
|
||||||
|
field_name = field.replace('custom_', '')
|
||||||
|
customfield = CustomField.objects.get(name=field_name)
|
||||||
|
cfv = TicketCustomFieldValue(ticket=t,
|
||||||
|
field=customfield,
|
||||||
|
value=value)
|
||||||
|
cfv.save()
|
||||||
|
|
||||||
f = FollowUp( ticket = t,
|
f = FollowUp( ticket = t,
|
||||||
title = _('Ticket Opened'),
|
title = _('Ticket Opened'),
|
||||||
date = datetime.now(),
|
date = datetime.now(),
|
||||||
@ -249,6 +308,54 @@ class PublicTicketForm(forms.Form):
|
|||||||
help_text=_('You can attach a file such as a document or screenshot to this ticket.'),
|
help_text=_('You can attach a file such as a document or screenshot to this ticket.'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Add any custom fields that are defined to the form
|
||||||
|
"""
|
||||||
|
super(PublicTicketForm, self).__init__(*args, **kwargs)
|
||||||
|
for field in CustomField.objects.filter(staff_only=False):
|
||||||
|
instanceargs = {
|
||||||
|
'label': field.label,
|
||||||
|
'help_text': field.help_text,
|
||||||
|
'required': field.required,
|
||||||
|
}
|
||||||
|
if field.data_type == 'varchar':
|
||||||
|
fieldclass = forms.CharField
|
||||||
|
instanceargs['max_length'] = field.max_length
|
||||||
|
elif field.data_type == 'text':
|
||||||
|
fieldclass = forms.TextField
|
||||||
|
instanceargs['max_length'] = field.max_length
|
||||||
|
elif field.data_type == 'integer':
|
||||||
|
fieldclass = forms.IntegerField
|
||||||
|
elif field.data_type == 'decimal':
|
||||||
|
fieldclass = forms.DecimalField
|
||||||
|
instanceargs['decimal_places'] = field.decimal_places
|
||||||
|
instanceargs['max_digits'] = field.max_length
|
||||||
|
elif field.data_type == 'list':
|
||||||
|
fieldclass = forms.ChoiceField
|
||||||
|
choices = ()
|
||||||
|
for line in field.choices:
|
||||||
|
choices.append((line, line))
|
||||||
|
instanceargs['choices'] = choices
|
||||||
|
elif field.data_type == 'boolean':
|
||||||
|
fieldclass = forms.BooleanField
|
||||||
|
elif field.data_type == 'date':
|
||||||
|
fieldclass = forms.DateField
|
||||||
|
elif field.data_type == 'time':
|
||||||
|
fieldclass = forms.TimeField
|
||||||
|
elif field.data_type == 'datetime':
|
||||||
|
fieldclass = forms.DateTimeField
|
||||||
|
elif field.data_type == 'email':
|
||||||
|
fieldclass = forms.EmailField
|
||||||
|
elif field.data_type == 'url':
|
||||||
|
fieldclass = forms.URLField
|
||||||
|
elif field.data_type == 'ipaddress':
|
||||||
|
fieldclass = forms.IPAddressField
|
||||||
|
elif field.data_type == 'slug':
|
||||||
|
fieldclass = forms.SlugField
|
||||||
|
|
||||||
|
self.fields['custom_%s' % field.name] = fieldclass(**instanceargs)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""
|
"""
|
||||||
Writes and returns a Ticket() object
|
Writes and returns a Ticket() object
|
||||||
@ -268,6 +375,15 @@ class PublicTicketForm(forms.Form):
|
|||||||
|
|
||||||
t.save()
|
t.save()
|
||||||
|
|
||||||
|
for field, value in self.cleaned_data.items():
|
||||||
|
if field.startswith('custom_'):
|
||||||
|
field_name = field.replace('custom_', '')
|
||||||
|
customfield = CustomField.objects.get(name=field_name)
|
||||||
|
cfv = TicketCustomFieldValue(ticket=t,
|
||||||
|
field=customfield,
|
||||||
|
value=value)
|
||||||
|
cfv.save()
|
||||||
|
|
||||||
f = FollowUp(
|
f = FollowUp(
|
||||||
ticket = t,
|
ticket = t,
|
||||||
title = _('Ticket Opened Via Web'),
|
title = _('Ticket Opened Via Web'),
|
||||||
|
@ -1085,3 +1085,102 @@ class TicketCC(models.Model):
|
|||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u'%s for %s' % (self.display, self.ticket.title)
|
return u'%s for %s' % (self.display, self.ticket.title)
|
||||||
|
|
||||||
|
|
||||||
|
class CustomField(models.Model):
|
||||||
|
"""
|
||||||
|
Definitions for custom fields that are glued onto each ticket.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = models.SlugField(
|
||||||
|
_('Field Name'),
|
||||||
|
help_text=_('As used in the database and behind the scenes. Must be unique and consist of only lowercase letters with no punctuation.'),
|
||||||
|
unique=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
label = models.CharField(
|
||||||
|
_('Label'),
|
||||||
|
max_length='30',
|
||||||
|
help_text=_('The display label for this field'),
|
||||||
|
)
|
||||||
|
|
||||||
|
help_text = models.TextField(
|
||||||
|
_('Help Text'),
|
||||||
|
help_text=_('Shown to the user when editing the ticket'),
|
||||||
|
)
|
||||||
|
|
||||||
|
DATA_TYPE_CHOICES = (
|
||||||
|
('varchar', _('Character (single line)')),
|
||||||
|
('text', _('Text (multi-line)')),
|
||||||
|
('integer', _('Integer')),
|
||||||
|
('decimal', _('Decimal')),
|
||||||
|
('list', _('List')),
|
||||||
|
('boolean', _('Boolean (checkbox yes/no)')),
|
||||||
|
('date', _('Date')),
|
||||||
|
('time', _('Time')),
|
||||||
|
('datetime', _('Date & Time')),
|
||||||
|
('email', _('E-Mail Address')),
|
||||||
|
('url', _('URL')),
|
||||||
|
('ipaddress', _('IP Address')),
|
||||||
|
('slug', _('Slug')),
|
||||||
|
)
|
||||||
|
|
||||||
|
data_type = models.CharField(
|
||||||
|
_('Data Type'),
|
||||||
|
max_length=100,
|
||||||
|
help_text=_('Allows you to restrict the data entered into this field'),
|
||||||
|
choices=DATA_TYPE_CHOICES,
|
||||||
|
)
|
||||||
|
|
||||||
|
max_length = models.IntegerField(
|
||||||
|
_('Maximum Length (characters)'),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
decimal_places = models.IntegerField(
|
||||||
|
_('Decimal Places'),
|
||||||
|
help_text=_('Only used for decimal fields'),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
list_values = models.TextField(
|
||||||
|
_('List Values'),
|
||||||
|
help_text=_('For list fields only. Enter one option per line.'),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
required = models.BooleanField(
|
||||||
|
_('Required?'),
|
||||||
|
help_text=_('Does the user have to enter a value for this field?'),
|
||||||
|
)
|
||||||
|
|
||||||
|
staff_only = models.BooleanField(
|
||||||
|
_('Staff Only?'),
|
||||||
|
help_text=_('If this is ticked, then the public submission form will NOT show this field'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return '%s' % (self.name)
|
||||||
|
|
||||||
|
|
||||||
|
class TicketCustomFieldValue(models.Model):
|
||||||
|
ticket = models.ForeignKey(
|
||||||
|
Ticket,
|
||||||
|
verbose_name=_('Ticket'),
|
||||||
|
)
|
||||||
|
|
||||||
|
field = models.ForeignKey(
|
||||||
|
CustomField,
|
||||||
|
verbose_name=_('Field'),
|
||||||
|
)
|
||||||
|
|
||||||
|
value = models.TextField(blank=True, null=True)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return '%s / %s' % (self.ticket, self.field)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
unique_together = ('ticket', 'field'),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{% extends "helpdesk/public_base.html" %}{% load i18n %}
|
{% extends "helpdesk/public_base.html" %}{% load i18n %}
|
||||||
|
{% cycle 'row_odd' 'row_even' as rowcolors %}
|
||||||
{% block helpdesk_title %}{% trans "View a Ticket" %}{% endblock %}
|
{% block helpdesk_title %}{% trans "View a Ticket" %}{% endblock %}
|
||||||
|
|
||||||
{% block helpdesk_body %}
|
{% block helpdesk_body %}
|
||||||
@ -7,39 +8,45 @@
|
|||||||
<tr class='row_tablehead'><td colspan='2'>{{ ticket.id }}. {{ ticket.title }} [{{ ticket.get_status }}]</td></tr>
|
<tr class='row_tablehead'><td colspan='2'>{{ ticket.id }}. {{ ticket.title }} [{{ ticket.get_status }}]</td></tr>
|
||||||
<tr class='row_columnheads'><th colspan='2'>{% blocktrans with ticket.queue as queue_name %}Queue: {{ queue_name }}{% endblocktrans %}</th></tr>
|
<tr class='row_columnheads'><th colspan='2'>{% blocktrans with ticket.queue as queue_name %}Queue: {{ queue_name }}{% endblocktrans %}</th></tr>
|
||||||
|
|
||||||
<tr class='row_odd'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Submitted On" %}</th>
|
<th>{% trans "Submitted On" %}</th>
|
||||||
<td>{{ ticket.created|date:"r" }} ({{ ticket.created|timesince }} ago)</td>
|
<td>{{ ticket.created|date:"r" }} ({{ ticket.created|timesince }} ago)</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr class='row_even'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Submitter E-Mail" %}</th>
|
<th>{% trans "Submitter E-Mail" %}</th>
|
||||||
<td>{{ ticket.submitter_email }}</td>
|
<td>{{ ticket.submitter_email }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr class='row_odd'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Priority" %}</th>
|
<th>{% trans "Priority" %}</th>
|
||||||
<td>{{ ticket.get_priority_display }}</td>
|
<td>{{ ticket.get_priority_display }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
{% for customfield in ticket.ticketcustomfieldvalue_set.all %}
|
||||||
|
<tr class='{% cycle rowcolors %}'>
|
||||||
|
<th>{{ customfield.field.label }}</th>
|
||||||
|
<td>{{ customfield.value }}</td>
|
||||||
|
</tr>{% endfor %}
|
||||||
|
|
||||||
{% if tags_enabled %}
|
{% if tags_enabled %}
|
||||||
<tr class='row_even'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Tags" %}</th>
|
<th>{% trans "Tags" %}</th>
|
||||||
<td>{{ ticket.tags }}</td>
|
<td>{{ ticket.tags }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<tr class='row_{% if tags_enabled %}odd{% else %}even{% endif %}'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th colspan='2'>{% trans "Description" %}</th>
|
<th colspan='2'>{% trans "Description" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class='row_{% if tags_enabled %}odd{% else %}even{% endif %}'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<td colspan='2'>{{ ticket.description|force_escape|urlizetrunc:50|linebreaksbr }}</td>
|
<td colspan='2'>{{ ticket.description|force_escape|urlizetrunc:50|linebreaksbr }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% if ticket.resolution %}<tr class='row_{% if tags_enabled %}even{% else %}odd{% endif %}'>
|
{% if ticket.resolution %}<tr class='{% cycle rowcolors %}'>
|
||||||
<th colspan='2'>{% trans "Resolution" %}{% ifequal ticket.get_status_display "Resolved" %} <a href='{{ request.get_full_path }}&close'><img src='{{ MEDIA_URL }}/helpdesk/buttons/accept.png' alt='{% trans "Accept" %}' title='{% trans "Accept and Close" %}' width='60' height='15' /></a>{% endifequal %}</th>
|
<th colspan='2'>{% trans "Resolution" %}{% ifequal ticket.get_status_display "Resolved" %} <a href='{{ request.get_full_path }}&close'><img src='{{ MEDIA_URL }}/helpdesk/buttons/accept.png' alt='{% trans "Accept" %}' title='{% trans "Accept and Close" %}' width='60' height='15' /></a>{% endifequal %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class='row_{% if tags_enabled %}even{% else %}odd{% endif %}'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<td colspan='2'>{{ ticket.resolution|urlizetrunc:50|linebreaksbr }}</td>
|
<td colspan='2'>{{ ticket.resolution|urlizetrunc:50|linebreaksbr }}</td>
|
||||||
</tr>{% endif %}
|
</tr>{% endif %}
|
||||||
|
|
||||||
|
@ -1,52 +1,58 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% cycle 'row_odd' 'row_even' as rowcolors %}
|
||||||
<table width='100%'>
|
<table width='100%'>
|
||||||
<tr class='row_tablehead'><td>{{ ticket.id }}. {{ ticket.title }} [{{ ticket.get_status }}]</td><td align='right'><a href='{% url helpdesk_edit ticket.id %}'><img src='{{ MEDIA_URL }}helpdesk/buttons/edit.png' alt='Edit' title='Edit' width='60' height='15' /></a><a href='{% url helpdesk_delete ticket.id %}'><img src='{{ MEDIA_URL }}helpdesk/buttons/delete.png' alt='Delete' title='Delete' width='60' height='15' /></a>{% if ticket.on_hold %}<a href='unhold/'>{% trans "Unhold" %}</a>{% else %}<a href='hold/'>{% trans "Hold" %}</a>{% endif %}</td></tr>
|
<tr class='row_tablehead'><td>{{ ticket.id }}. {{ ticket.title }} [{{ ticket.get_status }}]</td><td align='right'><a href='{% url helpdesk_edit ticket.id %}'><img src='{{ MEDIA_URL }}helpdesk/buttons/edit.png' alt='Edit' title='Edit' width='60' height='15' /></a><a href='{% url helpdesk_delete ticket.id %}'><img src='{{ MEDIA_URL }}helpdesk/buttons/delete.png' alt='Delete' title='Delete' width='60' height='15' /></a>{% if ticket.on_hold %}<a href='unhold/'>{% trans "Unhold" %}</a>{% else %}<a href='hold/'>{% trans "Hold" %}</a>{% endif %}</td></tr>
|
||||||
<tr class='row_columnheads'><th colspan='2'>{% blocktrans with ticket.queue as queue %}Queue: {{ queue }}{% endblocktrans %}</th></tr>
|
<tr class='row_columnheads'><th colspan='2'>{% blocktrans with ticket.queue as queue %}Queue: {{ queue }}{% endblocktrans %}</th></tr>
|
||||||
|
|
||||||
<tr class='row_odd'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Submitted On" %}</th>
|
<th>{% trans "Submitted On" %}</th>
|
||||||
<td>{{ ticket.created|date:"r" }} ({{ ticket.created|timesince }} ago)</td>
|
<td>{{ ticket.created|date:"r" }} ({{ ticket.created|timesince }} ago)</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr class='row_even'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Assigned To" %}</th>
|
<th>{% trans "Assigned To" %}</th>
|
||||||
<td>{{ ticket.get_assigned_to }}{% ifequal ticket.get_assigned_to _('Unassigned') %} <strong><a href='?take'><span class='button button_take'>{% trans "Take" %}</span></a></strong>{% endifequal %}</td>
|
<td>{{ ticket.get_assigned_to }}{% ifequal ticket.get_assigned_to _('Unassigned') %} <strong><a href='?take'><span class='button button_take'>{% trans "Take" %}</span></a></strong>{% endifequal %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr class='row_odd'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Submitter E-Mail" %}</th>
|
<th>{% trans "Submitter E-Mail" %}</th>
|
||||||
<td>{{ ticket.submitter_email }}{% if user.is_superuser %} <strong><a href='{% url helpdesk_email_ignore_add %}?email={{ ticket.submitter_email }}'>{% trans "Ignore" %}</a></strong>{% endif %}</td>
|
<td>{{ ticket.submitter_email }}{% if user.is_superuser %} <strong><a href='{% url helpdesk_email_ignore_add %}?email={{ ticket.submitter_email }}'>{% trans "Ignore" %}</a></strong>{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr class='row_even'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Priority" %}</th>
|
<th>{% trans "Priority" %}</th>
|
||||||
<td>{{ ticket.get_priority_display }}</td>
|
<td>{{ ticket.get_priority_display }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr class='row_odd'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Copies To" %}</th>
|
<th>{% trans "Copies To" %}</th>
|
||||||
<td>{% for ticketcc in ticket.ticketcc_set.all %}{{ ticketcc.display }}{% if not forloop.last %}, {% endif %}{% endfor %} <strong><a href='{% url helpdesk_ticket_cc ticket.id %}'>{% trans "Manage" %}</a></strong></td>
|
<td>{% for ticketcc in ticket.ticketcc_set.all %}{{ ticketcc.display }}{% if not forloop.last %}, {% endif %}{% endfor %} <strong><a href='{% url helpdesk_ticket_cc ticket.id %}'>{% trans "Manage" %}</a></strong></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% if tags_enabled %}
|
{% if tags_enabled %}
|
||||||
<tr class='row_even'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th>{% trans "Tags" %}</th>
|
<th>{% trans "Tags" %}</th>
|
||||||
<td>{{ ticket.tags }}</td>
|
<td>{{ ticket.tags }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<tr class='row_even'>
|
{% for customfield in ticket.ticketcustomfieldvalue_set.all %}
|
||||||
<tr class='row_{% if tags_enabled %}odd{% else %}even{% endif %}'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
|
<th>{{ customfield.field.label }}</th>
|
||||||
|
<td>{{ customfield.value }}</td>
|
||||||
|
</tr>{% endfor %}
|
||||||
|
|
||||||
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<th colspan='2'>{% trans "Description" %}</th>
|
<th colspan='2'>{% trans "Description" %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class='row_{% if tags_enabled %}even{% else %}odd{% endif %}'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<td colspan='2'>{{ ticket.description|force_escape|urlizetrunc:50|linebreaksbr }}</td>
|
<td colspan='2'>{{ ticket.description|force_escape|urlizetrunc:50|linebreaksbr }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% if ticket.resolution %}<tr class='row_{% if tags_enabled %}odd{% else %}even{% endif %}'>
|
{% if ticket.resolution %}<tr class='{% cycle rowcolors %}'>
|
||||||
<th colspan='2'>{% trans "Resolution" %}{% ifequal ticket.get_status_display "Resolved" %} <a href='?close'><img src='{{ MEDIA_URL }}helpdesk/buttons/accept.png' alt='{% trans "Accept" %}' title='{% trans "Accept and Close" %}' width='60' height='15' /></a>{% endifequal %}</th>
|
<th colspan='2'>{% trans "Resolution" %}{% ifequal ticket.get_status_display "Resolved" %} <a href='?close'><img src='{{ MEDIA_URL }}helpdesk/buttons/accept.png' alt='{% trans "Accept" %}' title='{% trans "Accept and Close" %}' width='60' height='15' /></a>{% endifequal %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class='row_{% if tags_enabled %}even{% else %}odd{% endif %}'>
|
<tr class='{% cycle rowcolors %}'>
|
||||||
<td colspan='2'>{{ ticket.resolution|force_escape|urlizetrunc:50|linebreaksbr }}</td>
|
<td colspan='2'>{{ ticket.resolution|force_escape|urlizetrunc:50|linebreaksbr }}</td>
|
||||||
</tr>{% endif %}
|
</tr>{% endif %}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user