diff --git a/src/pretix/base/migrations/0003_auto_20150602_2232.py b/src/pretix/base/migrations/0003_auto_20150602_2232.py new file mode 100644 index 0000000000..8a055357c0 --- /dev/null +++ b/src/pretix/base/migrations/0003_auto_20150602_2232.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +import django.core.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0002_auto_20150524_1148'), + ] + + operations = [ + migrations.AlterModelOptions( + name='item', + options={'verbose_name_plural': 'Products', 'ordering': ('category__position', 'category', 'position'), 'verbose_name': 'Product'}, + ), + migrations.AddField( + model_name='item', + name='position', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='organizer', + name='slug', + field=models.SlugField(help_text='Should be short, only contain lowercase letters and numbers, and must be unique among your events. This is being used in addresses and bank transfer references.', validators=[django.core.validators.RegexValidator(message='The slug may only contain letters, numbers, dots and dashes.', regex='^[a-zA-Z0-9.-]+$')], verbose_name='Slug'), + ), + ] diff --git a/src/pretix/base/models.py b/src/pretix/base/models.py index 48089bfe74..2c71a9e29d 100644 --- a/src/pretix/base/models.py +++ b/src/pretix/base/models.py @@ -860,10 +860,14 @@ class Item(Versionable): ), default=False ) + position = models.IntegerField( + default=0 + ) class Meta: verbose_name = _("Product") verbose_name_plural = _("Products") + ordering = ("category__position", "category", "position") def __str__(self): return str(self.name) diff --git a/src/pretix/control/templates/pretixcontrol/items/index.html b/src/pretix/control/templates/pretixcontrol/items/index.html index 6b9afc8bfd..85ad40cbad 100644 --- a/src/pretix/control/templates/pretixcontrol/items/index.html +++ b/src/pretix/control/templates/pretixcontrol/items/index.html @@ -3,6 +3,13 @@ {% block title %}{% trans "Products" %}{% endblock %} {% block inside %}

{% trans "Products" %}

+

+ {% blocktrans trimmed %} + Below, you find a list of all available products. You can click on a product name to inspect and change + product details. You can also use the buttons on the right to change the order of products within a + give category. + {% endblocktrans %} +

{% trans "Create new product" %} @@ -12,16 +19,24 @@ {% trans "Product name" %} {% trans "Category" %} + - {% for i in items %} - - {{ i.name }} - {% if i.category %}{{ i.category.name }}{% endif %} - - {% endfor %} + {% regroup items by category as cat_list %} + {% for c in cat_list %} + {% for i in c.list %} + + {{ i.name }} + {% if i.category %}{{ i.category.name }}{% endif %} + + + + + + {% endfor %} + {% endfor %} {% include "pretixcontrol/pagination.html" %} diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index 8662439d3f..633ef415dd 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -27,6 +27,8 @@ urlpatterns = [ name='event.item.variations'), url(r'^items/(?P[0-9a-f-]+)/restrictions$', item.ItemRestrictions.as_view(), name='event.item.restrictions'), + url(r'^items/(?P[0-9a-f-]+)/up$', item.item_move_up, name='event.items.up'), + url(r'^items/(?P[0-9a-f-]+)/down$', item.item_move_down, name='event.items.down'), url(r'^categories/$', item.CategoryList.as_view(), name='event.items.categories'), url(r'^categories/(?P[0-9a-f-]+)/delete$', item.CategoryDelete.as_view(), name='event.items.categories.delete'), diff --git a/src/pretix/control/views/item.py b/src/pretix/control/views/item.py index 9c744f8430..bb3a91ff1f 100644 --- a/src/pretix/control/views/item.py +++ b/src/pretix/control/views/item.py @@ -27,7 +27,9 @@ from . import UpdateView, CreateView class ItemList(ListView): model = Item context_object_name = 'items' - paginate_by = 30 + # paginate_by = 30 + # Pagination is disabled as it is very unlikely to be necessary + # here and could cause problems with the "reorder-within-category" feature template_name = 'pretixcontrol/items/index.html' def get_queryset(self): @@ -36,6 +38,49 @@ class ItemList(ListView): ).prefetch_related("category") +def item_move(request, item, up=True): + """ + This is a helper function to avoid duplicating code in item_move_up and + item_move_down. It takes an item and a direction and then tries to bring + all items for this category in a new order. + """ + try: + item = request.event.items.current.get( + identity=item + ) + except Item.DoesNotExist: + raise Http404(_("The requested product does not exist.")) + items = list(request.event.items.current.filter(category=item.category).order_by("position")) + + index = items.index(item) + if index != 0 and up: + items[index - 1], items[index] = items[index], items[index - 1] + elif index != len(items) - 1 and not up: + items[index + 1], items[index] = items[index], items[index + 1] + + for i, item in enumerate(items): + if item.position != i: + item.position = i + item.save() # TODO: Clone or document sloppiness? + messages.success(request, _('The order of items as been updated.')) + + +@event_permission_required("can_change_items") +def item_move_up(request, organizer, event, item): + item_move(request, item, up=True) + return redirect('control:event.items', + organizer=request.event.organizer.slug, + event=request.event.slug) + + +@event_permission_required("can_change_items") +def item_move_down(request, organizer, event, item): + item_move(request, item, up=False) + return redirect('control:event.items', + organizer=request.event.organizer.slug, + event=request.event.slug) + + class CategoryForm(VersionedModelForm): class Meta: @@ -159,6 +204,7 @@ def category_move(request, category, up=True): if cat.position != i: cat.position = i cat.save() # TODO: Clone or document sloppiness? + messages.success(request, _('The order of categories as been updated.')) @event_permission_required("can_change_items") diff --git a/src/pretix/presale/views/event.py b/src/pretix/presale/views/event.py index 3d9b942316..7714258e27 100644 --- a/src/pretix/presale/views/event.py +++ b/src/pretix/presale/views/event.py @@ -35,7 +35,7 @@ class EventIndex(EventViewMixin, CartDisplayMixin, TemplateView): 'quotas', 'variations__quotas', 'quotas__event' # for .availability() ).annotate(quotac=Count('quotas')).filter( quotac__gt=0 - ).order_by('category__position', 'category_id', 'name') + ).order_by('category__position', 'category_id', 'position', 'name') for item in items: item.available_variations = sorted(item.get_all_available_variations(),