forked from CGM_Public/pretix_original
Propagate setting and add organizer display settings page
This commit is contained in:
@@ -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 %}
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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,))
|
||||||
|
|||||||
Reference in New Issue
Block a user