Propagate setting and add organizer display settings page

This commit is contained in:
Raphael Michel
2017-10-07 18:13:06 +02:00
parent 28d074366e
commit bbd112280a
7 changed files with 139 additions and 31 deletions
+28 -16
View File
@@ -9,6 +9,7 @@ from pretix.base.forms import I18nModelForm, SettingsForm
from pretix.base.models import Organizer, Team from pretix.base.models import Organizer, Team
from pretix.control.forms import ExtFileField from pretix.control.forms import ExtFileField
from pretix.multidomain.models import KnownDomain from pretix.multidomain.models import KnownDomain
from pretix.presale.style import get_fonts
class OrganizerForm(I18nModelForm): class OrganizerForm(I18nModelForm):
@@ -114,14 +115,16 @@ class TeamForm(forms.ModelForm):
class OrganizerSettingsForm(SettingsForm): class OrganizerSettingsForm(SettingsForm):
locales = forms.MultipleChoiceField( organizer_info_text = I18nFormField(
choices=settings.LANGUAGES, label=_('Info text'),
label=_("Use languages"), required=False,
widget=forms.CheckboxSelectMultiple, widget=I18nTextarea,
help_text=_('Choose all languages that your organizer homepage should be available in.') help_text=_('Not displayed anywhere by default, but if you want to, you can use this e.g. in ticket templates.')
) )
organizer_primary_color = forms.CharField(
class OrganizerDisplaySettingsForm(SettingsForm):
primary_color = forms.CharField(
label=_("Primary color"), label=_("Primary color"),
required=False, required=False,
validators=[ validators=[
@@ -130,21 +133,12 @@ class OrganizerSettingsForm(SettingsForm):
], ],
widget=forms.TextInput(attrs={'class': 'colorpickerfield'}) widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
) )
organizer_homepage_text = I18nFormField( organizer_homepage_text = I18nFormField(
label=_('Homepage text'), label=_('Homepage text'),
required=False, required=False,
widget=I18nTextarea, widget=I18nTextarea,
help_text=_('This will be displayed on the organizer homepage.') help_text=_('This will be displayed on the organizer homepage.')
) )
organizer_info_text = I18nFormField(
label=_('Info text'),
required=False,
widget=I18nTextarea,
help_text=_('Not displayed anywhere by default, but if you want to, you can use this e.g. in ticket templates.')
)
organizer_logo_image = ExtFileField( organizer_logo_image = ExtFileField(
label=_('Logo image'), label=_('Logo image'),
ext_whitelist=(".png", ".jpg", ".gif", ".jpeg"), ext_whitelist=(".png", ".jpg", ".gif", ".jpeg"),
@@ -152,7 +146,6 @@ class OrganizerSettingsForm(SettingsForm):
help_text=_('If you provide a logo image, we will by default not show your organization name ' help_text=_('If you provide a logo image, we will by default not show your organization name '
'in the page header. We will show your logo with a maximal height of 120 pixels.') 'in the page header. We will show your logo with a maximal height of 120 pixels.')
) )
event_list_type = forms.ChoiceField( event_list_type = forms.ChoiceField(
label=_('Default overview style'), label=_('Default overview style'),
choices=( choices=(
@@ -160,3 +153,22 @@ class OrganizerSettingsForm(SettingsForm):
('calendar', _('Calendar')) ('calendar', _('Calendar'))
) )
) )
locales = forms.MultipleChoiceField(
choices=settings.LANGUAGES,
label=_("Use languages"),
widget=forms.CheckboxSelectMultiple,
help_text=_('Choose all languages that your organizer homepage should be available in.')
)
primary_font = forms.ChoiceField(
label=_('Font'),
choices=[
('Open Sans', 'Open Sans')
],
help_text=_('Only respected by modern browsers.')
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['primary_font'].choices += [
(a, a) for a in get_fonts()
]
@@ -26,6 +26,13 @@
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if 'can_change_organizer_settings' in request.orgapermset %}
<li {% if "organizer.display" in url_name %}class="active"{% endif %}>
<a href="{% url "control:organizer.display" organizer=organizer.slug %}">
{% trans "Display" %}
</a>
</li>
{% endif %}
{% for nav in nav_organizer %} {% for nav in nav_organizer %}
<li {% if nav.active %}class="active"{% endif %}> <li {% if nav.active %}class="active"{% endif %}>
<a href="{{ nav.url }}"> <a href="{{ nav.url }}">
@@ -0,0 +1,32 @@
{% extends "pretixcontrol/organizers/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block inner %}
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
<legend>{% trans "Organizer page" %}</legend>
{% bootstrap_form_errors form %}
{% bootstrap_field form.locales layout="horizontal" %}
{% bootstrap_field form.organizer_logo_image layout="horizontal" %}
{% bootstrap_field form.organizer_homepage_text layout="horizontal" %}
{% bootstrap_field form.event_list_type layout="horizontal" %}
</fieldset>
<fieldset>
<legend>{% trans "Shop design" %}</legend>
<p class="help-block">
{% blocktrans trimmed %}
These settings will be used for the organizer page as well as for the default settings
for all events in this account that do not have their own design settings.
{% endblocktrans %}
</p>
{% bootstrap_field form.primary_color layout="horizontal" %}
{% bootstrap_field form.primary_font layout="horizontal" %}
</fieldset>
<div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>
</div>
</form>
{% endblock %}
@@ -16,15 +16,6 @@
{% bootstrap_field form.domain layout="horizontal" %} {% bootstrap_field form.domain layout="horizontal" %}
{% endif %} {% endif %}
</fieldset> </fieldset>
<fieldset>
<legend>{% trans "Display settings" %}</legend>
{% bootstrap_form_errors sform %}
{% bootstrap_field sform.locales layout="horizontal" %}
{% bootstrap_field sform.organizer_primary_color layout="horizontal" %}
{% bootstrap_field sform.organizer_logo_image layout="horizontal" %}
{% bootstrap_field sform.organizer_homepage_text layout="horizontal" %}
{% bootstrap_field sform.event_list_type layout="horizontal" %}
</fieldset>
<fieldset> <fieldset>
<legend>{% trans "Other" %}</legend> <legend>{% trans "Other" %}</legend>
{% bootstrap_form_errors sform %} {% bootstrap_form_errors sform %}
+2
View File
@@ -35,6 +35,8 @@ urlpatterns = [
url(r'^organizers/add$', organizer.OrganizerCreate.as_view(), name='organizers.add'), url(r'^organizers/add$', organizer.OrganizerCreate.as_view(), name='organizers.add'),
url(r'^organizer/(?P<organizer>[^/]+)/$', organizer.OrganizerDetail.as_view(), name='organizer'), url(r'^organizer/(?P<organizer>[^/]+)/$', organizer.OrganizerDetail.as_view(), name='organizer'),
url(r'^organizer/(?P<organizer>[^/]+)/edit$', organizer.OrganizerUpdate.as_view(), name='organizer.edit'), url(r'^organizer/(?P<organizer>[^/]+)/edit$', organizer.OrganizerUpdate.as_view(), name='organizer.edit'),
url(r'^organizer/(?P<organizer>[^/]+)/settings/display$', organizer.OrganizerDisplaySettings.as_view(),
name='organizer.display'),
url(r'^organizer/(?P<organizer>[^/]+)/teams$', organizer.TeamListView.as_view(), name='organizer.teams'), url(r'^organizer/(?P<organizer>[^/]+)/teams$', organizer.TeamListView.as_view(), name='organizer.teams'),
url(r'^organizer/(?P<organizer>[^/]+)/team/add$', organizer.TeamCreateView.as_view(), name='organizer.team.add'), url(r'^organizer/(?P<organizer>[^/]+)/team/add$', organizer.TeamCreateView.as_view(), name='organizer.team.add'),
url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/$', organizer.TeamMemberView.as_view(), url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/$', organizer.TeamMemberView.as_view(),
+68 -4
View File
@@ -10,7 +10,7 @@ from django.shortcuts import get_object_or_404, redirect
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic import ( from django.views.generic import (
CreateView, DeleteView, DetailView, ListView, UpdateView, CreateView, DeleteView, DetailView, FormView, ListView, UpdateView,
) )
from pretix.base.models import Organizer, Team, TeamInvite, User from pretix.base.models import Organizer, Team, TeamInvite, User
@@ -18,8 +18,8 @@ from pretix.base.models.event import EventMetaProperty
from pretix.base.models.organizer import TeamAPIToken from pretix.base.models.organizer import TeamAPIToken
from pretix.base.services.mail import SendMailException, mail from pretix.base.services.mail import SendMailException, mail
from pretix.control.forms.organizer import ( from pretix.control.forms.organizer import (
EventMetaPropertyForm, OrganizerForm, OrganizerSettingsForm, EventMetaPropertyForm, OrganizerDisplaySettingsForm, OrganizerForm,
OrganizerUpdateForm, TeamForm, OrganizerSettingsForm, OrganizerUpdateForm, TeamForm,
) )
from pretix.control.permissions import OrganizerPermissionRequiredMixin from pretix.control.permissions import OrganizerPermissionRequiredMixin
from pretix.control.signals import nav_organizer from pretix.control.signals import nav_organizer
@@ -86,6 +86,71 @@ class OrganizerTeamView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix
context_object_name = 'organizer' context_object_name = 'organizer'
class OrganizerSettingsFormView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, FormView):
model = Organizer
permission = 'can_change_organizer_settings'
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['obj'] = self.request.organizer
return kwargs
@transaction.atomic
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
form.save()
if form.has_changed():
self.request.organizer.log_action(
'pretix.organizer.settings', user=self.request.user, data={
k: (form.cleaned_data.get(k).name
if isinstance(form.cleaned_data.get(k), File)
else form.cleaned_data.get(k))
for k in form.changed_data
}
)
messages.success(self.request, _('Your changes have been saved.'))
return redirect(self.get_success_url())
else:
messages.error(self.request, _('We could not save your changes. See below for details.'))
return self.get(request)
class OrganizerDisplaySettings(OrganizerSettingsFormView):
model = Organizer
form_class = OrganizerDisplaySettingsForm
template_name = 'pretixcontrol/organizers/display.html'
permission = 'can_change_organizer_settings'
def get_success_url(self) -> str:
return reverse('control:organizer.display', kwargs={
'organizer': self.request.organizer.slug,
})
@transaction.atomic
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
form.save()
if form.has_changed():
self.request.organizer.log_action(
'pretix.organizer.settings', user=self.request.user, data={
k: (form.cleaned_data.get(k).name
if isinstance(form.cleaned_data.get(k), File)
else form.cleaned_data.get(k))
for k in form.changed_data
}
)
regenerate_organizer_css.apply_async(args=(self.request.organizer.pk,))
messages.success(self.request, _('Your changes have been saved. Please note that it can '
'take a short period of time until your changes become '
'active.'))
return redirect(self.get_success_url())
else:
messages.error(self.request, _('We could not save your changes. See below for details.'))
return self.get(request)
class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView): class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
model = Organizer model = Organizer
form_class = OrganizerUpdateForm form_class = OrganizerUpdateForm
@@ -136,7 +201,6 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
user=self.request.user, user=self.request.user,
data={k: form.cleaned_data.get(k) for k in form.changed_data} data={k: form.cleaned_data.get(k) for k in form.changed_data}
) )
regenerate_organizer_css.apply_async(args=(self.request.organizer.pk,))
messages.success(self.request, _('Your changes have been saved.')) messages.success(self.request, _('Your changes have been saved.'))
return super().form_valid(form) return super().form_valid(form)
+2 -2
View File
@@ -91,8 +91,8 @@ def regenerate_organizer_css(organizer_id: int):
organizer.settings.set('presale_css_checksum', checksum) organizer.settings.set('presale_css_checksum', checksum)
non_inherited_events = set(Event_SettingsStore.objects.filter( non_inherited_events = set(Event_SettingsStore.objects.filter(
event__organizer=organizer, key__in=affected_keys object__organizer=organizer, key__in=affected_keys
).values_list('event_id', flat=True)) ).values_list('object_id', flat=True))
for event in organizer.events.all(): for event in organizer.events.all():
if event.pk not in non_inherited_events: if event.pk not in non_inherited_events:
regenerate_css.apply_async(args=(event.pk,)) regenerate_css.apply_async(args=(event.pk,))