mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
* add ajax and dummy api response * add preview <p> blocks * finalise order_placed setup - use <pre> for mail preview - create dummy data in backend * fix i18n text conversion * create fragment template for mail preview * support i18n in mail preview view * apply mail fragment in all mail settings fix mistake in input[lang=en] flag style add dummy data for all placeholders apply fragment template to all fields add exclude option to fragment template * remove migration file * add translation mapping & fix field label remove hardcoded field label add transblock for translation file * add test for mail setting preview * fix code style in preview class * bug fix in mail preview view - fixed localised date values - added locale index mapping - added tests on multi-language event - enhanced dummy data
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/main.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/quota.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/question.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/mail.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/asynctask.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/asyncdownload.js" %}"></script>
|
||||
{% endcompress %}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inside %}
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data"
|
||||
mail-preview-url="{% url "control:event.settings.mail.preview" event=request.event.slug organizer=request.event.organizer.slug %}">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
<fieldset>
|
||||
@@ -13,106 +14,26 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "E-mail content" %}</legend>
|
||||
<div class="panel-group" id="questions_group">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" href="#order_placed">
|
||||
<strong>{% trans "Placed order" %}</strong>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="order_placed" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% bootstrap_field form.mail_text_order_placed layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" href="#order_paid">
|
||||
<strong>{% trans "Paid order" %}</strong>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="order_paid" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% bootstrap_field form.mail_text_order_paid layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" href="#order_free">
|
||||
<strong>{% trans "Free order" %}</strong>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="order_free" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% bootstrap_field form.mail_text_order_free layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" href="#resend_link">
|
||||
<strong>{% trans "Resend link" %}</strong>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="resend_link" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% bootstrap_field form.mail_text_resend_link layout="horizontal" %}
|
||||
{% bootstrap_field form.mail_text_resend_all_links layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" href="#order_changed">
|
||||
<strong>{% trans "Order changed" %}</strong>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="order_changed" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% bootstrap_field form.mail_text_order_changed layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" href="#order_expirew">
|
||||
<strong>{% trans "Payment reminder" %}</strong>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="order_expirew" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% bootstrap_field form.mail_days_order_expire_warning layout="horizontal" %}
|
||||
{% bootstrap_field form.mail_text_order_expire_warning layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" href="#waiting_list">
|
||||
<strong>{% trans "Waiting list notification" %}</strong>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="waiting_list" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% bootstrap_field form.mail_text_waiting_list layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% blocktrans asvar title_placed_order %}Placed order{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_placed" title=title_placed_order items="mail_text_order_placed" %}
|
||||
|
||||
{% blocktrans asvar title_paid_order %}Paid order{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_paid" title=title_paid_order items="mail_text_order_paid" %}
|
||||
|
||||
{% blocktrans asvar title_free_order %}Free order{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_free" title=title_free_order items="mail_text_order_free" %}
|
||||
|
||||
{% blocktrans asvar title_resend_link %}Resend link{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="resend_link" title=title_resend_link items="mail_text_resend_link,mail_text_resend_all_links" %}
|
||||
|
||||
{% blocktrans asvar title_order_changed %}Order changed{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_changed" title=title_order_changed items="mail_text_order_changed" %}
|
||||
|
||||
{% blocktrans asvar title_payment_reminder %}Payment reminder{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="order_expirew" title=title_payment_reminder items="mail_days_order_expire_warning,mail_text_order_expire_warning" exclude="mail_days_order_expire_warning" %}
|
||||
|
||||
{% blocktrans asvar title_waiting_list_notification %}Waiting list notification{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="waiting_list" title=title_waiting_list_notification items="mail_text_waiting_list" %}
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load mail_settings_preview %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" href="#{{ pid }}">
|
||||
<strong>{% trans title %}</strong>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="{{ pid }}" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
{% with exclude|split as exclusion %}
|
||||
{% with items|split as item_list %}
|
||||
{% for item in item_list %}
|
||||
{% if item in exclusion %}
|
||||
{% with form|getattr:item as field %}
|
||||
{% bootstrap_field field layout="horizontal" %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<div id="{{ item }}_panel" class="preview-panel form-group" for="{{ item }}">
|
||||
{% with form|getattr:item as field %}
|
||||
<label class="col-md-3 control-label">{{ field.label }}</label>
|
||||
<div class="col-md-9">
|
||||
<div class="tab-content">
|
||||
<div id="{{ item }}_edit" class="tab-pane fade in active">
|
||||
{% bootstrap_field field show_label=False form_group_class="" %}
|
||||
</div>
|
||||
<div id="{{ item }}_preview" class="tab-pane">
|
||||
{% for l in request.event.settings.locales %}
|
||||
<pre lang="{{ l }}" for="{{ item }}"></pre>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<ul class="nav nav-pills pull-right">
|
||||
<li role="presentation" class="active">
|
||||
<a data-toggle="pill" type="edit" href="#{{ item }}_edit"><i class="fa fa-pencil-square-o fa-fw"></i> {% trans "Edit" %}</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a data-toggle="pill" type="preview" href="#{{ item }}_preview"><i class="fa fa-tv fa-fw"></i> {% trans "Preview" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
13
src/pretix/control/templatetags/mail_settings_preview.py
Normal file
13
src/pretix/control/templatetags/mail_settings_preview.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter(name='split', delimiter=",")
|
||||
def split(value, delimiter=","):
|
||||
return value.split(delimiter)
|
||||
|
||||
|
||||
@register.filter(name="getattr")
|
||||
def get_attribute(value, key):
|
||||
return value[key]
|
||||
@@ -52,6 +52,7 @@ urlpatterns = [
|
||||
url(r'^settings/tickets/preview/(?P<output>[^/]+)$', event.TicketSettingsPreview.as_view(),
|
||||
name='event.settings.tickets.preview'),
|
||||
url(r'^settings/email$', event.MailSettings.as_view(), name='event.settings.mail'),
|
||||
url(r'^settings/email/preview$', event.MailSettingsPreview.as_view(), name='event.settings.mail.preview'),
|
||||
url(r'^settings/invoice$', event.InvoiceSettings.as_view(), name='event.settings.invoice'),
|
||||
url(r'^settings/invoice/preview$', event.InvoicePreview.as_view(), name='event.settings.invoice.preview'),
|
||||
url(r'^settings/display', event.DisplaySettings.as_view(), name='event.settings.display'),
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
from datetime import timedelta
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files import File
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import transaction
|
||||
from django.forms import modelformset_factory
|
||||
from django.http import HttpResponse
|
||||
from django.http import HttpResponse, HttpResponseBadRequest, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.utils import translation
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import FormView, ListView
|
||||
from django.views.generic.base import TemplateView, View
|
||||
@@ -400,6 +406,112 @@ class MailSettings(EventSettingsFormView):
|
||||
return self.get(request)
|
||||
|
||||
|
||||
class MailSettingsPreview(EventPermissionRequiredMixin, View):
|
||||
permission = 'can_change_settings'
|
||||
|
||||
# return the origin text if key is missing in dict
|
||||
class SafeDict(dict):
|
||||
def __missing__(self, key):
|
||||
return '{' + key + '}'
|
||||
|
||||
@staticmethod
|
||||
def generate_order_fullname(slug, code):
|
||||
return '{event}-{code}'.format(event=slug.upper(), code=code)
|
||||
|
||||
# create data which depend on locale
|
||||
def localized_data(self):
|
||||
return {
|
||||
'date': date_format(now() + timedelta(days=7), 'SHORT_DATE_FORMAT'),
|
||||
'expire_date': date_format(now() + timedelta(days=15), 'SHORT_DATE_FORMAT'),
|
||||
'payment_info': _('{} {} has been transferred to account<9999-9999-9999-9999> at {}').format(
|
||||
42.23, self.request.event.currency, date_format(now(), 'SHORT_DATETIME_FORMAT'))
|
||||
}
|
||||
|
||||
# create index-language mapping
|
||||
@cached_property
|
||||
def supported_locale(self):
|
||||
locales = {}
|
||||
for idx, val in enumerate(settings.LANGUAGES):
|
||||
if val[0] in self.request.event.settings.locales:
|
||||
locales[str(idx)] = val[0]
|
||||
return locales
|
||||
|
||||
@cached_property
|
||||
def items(self):
|
||||
return {
|
||||
'mail_text_order_placed': ['total', 'currency', 'date', 'invoice_company',
|
||||
'event', 'paymentinfo', 'url', 'invoice_name'],
|
||||
'mail_text_order_paid': ['event', 'url', 'invoice_name', 'invoice_company', 'payment_info'],
|
||||
'mail_text_order_free': ['event', 'url', 'invoice_name', 'invoice_company'],
|
||||
'mail_text_resend_link': ['event', 'url', 'invoice_name', 'invoice_company'],
|
||||
'mail_text_resend_all_links': ['event', 'orders'],
|
||||
'mail_text_order_changed': ['event', 'url', 'invoice_name', 'invoice_company'],
|
||||
'mail_text_order_expire_warning': ['event', 'url', 'expire_date', 'invoice_name', 'invoice_company'],
|
||||
'mail_text_waiting_list': ['event', 'url', 'product', 'hours', 'code']
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def base_data(self):
|
||||
user_orders = [
|
||||
{'code': 'F8VVL', 'secret': '6zzjnumtsx136ddy'},
|
||||
{'code': 'HIDHK', 'secret': '98kusd8ofsj8dnkd'},
|
||||
{'code': 'OPKSB', 'secret': '09pjdksflosk3njd'}
|
||||
]
|
||||
orders = [' - {} - {}'.format(self.generate_order_fullname(self.request.event.slug, order['code']),
|
||||
self.generate_order_url(order['code'], order['secret']))
|
||||
for order in user_orders]
|
||||
return {
|
||||
'event': self.request.event.name,
|
||||
'total': 42.23,
|
||||
'currency': self.request.event.currency,
|
||||
'url': self.generate_order_url(user_orders[0]['code'], user_orders[0]['secret']),
|
||||
'orders': '\n'.join(orders),
|
||||
'hours': self.request.event.settings.waiting_list_hours,
|
||||
'product': _('Sample Admission Ticket'),
|
||||
'code': '68CYU2H6ZTP3WLK5',
|
||||
'invoice_name': _('John Doe'),
|
||||
'invoice_company': _('Sample Corporation'),
|
||||
'paymentinfo': _('Please transfer money to this bank account: 9999-9999-9999-9999')
|
||||
}
|
||||
|
||||
def generate_order_url(self, code, secret):
|
||||
return build_absolute_uri('presale:event.order', kwargs={
|
||||
'event': self.request.event.slug,
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'order': code,
|
||||
'secret': secret
|
||||
})
|
||||
|
||||
# get all supported placeholders with dummy values
|
||||
def placeholders(self, item):
|
||||
supported = {}
|
||||
local_data = self.localized_data()
|
||||
for key in self.items.get(item):
|
||||
supported[key] = self.base_data.get(key) if key in self.base_data else local_data.get(key)
|
||||
return self.SafeDict(supported)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
preview_item = request.POST.get('item', '')
|
||||
if preview_item not in self.items:
|
||||
return HttpResponseBadRequest(_('invalid item'))
|
||||
|
||||
regex = r"^" + re.escape(preview_item) + r"_(?P<idx>[\d+])$"
|
||||
msgs = {}
|
||||
for k, v in request.POST.items():
|
||||
# only accept allowed fields
|
||||
matched = re.search(regex, k)
|
||||
if matched is not None:
|
||||
idx = matched.group('idx')
|
||||
if idx in self.supported_locale:
|
||||
with translation.override(self.supported_locale[idx]):
|
||||
msgs[self.supported_locale[idx]] = v.format_map(self.placeholders(preview_item))
|
||||
|
||||
return JsonResponse({
|
||||
'item': preview_item,
|
||||
'msgs': msgs
|
||||
})
|
||||
|
||||
|
||||
class TicketSettingsPreview(EventPermissionRequiredMixin, View):
|
||||
permission = 'can_change_settings'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user