forked from CGM_Public/pretix_original
Add customized links to page footer (#2685)
Co-authored-by: Richard Schreiber <wiffbi@gmail.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 3.2.12 on 2022-06-15 08:10
|
||||
|
||||
import django.db.models.deletion
|
||||
import i18nfield.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0216_checkin_forced_sent'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='OrganizerFooterLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('label', i18nfield.fields.I18nCharField(max_length=200)),
|
||||
('url', models.URLField()),
|
||||
('organizer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='footer_links', to='pretixbase.organizer')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EventFooterLink',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('label', i18nfield.fields.I18nCharField(max_length=200)),
|
||||
('url', models.URLField()),
|
||||
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='footer_links', to='pretixbase.event')),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -718,6 +718,11 @@ class Event(EventMixin, LoggedModel):
|
||||
self.save()
|
||||
self.log_action('pretix.object.cloned', data={'source': other.slug, 'source_id': other.pk})
|
||||
|
||||
for fl in EventFooterLink.objects.filter(event=other):
|
||||
fl.pk = None
|
||||
fl.event = self
|
||||
fl.save(force_insert=True)
|
||||
|
||||
tax_map = {}
|
||||
for t in other.tax_rules.all():
|
||||
tax_map[t.pk] = t
|
||||
@@ -1612,3 +1617,25 @@ class SubEventMetaValue(LoggedModel):
|
||||
super().save(*args, **kwargs)
|
||||
if self.subevent:
|
||||
self.subevent.event.cache.clear()
|
||||
|
||||
|
||||
class EventFooterLink(models.Model):
|
||||
"""
|
||||
A footer link assigned to an event.
|
||||
"""
|
||||
event = models.ForeignKey('Event', on_delete=models.CASCADE, related_name='footer_links')
|
||||
label = I18nCharField(
|
||||
max_length=200,
|
||||
verbose_name=_("Link text"),
|
||||
)
|
||||
url = models.URLField(
|
||||
verbose_name=_("Link URL"),
|
||||
)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
super().delete(*args, **kwargs)
|
||||
self.event.cache.clear()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(*args, **kwargs)
|
||||
self.event.cache.clear()
|
||||
|
||||
@@ -46,6 +46,7 @@ from django.utils.crypto import get_random_string
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.timezone import get_current_timezone, make_aware, now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from i18nfield.fields import I18nCharField
|
||||
|
||||
from pretix.base.models.base import LoggedModel
|
||||
from pretix.base.validators import OrganizerSlugBanlistValidator
|
||||
@@ -464,3 +465,25 @@ class TeamAPIToken(models.Model):
|
||||
return self.get_events_with_any_permission()
|
||||
else:
|
||||
return self.team.organizer.events.none()
|
||||
|
||||
|
||||
class OrganizerFooterLink(models.Model):
|
||||
"""
|
||||
A footer link assigned to an organizer.
|
||||
"""
|
||||
organizer = models.ForeignKey('Organizer', on_delete=models.CASCADE, related_name='footer_links')
|
||||
label = I18nCharField(
|
||||
max_length=200,
|
||||
verbose_name=_("Link text"),
|
||||
)
|
||||
url = models.URLField(
|
||||
verbose_name=_("Link URL"),
|
||||
)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
super().delete(*args, **kwargs)
|
||||
self.organizer.cache.clear()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(*args, **kwargs)
|
||||
self.organizer.cache.clear()
|
||||
|
||||
@@ -41,7 +41,9 @@ from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import validate_email
|
||||
from django.db.models import Prefetch, Q, prefetch_related_objects
|
||||
from django.forms import CheckboxSelectMultiple, formset_factory
|
||||
from django.forms import (
|
||||
CheckboxSelectMultiple, formset_factory, inlineformset_factory,
|
||||
)
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.html import escape
|
||||
@@ -58,7 +60,7 @@ from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.email import get_available_placeholders
|
||||
from pretix.base.forms import I18nModelForm, PlaceholderValidator, SettingsForm
|
||||
from pretix.base.models import Event, Organizer, TaxRule, Team
|
||||
from pretix.base.models.event import EventMetaValue, SubEvent
|
||||
from pretix.base.models.event import EventFooterLink, EventMetaValue, SubEvent
|
||||
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
|
||||
from pretix.base.settings import (
|
||||
PERSON_NAME_SCHEMES, PERSON_NAME_TITLE_GROUPS, validate_event_settings,
|
||||
@@ -1484,3 +1486,25 @@ ConfirmTextFormset = formset_factory(
|
||||
formset=BaseConfirmTextFormSet,
|
||||
can_order=True, can_delete=True, extra=0
|
||||
)
|
||||
|
||||
|
||||
class EventFooterLinkForm(I18nModelForm):
|
||||
class Meta:
|
||||
model = EventFooterLink
|
||||
fields = ('label', 'url')
|
||||
|
||||
|
||||
class BaseEventFooterLinkFormSet(I18nFormSetMixin, forms.BaseInlineFormSet):
|
||||
def __init__(self, *args, **kwargs):
|
||||
event = kwargs.pop('event', None)
|
||||
if event:
|
||||
kwargs['locales'] = event.settings.get('locales')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
EventFooterLinkFormset = inlineformset_factory(
|
||||
Event, EventFooterLink,
|
||||
EventFooterLinkForm,
|
||||
formset=BaseEventFooterLinkFormSet,
|
||||
can_order=False, can_delete=True, extra=0
|
||||
)
|
||||
|
||||
@@ -39,12 +39,13 @@ from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models import Q
|
||||
from django.forms import inlineformset_factory
|
||||
from django.forms.utils import ErrorDict
|
||||
from django.utils.crypto import get_random_string
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_scopes.forms import SafeModelMultipleChoiceField
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea
|
||||
from i18nfield.forms import I18nFormField, I18nFormSetMixin, I18nTextarea
|
||||
from phonenumber_field.formfields import PhoneNumberField
|
||||
from pytz import common_timezones
|
||||
|
||||
@@ -60,6 +61,7 @@ from pretix.base.models import (
|
||||
Customer, Device, EventMetaProperty, Gate, GiftCard, Membership,
|
||||
MembershipType, Organizer, Team,
|
||||
)
|
||||
from pretix.base.models.organizer import OrganizerFooterLink
|
||||
from pretix.base.settings import PERSON_NAME_SCHEMES, PERSON_NAME_TITLE_GROUPS
|
||||
from pretix.control.forms import ExtFileField, SplitDateTimeField
|
||||
from pretix.control.forms.event import (
|
||||
@@ -682,3 +684,25 @@ class MembershipUpdateForm(forms.ModelForm):
|
||||
titles=self.instance.customer.organizer.settings.name_scheme_titles,
|
||||
label=_('Attendee name'),
|
||||
)
|
||||
|
||||
|
||||
class OrganizerFooterLinkForm(I18nModelForm):
|
||||
class Meta:
|
||||
model = OrganizerFooterLink
|
||||
fields = ('label', 'url')
|
||||
|
||||
|
||||
class BaseOrganizerFooterLinkFormSet(I18nFormSetMixin, forms.BaseInlineFormSet):
|
||||
def __init__(self, *args, **kwargs):
|
||||
organizer = kwargs.pop('organizer', None)
|
||||
if organizer:
|
||||
kwargs['locales'] = organizer.settings.get('locales')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
OrganizerFooterLinkFormset = inlineformset_factory(
|
||||
Organizer, OrganizerFooterLink,
|
||||
OrganizerFooterLinkForm,
|
||||
formset=BaseOrganizerFooterLinkFormSet,
|
||||
can_order=False, can_delete=True, extra=0
|
||||
)
|
||||
|
||||
@@ -314,6 +314,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.object.cloned': _('This object has been created by cloning.'),
|
||||
'pretix.organizer.changed': _('The organizer has been changed.'),
|
||||
'pretix.organizer.settings': _('The organizer settings have been changed.'),
|
||||
'pretix.organizer.footerlinks.changed': _('The footer links have been changed.'),
|
||||
'pretix.giftcards.acceptance.added': _('Gift card acceptance for another organizer has been added.'),
|
||||
'pretix.giftcards.acceptance.removed': _('Gift card acceptance for another organizer has been removed.'),
|
||||
'pretix.webhook.created': _('The webhook has been created.'),
|
||||
@@ -468,6 +469,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
'pretix.event.testmode.deactivated': _('The test mode has been disabled.'),
|
||||
'pretix.event.added': _('The event has been created.'),
|
||||
'pretix.event.changed': _('The event details have been changed.'),
|
||||
'pretix.event.footerlinks.changed': _('The footer links have been changed.'),
|
||||
'pretix.event.question.option.added': _('An answer option has been added to the question.'),
|
||||
'pretix.event.question.option.deleted': _('An answer option has been removed from the question.'),
|
||||
'pretix.event.question.option.changed': _('An answer option has been changed.'),
|
||||
|
||||
@@ -69,7 +69,8 @@
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" checked="checked" disabled="disabled"> {% trans "Ask and require input" %}</label>
|
||||
<label><input type="checkbox" checked="checked"
|
||||
disabled="disabled"> {% trans "Ask and require input" %}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -81,7 +82,8 @@
|
||||
</label>
|
||||
<div class="col-md-9 static-form-row">
|
||||
<p>
|
||||
<a href="{% url "control:event.settings.invoice" event=request.event.slug organizer=request.organizer.slug %}#tab-0-1-open" target="_blank">
|
||||
<a href="{% url "control:event.settings.invoice" event=request.event.slug organizer=request.organizer.slug %}#tab-0-1-open"
|
||||
target="_blank">
|
||||
{% trans "See invoice settings" %}
|
||||
</a>
|
||||
</p>
|
||||
@@ -101,7 +103,8 @@
|
||||
</label>
|
||||
<div class="col-md-9 static-form-row">
|
||||
<p>
|
||||
<a href="{% url "control:event.items.questions" event=request.event.slug organizer=request.organizer.slug %}" target="_blank">
|
||||
<a href="{% url "control:event.items.questions" event=request.event.slug organizer=request.organizer.slug %}"
|
||||
target="_blank">
|
||||
{% trans "Manage questions" %}
|
||||
</a>
|
||||
</p>
|
||||
@@ -232,10 +235,74 @@
|
||||
{% bootstrap_field sform.display_net_prices layout="control" %}
|
||||
{% bootstrap_field sform.show_variations_expanded layout="control" %}
|
||||
{% bootstrap_field sform.hide_sold_out layout="control" %}
|
||||
{% url "control:organizer.edit" organizer=request.organizer.slug as org_url %}
|
||||
{% propagated request.event org_url "meta_noindex" %}
|
||||
{% bootstrap_field sform.meta_noindex layout="control" %}
|
||||
{% endpropagated %}
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Footer links" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<p class="help-block">
|
||||
{% blocktrans trimmed %}
|
||||
These links will be shown in the footer of your ticket shop. You could
|
||||
for example link your terms of service here. Your contact address, imprint, and privacy
|
||||
policy will be linked automatically (if you configured them), so you do not need to add
|
||||
them here.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<div class="formset" data-formset data-formset-prefix="{{ footer_links_formset.prefix }}">
|
||||
{{ footer_links_formset.management_form }}
|
||||
{% bootstrap_formset_errors footer_links_formset %}
|
||||
<div data-formset-body>
|
||||
{% for form in footer_links_formset %}
|
||||
<div class="row formset-row" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ form.id }}
|
||||
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_form_errors form %}
|
||||
{% bootstrap_field form.label layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_field form.url layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-2 text-right flip">
|
||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script type="form-template" data-formset-empty-form>
|
||||
{% escapescript %}
|
||||
<div class="row formset-row" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ footer_links_formset.empty_form.id }}
|
||||
{% bootstrap_field footer_links_formset.empty_form.DELETE form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_field footer_links_formset.empty_form.label layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_field footer_links_formset.empty_form.url layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-2 text-right flip">
|
||||
|
||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endescapescript %}
|
||||
</script>
|
||||
<p>
|
||||
<button type="button" class="btn btn-default" data-formset-add>
|
||||
<i class="fa fa-plus"></i> {% trans "Add link" %}</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if sform.frontpage_subevent_ordering %}
|
||||
{% bootstrap_field sform.frontpage_subevent_ordering layout="control" %}
|
||||
{% endif %}
|
||||
@@ -245,6 +312,11 @@
|
||||
{% if sform.event_list_available_only %}
|
||||
{% bootstrap_field sform.event_list_available_only layout="control" %}
|
||||
{% endif %}
|
||||
|
||||
{% url "control:organizer.edit" organizer=request.organizer.slug as org_url %}
|
||||
{% propagated request.event org_url "meta_noindex" %}
|
||||
{% bootstrap_field sform.meta_noindex layout="control" %}
|
||||
{% endpropagated %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Cart" %}</legend>
|
||||
@@ -262,13 +334,15 @@
|
||||
</div>
|
||||
<div class="alert alert-info">
|
||||
{% blocktrans trimmed %}
|
||||
The waiting list determines availability mainly based on quotas. If you use a seating plan and your
|
||||
The waiting list determines availability mainly based on quotas. If you use a seating plan and
|
||||
your
|
||||
number of available seats is less than the available quota, you might run into situations where
|
||||
people are sent an email from the waiting list but still are unable to book a seat.
|
||||
{% endblocktrans %}
|
||||
<strong>
|
||||
{% blocktrans trimmed %}
|
||||
Specifically, this means the waiting list is not safe to use together with the minimum distance
|
||||
Specifically, this means the waiting list is not safe to use together with the minimum
|
||||
distance
|
||||
feature of our seating plan module.
|
||||
{% endblocktrans %}
|
||||
</strong>
|
||||
|
||||
@@ -50,6 +50,77 @@
|
||||
{% bootstrap_field sform.event_list_availability layout="control" %}
|
||||
{% bootstrap_field sform.organizer_link_back layout="control" %}
|
||||
{% bootstrap_field sform.meta_noindex layout="control" %}
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label">
|
||||
{% trans "Footer links" %}<br>
|
||||
<span class="optional">{% trans "Optional" %}</span>
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<p class="help-block">
|
||||
{% blocktrans trimmed %}
|
||||
These links will be shown in the footer of your ticket shop. You could
|
||||
for example link your terms of service here. Your contact address, imprint, and privacy
|
||||
policy will be linked automatically (if you configured them), so you do not need to add
|
||||
them here.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<p class="help-block">
|
||||
{% blocktrans trimmed %}
|
||||
The links you configure here will also be shown on all of your events.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
<div class="formset" data-formset data-formset-prefix="{{ footer_links_formset.prefix }}">
|
||||
{{ footer_links_formset.management_form }}
|
||||
{% bootstrap_formset_errors footer_links_formset %}
|
||||
<div data-formset-body>
|
||||
{% for form in footer_links_formset %}
|
||||
<div class="row formset-row" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ form.id }}
|
||||
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_form_errors form %}
|
||||
{% bootstrap_field form.label layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_field form.url layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-2 text-right flip">
|
||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script type="form-template" data-formset-empty-form>
|
||||
{% escapescript %}
|
||||
<div class="row formset-row" data-formset-form>
|
||||
<div class="sr-only">
|
||||
{{ footer_links_formset.empty_form.id }}
|
||||
{% bootstrap_field footer_links_formset.empty_form.DELETE form_group_class="" layout="inline" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_field footer_links_formset.empty_form.label layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
{% bootstrap_field footer_links_formset.empty_form.url layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
<div class="col-md-2 text-right flip">
|
||||
|
||||
<button type="button" class="btn btn-danger" data-formset-delete-button>
|
||||
<i class="fa fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endescapescript %}
|
||||
</script>
|
||||
<p>
|
||||
<button type="button" class="btn btn-default" data-formset-add>
|
||||
<i class="fa fa-plus"></i> {% trans "Add link" %}</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Localization" %}</legend>
|
||||
|
||||
@@ -74,9 +74,9 @@ from pretix.base.signals import register_ticket_outputs
|
||||
from pretix.base.templatetags.rich_text import markdown_compile_email
|
||||
from pretix.control.forms.event import (
|
||||
CancelSettingsForm, CommentForm, ConfirmTextFormset, EventDeleteForm,
|
||||
EventMetaValueForm, EventSettingsForm, EventUpdateForm,
|
||||
InvoiceSettingsForm, ItemMetaPropertyForm, MailSettingsForm,
|
||||
PaymentSettingsForm, ProviderForm, QuickSetupForm,
|
||||
EventFooterLinkFormset, EventMetaValueForm, EventSettingsForm,
|
||||
EventUpdateForm, InvoiceSettingsForm, ItemMetaPropertyForm,
|
||||
MailSettingsForm, PaymentSettingsForm, ProviderForm, QuickSetupForm,
|
||||
QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet,
|
||||
TicketSettingsForm, WidgetCodeForm,
|
||||
)
|
||||
@@ -186,6 +186,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
context['meta_forms'] = self.meta_forms
|
||||
context['item_meta_property_formset'] = self.item_meta_property_formset
|
||||
context['confirm_texts_formset'] = self.confirm_texts_formset
|
||||
context['footer_links_formset'] = self.footer_links_formset
|
||||
return context
|
||||
|
||||
@transaction.atomic
|
||||
@@ -195,6 +196,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
self.save_meta()
|
||||
self.save_item_meta_property_formset(self.object)
|
||||
self.save_confirm_texts_formset(self.object)
|
||||
self.save_footer_links_formset(self.object)
|
||||
change_css = False
|
||||
|
||||
if self.sform.has_changed() or self.confirm_texts_formset.has_changed():
|
||||
@@ -204,6 +206,10 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
self.request.event.log_action('pretix.event.settings', user=self.request.user, data=data)
|
||||
if any(p in self.sform.changed_data for p in SETTINGS_AFFECTING_CSS):
|
||||
change_css = True
|
||||
if self.footer_links_formset.has_changed():
|
||||
self.request.event.log_action('pretix.event.footerlinks.changed', user=self.request.user, data={
|
||||
'data': self.footer_links_formset.cleaned_data
|
||||
})
|
||||
if form.has_changed():
|
||||
self.request.event.log_action('pretix.event.changed', user=self.request.user, data={
|
||||
k: (form.cleaned_data.get(k).name
|
||||
@@ -238,7 +244,8 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
if form.is_valid() and self.sform.is_valid() and all([f.is_valid() for f in self.meta_forms]) and \
|
||||
self.item_meta_property_formset.is_valid() and self.confirm_texts_formset.is_valid():
|
||||
self.item_meta_property_formset.is_valid() and self.confirm_texts_formset.is_valid() and \
|
||||
self.footer_links_formset.is_valid():
|
||||
# reset timezone
|
||||
zone = timezone(self.sform.cleaned_data['timezone'])
|
||||
event = form.instance
|
||||
@@ -292,10 +299,18 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
def save_confirm_texts_formset(self, obj):
|
||||
obj.settings.confirm_texts = LazyI18nStringList(
|
||||
form_data['text'].data
|
||||
for form_data in sorted(self.confirm_texts_formset.cleaned_data, key=operator.itemgetter("ORDER"))
|
||||
if not form_data.get("DELETE", False)
|
||||
for form_data in sorted((d for d in self.confirm_texts_formset.cleaned_data if d), key=operator.itemgetter("ORDER"))
|
||||
if form_data and not form_data.get("DELETE", False)
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def footer_links_formset(self):
|
||||
return EventFooterLinkFormset(self.request.POST if self.request.method == "POST" else None, event=self.object,
|
||||
prefix="footer-links", instance=self.object)
|
||||
|
||||
def save_footer_links_formset(self, obj):
|
||||
self.footer_links_formset.save()
|
||||
|
||||
|
||||
class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin):
|
||||
model = Event
|
||||
|
||||
@@ -92,8 +92,8 @@ from pretix.control.forms.organizer import (
|
||||
CustomerCreateForm, CustomerUpdateForm, DeviceBulkEditForm, DeviceForm,
|
||||
EventMetaPropertyForm, GateForm, GiftCardCreateForm, GiftCardUpdateForm,
|
||||
MailSettingsForm, MembershipTypeForm, MembershipUpdateForm,
|
||||
OrganizerDeleteForm, OrganizerForm, OrganizerSettingsForm,
|
||||
OrganizerUpdateForm, TeamForm, WebHookForm,
|
||||
OrganizerDeleteForm, OrganizerFooterLinkFormset, OrganizerForm,
|
||||
OrganizerSettingsForm, OrganizerUpdateForm, TeamForm, WebHookForm,
|
||||
)
|
||||
from pretix.control.logdisplay import OVERVIEW_BANLIST
|
||||
from pretix.control.permissions import (
|
||||
@@ -416,11 +416,13 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
def get_context_data(self, *args, **kwargs) -> dict:
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
context['sform'] = self.sform
|
||||
context['footer_links_formset'] = self.footer_links_formset
|
||||
return context
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
self.sform.save()
|
||||
self.save_footer_links_formset(self.object)
|
||||
change_css = False
|
||||
if self.sform.has_changed():
|
||||
self.request.organizer.log_action(
|
||||
@@ -435,6 +437,10 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in SETTINGS_AFFECTING_CSS):
|
||||
change_css = True
|
||||
if self.footer_links_formset.has_changed():
|
||||
self.request.organizer.log_action('pretix.organizer.footerlinks.changed', user=self.request.user, data={
|
||||
'data': self.footer_links_formset.cleaned_data
|
||||
})
|
||||
if form.has_changed():
|
||||
self.request.organizer.log_action(
|
||||
'pretix.organizer.changed',
|
||||
@@ -466,11 +472,19 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
form = self.get_form()
|
||||
if form.is_valid() and self.sform.is_valid():
|
||||
if form.is_valid() and self.sform.is_valid() and self.footer_links_formset.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
@cached_property
|
||||
def footer_links_formset(self):
|
||||
return OrganizerFooterLinkFormset(self.request.POST if self.request.method == "POST" else None, organizer=self.object,
|
||||
prefix="footer-links", instance=self.object)
|
||||
|
||||
def save_footer_links_formset(self, obj):
|
||||
self.footer_links_formset.save()
|
||||
|
||||
|
||||
class OrganizerCreate(CreateView):
|
||||
model = Organizer
|
||||
|
||||
@@ -118,6 +118,10 @@ def _default_context(request):
|
||||
_footer += response
|
||||
else:
|
||||
_footer.append(response)
|
||||
_footer += request.event.cache.get_or_set('footer_links', lambda: [
|
||||
{'url': fl.url, 'label': fl.label}
|
||||
for fl in request.event.footer_links.all()
|
||||
], timeout=300)
|
||||
|
||||
if request.event.settings.presale_css_file:
|
||||
ctx['css_file'] = default_storage.url(request.event.settings.presale_css_file)
|
||||
@@ -158,6 +162,10 @@ def _default_context(request):
|
||||
ctx['organizer_logo'] = request.organizer.settings.get('organizer_logo_image', as_type=str, default='')[7:]
|
||||
ctx['organizer_homepage_text'] = request.organizer.settings.get('organizer_homepage_text', as_type=LazyI18nString)
|
||||
ctx['organizer'] = request.organizer
|
||||
_footer += request.organizer.cache.get_or_set('footer_links', lambda: [
|
||||
{'url': fl.url, 'label': fl.label}
|
||||
for fl in request.organizer.footer_links.all()
|
||||
], timeout=300)
|
||||
|
||||
ctx['html_head'] = "".join(h for h in _html_head if h)
|
||||
ctx['html_foot'] = "".join(h for h in _html_foot if h)
|
||||
|
||||
Reference in New Issue
Block a user