mirror of
https://github.com/django-helpdesk/django-helpdesk.git
synced 2024-12-14 10:51:21 +01:00
dfb821336e
text to assist with future translation efforts. I've no doubt missed a few. Also we don't have a "Change Language" view in here, unsure if this should be a helpdesk function or a function of the parent project. * Updated svn:ignore to ignore .pyc files * Added new function to replace cursor.dictfetchall() which is available in psycopg1 but not psycopg2. New function should work across other database systems, but is untested.
204 lines
6.9 KiB
Python
204 lines
6.9 KiB
Python
""" ..
|
|
Jutda Helpdesk - A Django powered ticket tracker for small enterprise.
|
|
|
|
(c) Copyright 2008 Jutda. All Rights Reserved. See LICENSE for details.
|
|
|
|
lib.py - Common functions (eg multipart e-mail)
|
|
"""
|
|
def send_templated_mail(template_name, email_context, recipients, sender=None, bcc=None, fail_silently=False, files=None):
|
|
from helpdesk.models import EmailTemplate
|
|
from django.core.mail import EmailMultiAlternatives
|
|
from django.template import loader, Context
|
|
from django.conf import settings
|
|
|
|
t = EmailTemplate.objects.get(template_name__iexact=template_name)
|
|
|
|
if not sender:
|
|
sender = settings.DEFAULT_FROM_EMAIL
|
|
|
|
context = Context(email_context)
|
|
|
|
text_part = loader.get_template_from_string("%s{%% include 'helpdesk/email_text_footer.txt' %%}" % t.plain_text).render(context)
|
|
html_part = loader.get_template_from_string("{%% extends 'helpdesk/email_html_base.html' %%}{%% block title %%}%s{%% endblock %%}{%% block content %%}%s{%% endblock %%}" % (t.heading, t.html)).render(context)
|
|
subject_part = loader.get_template_from_string("{{ ticket.ticket }} {{ ticket.title }} %s" % t.subject).render(context)
|
|
|
|
if type(recipients) != list:
|
|
recipients = [recipients,]
|
|
|
|
msg = EmailMultiAlternatives(subject_part, text_part, sender, recipients, bcc=bcc)
|
|
msg.attach_alternative(html_part, "text/html")
|
|
|
|
if files:
|
|
if type(files) != list:
|
|
files = [files,]
|
|
|
|
for file in files:
|
|
msg.attach_file(file)
|
|
|
|
return msg.send(fail_silently)
|
|
|
|
|
|
|
|
def send_multipart_mail(template_name, email_context, subject, recipients, sender=None, bcc=None, fail_silently=False, files=None):
|
|
"""
|
|
This function will send a multi-part e-mail with both HTML and
|
|
Text parts.
|
|
|
|
template_name must NOT contain an extension. Both HTML (.html) and TEXT
|
|
(.txt) versions must exist, eg 'emails/public_submit' will use both
|
|
public_submit.html and public_submit.txt.
|
|
|
|
email_context should be a plain python dictionary. It is applied against
|
|
both the email messages (templates) & the subject.
|
|
|
|
subject can be plain text or a Django template string, eg:
|
|
New Job: {{ job.id }} {{ job.title }}
|
|
|
|
recipients can be either a string, eg 'a@b.com' or a list, eg:
|
|
['a@b.com', 'c@d.com']. Type conversion is done if needed.
|
|
|
|
sender can be an e-mail, 'Name <email>' or None. If unspecified, the
|
|
DEFAULT_FROM_EMAIL will be used.
|
|
|
|
Originally posted on my blog at http://www.rossp.org/
|
|
"""
|
|
from django.core.mail import EmailMultiAlternatives
|
|
from django.template import loader, Context
|
|
from django.conf import settings
|
|
|
|
if not sender:
|
|
sender = settings.DEFAULT_FROM_EMAIL
|
|
|
|
context = Context(email_context)
|
|
|
|
text_part = loader.get_template('%s.txt' % template_name).render(context)
|
|
html_part = loader.get_template('%s.html' % template_name).render(context)
|
|
subject_part = loader.get_template_from_string(subject).render(context)
|
|
|
|
if type(recipients) != list:
|
|
recipients = [recipients,]
|
|
|
|
msg = EmailMultiAlternatives(subject_part, text_part, sender, recipients, bcc=bcc)
|
|
msg.attach_alternative(html_part, "text/html")
|
|
|
|
if files:
|
|
if type(files) != list:
|
|
files = [files,]
|
|
|
|
for file in files:
|
|
msg.attach_file(file)
|
|
|
|
return msg.send(fail_silently)
|
|
|
|
|
|
def normalise_data(data, to=100):
|
|
"""
|
|
Used for normalising data prior to graphing with Google charting API
|
|
"""
|
|
max_value = max(data)
|
|
if max_value > to:
|
|
new_data = []
|
|
for d in data:
|
|
new_data.append(int(d/float(max_value)*to))
|
|
data = new_data
|
|
return data
|
|
|
|
chart_colours = ('80C65A', '990066', 'FF9900', '3399CC', 'BBCCED', '3399CC', 'FFCC33')
|
|
|
|
def line_chart(data):
|
|
"""
|
|
'data' is a list of lists making a table.
|
|
Row 1, columns 2-n are data headings (the time periods)
|
|
Rows 2-n are data, with column 1 being the line labels
|
|
"""
|
|
|
|
column_headings = data[0][1:]
|
|
max = 0
|
|
for row in data[1:]:
|
|
for field in row[1:]:
|
|
if field > max:
|
|
max = field
|
|
|
|
|
|
# Set width to '65px * number of months'.
|
|
chart_url = 'http://chart.apis.google.com/chart?cht=lc&chs=%sx90&chd=t:' % (len(column_headings)*65)
|
|
first_row = True
|
|
row_headings = []
|
|
for row in data[1:]:
|
|
# Add data to URL, normalised to the maximum for all lines on this chart
|
|
norm = normalise_data(row[1:], max)
|
|
if not first_row:
|
|
chart_url += '|'
|
|
chart_url += ','.join([str(num) for num in norm])
|
|
row_headings.append(row[0])
|
|
first_row = False
|
|
|
|
chart_url += '&chds='
|
|
rows = len(data)-1
|
|
first = True
|
|
for row in range(rows):
|
|
# Set maximum data ranges to '0:x' where 'x' is the maximum number in use.
|
|
if not first:
|
|
chart_url += ','
|
|
chart_url += '0,%s' % max
|
|
first = False
|
|
chart_url += '&chdl=%s' % '|'.join(row_headings) # Display legend/labels
|
|
chart_url += '&chco=%s' % ','.join(chart_colours) # Default colour set
|
|
chart_url += '&chxt=x,y' # Turn on axis labels
|
|
chart_url += '&chxl=0:|%s|1:|0|%s' % ('|'.join(column_headings), max) # Axis Label Text
|
|
|
|
return chart_url
|
|
|
|
def bar_chart(data):
|
|
"""
|
|
'data' is a list of lists making a table.
|
|
Row 1, columns 2-n are data headings
|
|
Rows 2-n are data, with column 1 being the line labels
|
|
"""
|
|
|
|
column_headings = data[0][1:]
|
|
max = 0
|
|
for row in data[1:]:
|
|
for field in row[1:]:
|
|
if field > max:
|
|
max = field
|
|
|
|
|
|
# Set width to '150px * number of months'.
|
|
chart_url = 'http://chart.apis.google.com/chart?cht=bvg&chs=%sx90&chd=t:' % (len(column_headings) * 150)
|
|
first_row = True
|
|
row_headings = []
|
|
for row in data[1:]:
|
|
# Add data to URL, normalised to the maximum for all lines on this chart
|
|
norm = normalise_data(row[1:], max)
|
|
if not first_row:
|
|
chart_url += '|'
|
|
chart_url += ','.join([str(num) for num in norm])
|
|
row_headings.append(row[0])
|
|
first_row = False
|
|
|
|
chart_url += '&chds=0,%s' % max
|
|
chart_url += '&chdl=%s' % '|'.join(row_headings) # Display legend/labels
|
|
chart_url += '&chco=%s' % ','.join(chart_colours) # Default colour set
|
|
chart_url += '&chxt=x,y' # Turn on axis labels
|
|
chart_url += '&chxl=0:|%s|1:|0|%s' % ('|'.join(column_headings), max) # Axis Label Text
|
|
|
|
return chart_url
|
|
|
|
def query_to_dict(results, descriptions):
|
|
""" Replacement method for cursor.dictfetchall() as that method no longer
|
|
exists in psycopg2, and I'm guessing in other backends too.
|
|
|
|
Converts the results of a raw SQL query into a list of dictionaries, suitable
|
|
for use in templates etc. """
|
|
output = []
|
|
for data in results:
|
|
row = {}
|
|
i = 0
|
|
for column in descriptions:
|
|
row[column[0]] = data[i]
|
|
i += 1
|
|
|
|
output.append(row)
|
|
return output
|