From fa372b3df0f695630db0272c95f0080451dd0f77 Mon Sep 17 00:00:00 2001 From: Felix Rindt Date: Fri, 11 Sep 2020 12:58:39 +0200 Subject: [PATCH] match copy answer button to fitting position --- src/pretix/base/views/mixins.py | 30 +++++++++- .../event/checkout_questions.html | 8 +-- src/pretix/static/pretixpresale/js/ui/main.js | 59 ++++++++++++------- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/pretix/base/views/mixins.py b/src/pretix/base/views/mixins.py index 76bc37612..cdbdd5306 100644 --- a/src/pretix/base/views/mixins.py +++ b/src/pretix/base/views/mixins.py @@ -1,3 +1,4 @@ +import itertools import json from collections import OrderedDict from decimal import Decimal @@ -53,7 +54,31 @@ class BaseQuestionsViewMixin: data=(self.request.POST if self.request.method == 'POST' else None), files=(self.request.FILES if self.request.method == 'POST' else None)) form.pos = cartpos or orderpos - form.show_copy_answers_to_addon_button = form.pos.addon_to and set(form.pos.addon_to.item.questions.all()) & set(form.pos.item.questions.all()) + + if form.pos.addon_to_id is not None: + form.copy_answer_from = None + # addons typically do not have the same item as the main position, so we look for overlapping questions + form.show_copy_answers_to_addon_button = bool( + set(form.pos.addon_to.item.questions.values_list("id", flat=True)) & + set(form.pos.item.questions.values_list("id", flat=True))) + else: + form.show_copy_answers_to_addon_button = False + # look for a position we can best copy answers from + form.copy_answer_from = next( + itertools.chain( + ( # match a position with the same item + other_form.pos.id for other_form in formlist + if other_form.pos.addon_to_id is None and form.pos.item.id == other_form.pos.item.id + ), + ( # match a position with questions in common + other_form.pos.id for other_form in formlist + if other_form.pos.addon_to_id is None + and set(form.pos.item.questions.values_list("id", flat=True)) & set(other_form.pos.item.questions.values_list("id", flat=True)) + ) + ), + None # didn't find a position to copy answers from + ) + if len(form.fields) > 0: formlist.append(form) return formlist @@ -105,8 +130,7 @@ class BaseQuestionsViewMixin: if hasattr(field, 'answer'): # We already have a cached answer object, so we don't # have to create a new one - if v == '' or v is None or (isinstance(field, forms.FileField) and v is False) \ - or (isinstance(v, QuerySet) and not v.exists()): + if v == '' or v is None or (isinstance(field, forms.FileField) and v is False) or (isinstance(v, QuerySet) and not v.exists()): if field.answer.file: field.answer.file.delete() field.answer.delete() diff --git a/src/pretix/presale/templates/pretixpresale/event/checkout_questions.html b/src/pretix/presale/templates/pretixpresale/event/checkout_questions.html index d87e44ba6..92e6b9050 100644 --- a/src/pretix/presale/templates/pretixpresale/event/checkout_questions.html +++ b/src/pretix/presale/templates/pretixpresale/event/checkout_questions.html @@ -60,9 +60,9 @@ {% if pos.variation %} – {{ pos.variation }} {% endif %} - {% if forloop.counter > 1 %} + {% if forms.0.copy_answer_from is not None %} - + {% else %} @@ -122,13 +122,13 @@ {% if form.show_copy_answers_to_addon_button %} - + {% endif %} + {{ form.pos.item.name }}{% if form.pos.variation %} – {{ form.pos.variation.value }}{% endif %} {% endif %} -
+
{% bootstrap_form form layout="checkout" %}
{% endfor %} diff --git a/src/pretix/static/pretixpresale/js/ui/main.js b/src/pretix/static/pretixpresale/js/ui/main.js index 3ea9f04df..94d033574 100644 --- a/src/pretix/static/pretixpresale/js/ui/main.js +++ b/src/pretix/static/pretixpresale/js/ui/main.js @@ -16,9 +16,13 @@ function ngettext(singular, plural, count) { function interpolate(fmt, object, named) { if (named) { - return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])}); + return fmt.replace(/%\(\w+\)s/g, function (match) { + return String(obj[match.slice(2, -2)]) + }); } else { - return fmt.replace(/%s/g, function(match){return String(obj.shift())}); + return fmt.replace(/%s/g, function (match) { + return String(obj.shift()) + }); } } @@ -171,13 +175,13 @@ $(function () { $(".js-copy-answers").click(function (e) { e.preventDefault(); e.stopPropagation(); - let idx = $(this).data('id'); - const addonDivs = $('div[data-idx="' + idx +'"]') + const idx = $(this).data('id'); + const copyFromIdx = $(this).data('copy-from') + const addonDivs = $('div[data-idx="' + idx + '"]') addonDivs.each(function (index) { const elements = $(this).find('input, select, textarea'); - - const addonIdx = $(this).attr("data-addonidx"); - const answersDiv = $('div[data-idx="0"][data-addonidx="' + addonIdx + '"]'); + const addonIdx = $(this).data("addonidx"); + const answersDiv = $('div[data-idx="' + copyFromIdx + '"][data-addonidx="' + addonIdx + '"]'); const answers = answersDiv.find('input, select, textarea'); copy_answers(elements, answers); @@ -189,7 +193,7 @@ $(function () { e.stopPropagation(); const id = $(this).data('id'); const addonId = $(this).data('addonid'); - const addonDiv = $('div[data-idx="' + id +'"][data-addonidx="' + addonId + '"]'); + const addonDiv = $('div[data-idx="' + id + '"][data-addonidx="' + addonId + '"]'); const elements = addonDiv.find('input, select, textarea'); const answers = $('*[data-idx="' + id + '"] input, *[data-idx="' + id + '"] select, *[data-idx="' + id + '"] textarea'); copy_answers(elements, answers); @@ -249,7 +253,7 @@ $(function () { is_enabled = true; } }); - $(".input-seat-selection option").each(function() { + $(".input-seat-selection option").each(function () { if ($(this).val() && $(this).val() !== "" && $(this).prop('selected')) { is_enabled = true; } @@ -257,7 +261,9 @@ $(function () { } if (!is_enabled && !$(".has-seating").length) { $("#btn-add-to-cart").prop("disabled", !is_enabled).popover({ - 'content': function () { return gettext("Please enter a quantity for one of the ticket types.") }, + 'content': function () { + return gettext("Please enter a quantity for one of the ticket types.") + }, 'placement': 'top', 'trigger': 'hover focus' }); @@ -353,7 +359,9 @@ $(function () { if (counter > curCounter) { return; // Lost race } - dependent.find("option").filter(function (t) {return !!$(this).attr("value")}).remove(); + dependent.find("option").filter(function (t) { + return !!$(this).attr("value") + }).remove(); if (data.data.length > 0) { $.each(data.data, function (k, s) { dependent.append($("