forked from CGM_Public/pretix_original
Use tabs for all long settings and CRUD forms (#1352)
* First tabs
* Convert more pages
* Convert question page
* Item form
* Add item_formsets signal
* Revert "Add new signal nav_item"
This reverts commit 1ce613ff89.
* Formset is a word!
This commit is contained in:
@@ -40,10 +40,10 @@ from pretix.base.signals import register_ticket_outputs
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.base.templatetags.rich_text import markdown_compile_email
|
||||
from pretix.control.forms.event import (
|
||||
CancelSettingsForm, CommentForm, DisplaySettingsForm, EventDeleteForm,
|
||||
EventMetaValueForm, EventSettingsForm, EventUpdateForm,
|
||||
InvoiceSettingsForm, MailSettingsForm, PaymentSettingsForm, ProviderForm,
|
||||
QuickSetupForm, QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet,
|
||||
CancelSettingsForm, CommentForm, EventDeleteForm, EventMetaValueForm,
|
||||
EventSettingsForm, EventUpdateForm, InvoiceSettingsForm, MailSettingsForm,
|
||||
PaymentSettingsForm, ProviderForm, QuickSetupForm,
|
||||
QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet,
|
||||
TicketSettingsForm, WidgetCodeForm,
|
||||
)
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
@@ -63,6 +63,17 @@ class EventSettingsViewMixin:
|
||||
ctx['is_event_settings'] = True
|
||||
return ctx
|
||||
|
||||
def _save_decoupled(self, form):
|
||||
# Save fields that are currently only set via the organizer but should be decoupled
|
||||
fields = set()
|
||||
for f in self.request.POST.getlist("decouple"):
|
||||
fields |= set(f.split(","))
|
||||
for f in fields:
|
||||
if f not in form.fields:
|
||||
continue
|
||||
if f not in self.request.event.settings._cache():
|
||||
self.request.event.settings.set(f, self.request.event.settings.get(f))
|
||||
|
||||
|
||||
class MetaDataEditorMixin:
|
||||
meta_form = EventMetaValueForm
|
||||
@@ -117,7 +128,8 @@ class EventUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, MetaData
|
||||
return EventSettingsForm(
|
||||
obj=self.object,
|
||||
prefix='settings',
|
||||
data=self.request.POST if self.request.method == 'POST' else None
|
||||
data=self.request.POST if self.request.method == 'POST' else None,
|
||||
files=self.request.FILES if self.request.method == 'POST' else None,
|
||||
)
|
||||
|
||||
def get_context_data(self, *args, **kwargs) -> dict:
|
||||
@@ -128,18 +140,32 @@ class EventUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, MetaData
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
self._save_decoupled(self.sform)
|
||||
self.sform.save()
|
||||
self.save_meta()
|
||||
change_css = False
|
||||
|
||||
if self.sform.has_changed():
|
||||
self.request.event.log_action('pretix.event.settings', user=self.request.user, data={
|
||||
k: self.request.event.settings.get(k) for k in self.sform.changed_data
|
||||
})
|
||||
display_properties = (
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in display_properties):
|
||||
change_css = True
|
||||
if form.has_changed():
|
||||
self.request.event.log_action('pretix.event.changed', user=self.request.user, data={
|
||||
k: getattr(self.request.event, k) for k in form.changed_data
|
||||
})
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
|
||||
if change_css:
|
||||
regenerate_css.apply_async(args=(self.request.event.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.'))
|
||||
else:
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
@@ -325,17 +351,6 @@ class EventSettingsFormView(EventPermissionRequiredMixin, FormView):
|
||||
kwargs['obj'] = self.request.event
|
||||
return kwargs
|
||||
|
||||
def _save_decoupled(self, form):
|
||||
# Save fields that are currently only set via the organizer but should be decoupled
|
||||
fields = set()
|
||||
for f in self.request.POST.getlist("decouple"):
|
||||
fields |= set(f.split(","))
|
||||
for f in fields:
|
||||
if f not in form.fields:
|
||||
continue
|
||||
if f not in self.request.event.settings._cache():
|
||||
self.request.event.settings.set(f, self.request.event.settings.get(f))
|
||||
|
||||
def form_success(self):
|
||||
pass
|
||||
|
||||
@@ -453,41 +468,12 @@ class InvoicePreview(EventPermissionRequiredMixin, View):
|
||||
return resp
|
||||
|
||||
|
||||
class DisplaySettings(EventSettingsViewMixin, EventSettingsFormView):
|
||||
model = Event
|
||||
form_class = DisplaySettingsForm
|
||||
template_name = 'pretixcontrol/event/display.html'
|
||||
permission = 'can_change_event_settings'
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
return reverse('control:event.settings.display', kwargs={
|
||||
class DisplaySettings(View):
|
||||
def get(self, request, *wargs, **kwargs):
|
||||
return redirect(reverse('control:event.settings', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug
|
||||
})
|
||||
|
||||
@transaction.atomic
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
self._save_decoupled(form)
|
||||
if form.has_changed():
|
||||
self.request.event.log_action(
|
||||
'pretix.event.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_css.apply_async(args=(self.request.event.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)
|
||||
}) + '#tab-0-3-open')
|
||||
|
||||
|
||||
class MailSettings(EventSettingsViewMixin, EventSettingsFormView):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
@@ -13,11 +14,13 @@ from django.utils.functional import cached_property
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
from django.views.generic import ListView
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||
from django.views.generic.edit import DeleteView
|
||||
from django_countries.fields import Country
|
||||
|
||||
from pretix.api.serializers.item import (
|
||||
ItemAddOnSerializer, ItemBundleSerializer, ItemVariationSerializer,
|
||||
)
|
||||
from pretix.base.forms import I18nFormSet
|
||||
from pretix.base.models import (
|
||||
CartPosition, Item, ItemCategory, ItemVariation, Order, Question,
|
||||
@@ -35,7 +38,7 @@ from pretix.control.forms.item import (
|
||||
from pretix.control.permissions import (
|
||||
EventPermissionRequiredMixin, event_permission_required,
|
||||
)
|
||||
from pretix.control.signals import item_forms, nav_item
|
||||
from pretix.control.signals import item_forms, item_formsets
|
||||
|
||||
from . import ChartContainingView, CreateView, PaginationMixin, UpdateView
|
||||
|
||||
@@ -824,18 +827,6 @@ class ItemDetailMixin(SingleObjectMixin):
|
||||
model = Item
|
||||
context_object_name = 'item'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
nav = sorted(
|
||||
sum(
|
||||
(list(a[1]) for a in nav_item.send(self.request.event, request=self.request, item=self.get_object())),
|
||||
[]
|
||||
),
|
||||
key=lambda r: str(r['label'])
|
||||
)
|
||||
ctx['extra_nav'] = nav
|
||||
return ctx
|
||||
|
||||
def get_object(self, queryset=None) -> Item:
|
||||
try:
|
||||
if not hasattr(self, 'object') or not self.object:
|
||||
@@ -916,14 +907,85 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
|
||||
'item': self.get_object().id,
|
||||
})
|
||||
|
||||
def is_valid(self, form):
|
||||
v = (
|
||||
form.is_valid()
|
||||
and all(f.is_valid() for f in self.plugin_forms)
|
||||
and all(f.is_valid() for f in self.formsets.values())
|
||||
)
|
||||
if v and form.cleaned_data['category'] and form.cleaned_data['category'].is_addon:
|
||||
addons = self.formsets['addons'].ordered_forms + [
|
||||
ef for ef in self.formsets['addons'].extra_forms
|
||||
if ef not in self.formsets['addons'].ordered_forms and ef not in self.formsets['addons'].deleted_forms
|
||||
]
|
||||
if addons:
|
||||
messages.error(self.request,
|
||||
_('You cannot add add-ons to a product that is only available as an add-on '
|
||||
'itself.'))
|
||||
v = False
|
||||
|
||||
bundles = [
|
||||
ef for ef in self.formsets['bundles'].forms
|
||||
if ef not in self.formsets['bundles'].deleted_forms
|
||||
]
|
||||
if bundles:
|
||||
messages.error(self.request,
|
||||
_('You cannot add bundles to a product that is only available as an add-on '
|
||||
'itself.'))
|
||||
v = False
|
||||
return v
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.get_object()
|
||||
form = self.get_form()
|
||||
if form.is_valid() and all(f.is_valid() for f in self.plugin_forms):
|
||||
if self.is_valid(form):
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
def save_formset(self, key, log_base, attr='item', order=True, serializer=None,
|
||||
rm_verb='removed'):
|
||||
for form in self.formsets[key].deleted_forms:
|
||||
if not form.instance.pk:
|
||||
continue
|
||||
d = {
|
||||
'id': form.instance.pk
|
||||
}
|
||||
if serializer:
|
||||
d.update(serializer(form.instance).data)
|
||||
self.get_object().log_action(
|
||||
'pretix.event.item.{}.{}'.format(log_base, rm_verb), user=self.request.user, data=d
|
||||
)
|
||||
form.instance.delete()
|
||||
form.instance.pk = None
|
||||
|
||||
if order:
|
||||
forms = self.formsets[key].ordered_forms + [
|
||||
ef for ef in self.formsets[key].extra_forms
|
||||
if ef not in self.formsets[key].ordered_forms and ef not in self.formsets[key].deleted_forms
|
||||
]
|
||||
else:
|
||||
forms = [
|
||||
ef for ef in self.formsets[key].forms
|
||||
if ef not in self.formsets[key].deleted_forms
|
||||
]
|
||||
for i, form in enumerate(forms):
|
||||
if order:
|
||||
form.instance.position = i
|
||||
setattr(form.instance, attr, self.get_object())
|
||||
created = not form.instance.pk
|
||||
form.save()
|
||||
if form.has_changed() and any(a for a in form.changed_data if a != 'ORDER'):
|
||||
change_data = {k: form.cleaned_data.get(k) for k in form.changed_data}
|
||||
if key == 'variations':
|
||||
change_data['value'] = form.instance.value
|
||||
change_data['id'] = form.instance.pk
|
||||
self.get_object().log_action(
|
||||
'pretix.event.item.{}.changed'.format(log_base) if not created else
|
||||
'pretix.event.item.{}.added'.format(log_base),
|
||||
user=self.request.user, data=change_data
|
||||
)
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
@@ -945,6 +1007,27 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
|
||||
invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'item': self.object.pk})
|
||||
for f in self.plugin_forms:
|
||||
f.save()
|
||||
|
||||
for k, v in self.formsets.items():
|
||||
if k == 'variations':
|
||||
self.save_formset(
|
||||
'variations', 'variation',
|
||||
serializer=ItemVariationSerializer,
|
||||
rm_verb='deleted'
|
||||
)
|
||||
elif k == 'addons':
|
||||
self.save_formset(
|
||||
'addons', 'addons', 'base_item',
|
||||
serializer=ItemAddOnSerializer
|
||||
)
|
||||
elif k == 'bundles':
|
||||
self.save_formset(
|
||||
'bundles', 'bundles', 'base_item', order=False,
|
||||
serializer=ItemBundleSerializer
|
||||
)
|
||||
else:
|
||||
v.save()
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
def form_invalid(self, form):
|
||||
@@ -954,6 +1037,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data()
|
||||
ctx['plugin_forms'] = self.plugin_forms
|
||||
ctx['formsets'] = self.formsets
|
||||
|
||||
if not ctx['item'].active and ctx['item'].bundled_with.count() > 0:
|
||||
messages.info(self.request, _("You disabled this item, but it is still part of a product bundle. "
|
||||
@@ -962,246 +1046,51 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
|
||||
|
||||
return ctx
|
||||
|
||||
|
||||
class ItemVariations(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView):
|
||||
permission = 'can_change_items'
|
||||
template_name = 'pretixcontrol/item/variations.html'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.item = None
|
||||
|
||||
@cached_property
|
||||
def formset(self):
|
||||
formsetclass = inlineformset_factory(
|
||||
Item, ItemVariation,
|
||||
form=ItemVariationForm, formset=ItemVariationsFormSet,
|
||||
can_order=True, can_delete=True, extra=0
|
||||
)
|
||||
return formsetclass(self.request.POST if self.request.method == "POST" else None,
|
||||
queryset=ItemVariation.objects.filter(item=self.get_object()),
|
||||
event=self.request.event)
|
||||
def formsets(self):
|
||||
f = OrderedDict([
|
||||
('variations', inlineformset_factory(
|
||||
Item, ItemVariation,
|
||||
form=ItemVariationForm, formset=ItemVariationsFormSet,
|
||||
can_order=True, can_delete=True, extra=0
|
||||
)(
|
||||
self.request.POST if self.request.method == "POST" else None,
|
||||
queryset=ItemVariation.objects.filter(item=self.get_object()),
|
||||
event=self.request.event, prefix="variations"
|
||||
)),
|
||||
('addons', inlineformset_factory(
|
||||
Item, ItemAddOn,
|
||||
form=ItemAddOnForm, formset=ItemAddOnsFormSet,
|
||||
can_order=True, can_delete=True, extra=0
|
||||
)(
|
||||
self.request.POST if self.request.method == "POST" else None,
|
||||
queryset=ItemAddOn.objects.filter(base_item=self.get_object()),
|
||||
event=self.request.event, prefix="addons"
|
||||
)),
|
||||
('bundles', inlineformset_factory(
|
||||
Item, ItemBundle,
|
||||
form=ItemBundleForm, formset=ItemBundleFormSet,
|
||||
fk_name='base_item',
|
||||
can_order=False, can_delete=True, extra=0
|
||||
)(
|
||||
self.request.POST if self.request.method == "POST" else None,
|
||||
queryset=ItemBundle.objects.filter(base_item=self.get_object()),
|
||||
event=self.request.event, item=self.item, prefix="bundles"
|
||||
)),
|
||||
])
|
||||
if not self.object.has_variations:
|
||||
del f['variations']
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
with transaction.atomic():
|
||||
if self.formset.is_valid():
|
||||
for form in self.formset.deleted_forms:
|
||||
if not form.instance.pk:
|
||||
continue
|
||||
self.get_object().log_action(
|
||||
'pretix.event.item.variation.deleted', user=self.request.user, data={
|
||||
'value': form.instance.value,
|
||||
'id': form.instance.pk
|
||||
}
|
||||
)
|
||||
form.instance.delete()
|
||||
form.instance.pk = None
|
||||
|
||||
forms = self.formset.ordered_forms + [
|
||||
ef for ef in self.formset.extra_forms
|
||||
if ef not in self.formset.ordered_forms and ef not in self.formset.deleted_forms
|
||||
]
|
||||
for i, form in enumerate(forms):
|
||||
form.instance.position = i
|
||||
form.instance.item = self.get_object()
|
||||
created = not form.instance.pk
|
||||
form.save()
|
||||
if form.has_changed():
|
||||
change_data = {k: form.cleaned_data.get(k) for k in form.changed_data}
|
||||
change_data['value'] = form.instance.value
|
||||
change_data['id'] = form.instance.pk
|
||||
self.get_object().log_action(
|
||||
'pretix.event.item.variation.changed' if not created else
|
||||
'pretix.event.item.variation.added',
|
||||
user=self.request.user, data=change_data
|
||||
)
|
||||
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
return redirect(self.get_success_url())
|
||||
messages.error(self.request, _('We could not save your changes. See below for details.'))
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
return reverse('control:event.item.variations', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
'item': self.get_object().id,
|
||||
})
|
||||
|
||||
def get_context_data(self, **kwargs) -> dict:
|
||||
self.object = self.get_object()
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['formset'] = self.formset
|
||||
return context
|
||||
|
||||
|
||||
class ItemAddOns(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView):
|
||||
permission = 'can_change_items'
|
||||
template_name = 'pretixcontrol/item/addons.html'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.item = None
|
||||
|
||||
@cached_property
|
||||
def formset(self):
|
||||
formsetclass = inlineformset_factory(
|
||||
Item, ItemAddOn,
|
||||
form=ItemAddOnForm, formset=ItemAddOnsFormSet,
|
||||
can_order=True, can_delete=True, extra=0
|
||||
)
|
||||
return formsetclass(self.request.POST if self.request.method == "POST" else None,
|
||||
queryset=ItemAddOn.objects.filter(base_item=self.get_object()),
|
||||
event=self.request.event)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
with transaction.atomic():
|
||||
if self.formset.is_valid():
|
||||
for form in self.formset.deleted_forms:
|
||||
if not form.instance.pk:
|
||||
continue
|
||||
self.get_object().log_action(
|
||||
'pretix.event.item.addons.removed', user=self.request.user, data={
|
||||
'category': form.instance.addon_category.pk
|
||||
}
|
||||
)
|
||||
form.instance.delete()
|
||||
form.instance.pk = None
|
||||
|
||||
forms = self.formset.ordered_forms + [
|
||||
ef for ef in self.formset.extra_forms
|
||||
if ef not in self.formset.ordered_forms and ef not in self.formset.deleted_forms
|
||||
]
|
||||
for i, form in enumerate(forms):
|
||||
form.instance.base_item = self.get_object()
|
||||
form.instance.position = i
|
||||
created = not form.instance.pk
|
||||
form.save()
|
||||
if form.has_changed():
|
||||
change_data = {k: form.cleaned_data.get(k) for k in form.changed_data}
|
||||
change_data['id'] = form.instance.pk
|
||||
self.get_object().log_action(
|
||||
'pretix.event.item.addons.changed' if not created else
|
||||
'pretix.event.item.addons.added',
|
||||
user=self.request.user, data=change_data
|
||||
)
|
||||
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
return redirect(self.get_success_url())
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if self.get_object().category and self.get_object().category.is_addon:
|
||||
messages.error(self.request, _('You cannot add add-ons to a product that is only available as an add-on '
|
||||
'itself.'))
|
||||
return redirect(self.get_previous_url())
|
||||
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_previous_url(self) -> str:
|
||||
return reverse('control:event.item', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
'item': self.get_object().id,
|
||||
})
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
return reverse('control:event.item.addons', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
'item': self.get_object().id,
|
||||
})
|
||||
|
||||
def get_context_data(self, **kwargs) -> dict:
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['formset'] = self.formset
|
||||
return context
|
||||
|
||||
|
||||
class ItemBundles(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView):
|
||||
permission = 'can_change_items'
|
||||
template_name = 'pretixcontrol/item/bundles.html'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.item = None
|
||||
|
||||
@cached_property
|
||||
def formset(self):
|
||||
formsetclass = inlineformset_factory(
|
||||
Item, ItemBundle,
|
||||
form=ItemBundleForm, formset=ItemBundleFormSet,
|
||||
fk_name='base_item',
|
||||
can_order=False, can_delete=True, extra=0
|
||||
)
|
||||
return formsetclass(self.request.POST if self.request.method == "POST" else None,
|
||||
queryset=ItemBundle.objects.filter(base_item=self.get_object()),
|
||||
event=self.request.event, item=self.item)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
with transaction.atomic():
|
||||
if self.formset.is_valid():
|
||||
for form in self.formset.deleted_forms:
|
||||
if not form.instance.pk:
|
||||
continue
|
||||
self.get_object().log_action(
|
||||
'pretix.event.item.bundles.removed', user=self.request.user, data={
|
||||
'bundled_item': form.instance.bundled_item.pk,
|
||||
'bundled_variation': (form.instance.bundled_variation.pk if form.instance.bundled_variation else None),
|
||||
'count': form.instance.count,
|
||||
'designated_price': str(form.instance.designated_price),
|
||||
}
|
||||
)
|
||||
form.instance.delete()
|
||||
form.instance.pk = None
|
||||
|
||||
forms = [
|
||||
ef for ef in self.formset.forms
|
||||
if ef not in self.formset.deleted_forms
|
||||
]
|
||||
for i, form in enumerate(forms):
|
||||
form.instance.base_item = self.get_object()
|
||||
created = not form.instance.pk
|
||||
form.save()
|
||||
if form.has_changed():
|
||||
change_data = {k: form.cleaned_data.get(k) for k in form.changed_data}
|
||||
change_data['id'] = form.instance.pk
|
||||
self.get_object().log_action(
|
||||
'pretix.event.item.bundles.changed' if not created else
|
||||
'pretix.event.item.bundles.added',
|
||||
user=self.request.user, data=change_data
|
||||
)
|
||||
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
return redirect(self.get_success_url())
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if self.get_object().category and self.get_object().category.is_addon:
|
||||
messages.error(self.request, _('You cannot add bundles to a product that is only available as an add-on '
|
||||
'itself.'))
|
||||
return redirect(self.get_previous_url())
|
||||
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_previous_url(self) -> str:
|
||||
return reverse('control:event.item', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
'item': self.get_object().id,
|
||||
})
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
return reverse('control:event.item.bundles', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
'item': self.get_object().id,
|
||||
})
|
||||
|
||||
def get_context_data(self, **kwargs) -> dict:
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['formset'] = self.formset
|
||||
return context
|
||||
i = 0
|
||||
for rec, resp in item_formsets.send(sender=self.request.event, item=self.item, request=self.request):
|
||||
if isinstance(resp, (list, tuple)):
|
||||
for k in resp:
|
||||
f['p-{}'.format(i)] = k
|
||||
i += 1
|
||||
else:
|
||||
f['p-{}'.format(i)] = resp
|
||||
i += 1
|
||||
return f
|
||||
|
||||
|
||||
class ItemDelete(EventPermissionRequiredMixin, DeleteView):
|
||||
|
||||
@@ -14,6 +14,7 @@ from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views import View
|
||||
from django.views.generic import (
|
||||
CreateView, DeleteView, DetailView, FormView, ListView, UpdateView,
|
||||
)
|
||||
@@ -25,9 +26,8 @@ from pretix.base.models.organizer import TeamAPIToken
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.control.forms.filter import OrganizerFilterForm
|
||||
from pretix.control.forms.organizer import (
|
||||
DeviceForm, EventMetaPropertyForm, OrganizerDeleteForm,
|
||||
OrganizerDisplaySettingsForm, OrganizerForm, OrganizerSettingsForm,
|
||||
OrganizerUpdateForm, TeamForm, WebHookForm,
|
||||
DeviceForm, EventMetaPropertyForm, OrganizerDeleteForm, OrganizerForm,
|
||||
OrganizerSettingsForm, OrganizerUpdateForm, TeamForm, WebHookForm,
|
||||
)
|
||||
from pretix.control.permissions import (
|
||||
AdministratorPermissionRequiredMixin, OrganizerPermissionRequiredMixin,
|
||||
@@ -154,39 +154,13 @@ class OrganizerSettingsFormView(OrganizerDetailViewMixin, OrganizerPermissionReq
|
||||
return self.get(request)
|
||||
|
||||
|
||||
class OrganizerDisplaySettings(OrganizerSettingsFormView):
|
||||
model = Organizer
|
||||
form_class = OrganizerDisplaySettingsForm
|
||||
template_name = 'pretixcontrol/organizers/display.html'
|
||||
permission = 'can_change_organizer_settings'
|
||||
class OrganizerDisplaySettings(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, View):
|
||||
permission = None
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
return reverse('control:organizer.display', kwargs={
|
||||
def get(self, request, *wargs, **kwargs):
|
||||
return redirect(reverse('control:organizer.edit', 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)
|
||||
}) + '#tab-0-3-open')
|
||||
|
||||
|
||||
class OrganizerDelete(AdministratorPermissionRequiredMixin, FormView):
|
||||
@@ -263,6 +237,7 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
def form_valid(self, form):
|
||||
self.save_formset(self.object)
|
||||
self.sform.save()
|
||||
change_css = False
|
||||
if self.sform.has_changed():
|
||||
self.request.organizer.log_action(
|
||||
'pretix.organizer.settings',
|
||||
@@ -274,13 +249,25 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
for k in self.sform.changed_data
|
||||
}
|
||||
)
|
||||
display_properties = (
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in display_properties):
|
||||
change_css = True
|
||||
if form.has_changed():
|
||||
self.request.organizer.log_action(
|
||||
'pretix.organizer.changed',
|
||||
user=self.request.user,
|
||||
data={k: form.cleaned_data.get(k) for k in form.changed_data}
|
||||
)
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
|
||||
if change_css:
|
||||
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.'))
|
||||
else:
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
|
||||
Reference in New Issue
Block a user