diff --git a/src/pretix/control/forms/organizer.py b/src/pretix/control/forms/organizer.py index 3982fd3327..dfa4527a41 100644 --- a/src/pretix/control/forms/organizer.py +++ b/src/pretix/control/forms/organizer.py @@ -9,6 +9,7 @@ from pretix.base.forms import I18nModelForm, SettingsForm from pretix.base.models import Organizer, Team from pretix.control.forms import ExtFileField from pretix.multidomain.models import KnownDomain +from pretix.presale.style import get_fonts class OrganizerForm(I18nModelForm): @@ -114,14 +115,16 @@ class TeamForm(forms.ModelForm): class OrganizerSettingsForm(SettingsForm): - 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.') + 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_primary_color = forms.CharField( + +class OrganizerDisplaySettingsForm(SettingsForm): + primary_color = forms.CharField( label=_("Primary color"), required=False, validators=[ @@ -130,21 +133,12 @@ class OrganizerSettingsForm(SettingsForm): ], widget=forms.TextInput(attrs={'class': 'colorpickerfield'}) ) - organizer_homepage_text = I18nFormField( label=_('Homepage text'), required=False, widget=I18nTextarea, 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( label=_('Logo image'), 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 ' 'in the page header. We will show your logo with a maximal height of 120 pixels.') ) - event_list_type = forms.ChoiceField( label=_('Default overview style'), choices=( @@ -160,3 +153,22 @@ class OrganizerSettingsForm(SettingsForm): ('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() + ] diff --git a/src/pretix/control/templates/pretixcontrol/organizers/base.html b/src/pretix/control/templates/pretixcontrol/organizers/base.html index 1bd8d6bc1b..3f04e7a5a7 100644 --- a/src/pretix/control/templates/pretixcontrol/organizers/base.html +++ b/src/pretix/control/templates/pretixcontrol/organizers/base.html @@ -26,6 +26,13 @@ {% endif %} + {% if 'can_change_organizer_settings' in request.orgapermset %} +
  • + + {% trans "Display" %} + +
  • + {% endif %} {% for nav in nav_organizer %}
  • diff --git a/src/pretix/control/templates/pretixcontrol/organizers/display.html b/src/pretix/control/templates/pretixcontrol/organizers/display.html new file mode 100644 index 0000000000..9e5e534f83 --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/organizers/display.html @@ -0,0 +1,32 @@ +{% extends "pretixcontrol/organizers/base.html" %} +{% load i18n %} +{% load bootstrap3 %} +{% block inner %} +
    + {% csrf_token %} +
    + {% trans "Organizer page" %} + {% 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" %} +
    +
    + {% trans "Shop design" %} +

    + {% 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 %} +

    + {% bootstrap_field form.primary_color layout="horizontal" %} + {% bootstrap_field form.primary_font layout="horizontal" %} +
    +
    + +
    +
    +{% endblock %} diff --git a/src/pretix/control/templates/pretixcontrol/organizers/edit.html b/src/pretix/control/templates/pretixcontrol/organizers/edit.html index 5b575b0d67..fbaaa03a16 100644 --- a/src/pretix/control/templates/pretixcontrol/organizers/edit.html +++ b/src/pretix/control/templates/pretixcontrol/organizers/edit.html @@ -16,15 +16,6 @@ {% bootstrap_field form.domain layout="horizontal" %} {% endif %} -
    - {% trans "Display settings" %} - {% 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" %} -
    {% trans "Other" %} {% bootstrap_form_errors sform %} diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index 7290448aaf..7e1e3cf607 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -35,6 +35,8 @@ urlpatterns = [ url(r'^organizers/add$', organizer.OrganizerCreate.as_view(), name='organizers.add'), url(r'^organizer/(?P[^/]+)/$', organizer.OrganizerDetail.as_view(), name='organizer'), url(r'^organizer/(?P[^/]+)/edit$', organizer.OrganizerUpdate.as_view(), name='organizer.edit'), + url(r'^organizer/(?P[^/]+)/settings/display$', organizer.OrganizerDisplaySettings.as_view(), + name='organizer.display'), url(r'^organizer/(?P[^/]+)/teams$', organizer.TeamListView.as_view(), name='organizer.teams'), url(r'^organizer/(?P[^/]+)/team/add$', organizer.TeamCreateView.as_view(), name='organizer.team.add'), url(r'^organizer/(?P[^/]+)/team/(?P[^/]+)/$', organizer.TeamMemberView.as_view(), diff --git a/src/pretix/control/views/organizer.py b/src/pretix/control/views/organizer.py index 92e8024868..aba6206d58 100644 --- a/src/pretix/control/views/organizer.py +++ b/src/pretix/control/views/organizer.py @@ -10,7 +10,7 @@ from django.shortcuts import get_object_or_404, redirect from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ 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 @@ -18,8 +18,8 @@ from pretix.base.models.event import EventMetaProperty from pretix.base.models.organizer import TeamAPIToken from pretix.base.services.mail import SendMailException, mail from pretix.control.forms.organizer import ( - EventMetaPropertyForm, OrganizerForm, OrganizerSettingsForm, - OrganizerUpdateForm, TeamForm, + EventMetaPropertyForm, OrganizerDisplaySettingsForm, OrganizerForm, + OrganizerSettingsForm, OrganizerUpdateForm, TeamForm, ) from pretix.control.permissions import OrganizerPermissionRequiredMixin from pretix.control.signals import nav_organizer @@ -86,6 +86,71 @@ class OrganizerTeamView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix 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): model = Organizer form_class = OrganizerUpdateForm @@ -136,7 +201,6 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView): user=self.request.user, 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.')) return super().form_valid(form) diff --git a/src/pretix/presale/style.py b/src/pretix/presale/style.py index fee23c2c30..893f1245ad 100644 --- a/src/pretix/presale/style.py +++ b/src/pretix/presale/style.py @@ -91,8 +91,8 @@ def regenerate_organizer_css(organizer_id: int): organizer.settings.set('presale_css_checksum', checksum) non_inherited_events = set(Event_SettingsStore.objects.filter( - event__organizer=organizer, key__in=affected_keys - ).values_list('event_id', flat=True)) + object__organizer=organizer, key__in=affected_keys + ).values_list('object_id', flat=True)) for event in organizer.events.all(): if event.pk not in non_inherited_events: regenerate_css.apply_async(args=(event.pk,))