mirror of
https://github.com/pretix/pretix.git
synced 2026-05-08 15:44:02 +00:00
Copy answers button for addon products (#1733)
This commit is contained in:
@@ -53,6 +53,7 @@ class BaseQuestionsViewMixin:
|
|||||||
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))
|
files=(self.request.FILES if self.request.method == 'POST' else None))
|
||||||
form.pos = cartpos or orderpos
|
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 len(form.fields) > 0:
|
if len(form.fields) > 0:
|
||||||
formlist.append(form)
|
formlist.append(form)
|
||||||
return formlist
|
return formlist
|
||||||
@@ -61,7 +62,7 @@ class BaseQuestionsViewMixin:
|
|||||||
def formdict(self):
|
def formdict(self):
|
||||||
storage = OrderedDict()
|
storage = OrderedDict()
|
||||||
for f in self.forms:
|
for f in self.forms:
|
||||||
pos = f.cartpos or f.orderpos
|
pos = f.pos
|
||||||
if pos.addon_to_id:
|
if pos.addon_to_id:
|
||||||
if pos.addon_to not in storage:
|
if pos.addon_to not in storage:
|
||||||
storage[pos.addon_to] = []
|
storage[pos.addon_to] = []
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
workshops as add-ons to the conference ticket. With this configuration, the workshops cannot be bought
|
workshops as add-ons to the conference ticket. With this configuration, the workshops cannot be bought
|
||||||
on their own but only in combination with a conference ticket. You can here specify categories of products
|
on their own but only in combination with a conference ticket. You can here specify categories of products
|
||||||
that can be used as add-ons to this product. You can also specify the minimum and maximum number of
|
that can be used as add-ons to this product. You can also specify the minimum and maximum number of
|
||||||
add-ons of the given category that can or need to be chosen. The user can buy every add-on from the
|
add-ons of the given category that can or need to be chosen.
|
||||||
category at most once. If an add-on product has multiple variations, only one of them can be bought.
|
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}">
|
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}">
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if forloop.counter > 1 %}
|
{% if forloop.counter > 1 %}
|
||||||
<span class="text-right flip">
|
<span class="text-right flip">
|
||||||
<input type="button" data-id="{{ forloop.counter0 }}" name="copy" class="js-copy-answers btn btn-default btn-xs" value='{% trans "Copy answers from above" %}'>
|
<button type="button" data-id="{{ forloop.counter0 }}" name="copy" class="js-copy-answers btn btn-default btn-xs">{% trans "Copy answers from above" %}</button>
|
||||||
<i class="fa fa-angle-down collapse-indicator"></i>
|
<i class="fa fa-angle-down collapse-indicator"></i>
|
||||||
</span>
|
</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
</h4>
|
</h4>
|
||||||
</summary>
|
</summary>
|
||||||
<div>
|
<div>
|
||||||
<div class="panel-body questions-form" data-idx="{{ forloop.counter0 }}">
|
<div class="panel-body questions-form">
|
||||||
{% if pos.addons.all %}
|
{% if pos.addons.all %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">
|
<label class="col-md-3 control-label">
|
||||||
@@ -105,9 +105,18 @@
|
|||||||
{% for form in forms %}
|
{% for form in forms %}
|
||||||
{% if form.pos.item != pos.item %}
|
{% if form.pos.item != pos.item %}
|
||||||
{# Add-Ons #}
|
{# Add-Ons #}
|
||||||
<legend>+ {{ form.pos.item.name }}{% if form.pos.variation %} – {{ form.pos.variation.value }}{% endif %}</legend>
|
<legend>
|
||||||
|
{% if form.show_copy_answers_to_addon_button %}
|
||||||
|
<span class="pull-right flip">
|
||||||
|
<button type="button" data-id="{{ forloop.parentloop.counter0 }}" data-addonid="{{ forloop.counter0 }}" name="copy" class="js-copy-answers-addon btn btn-default btn-xs">{% trans "Copy answers" %}</button>
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
+ {{ form.pos.item.name }}{% if form.pos.variation %} – {{ form.pos.variation.value }}{% endif %}
|
||||||
|
</legend>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% bootstrap_form form layout="checkout" %}
|
<div data-idx="{{ forloop.parentloop.counter0 }}" data-addonidx="{{ forloop.counter0 }}">
|
||||||
|
{% bootstrap_form form layout="checkout" %}
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -171,8 +171,28 @@ $(function () {
|
|||||||
$(".js-copy-answers").click(function (e) {
|
$(".js-copy-answers").click(function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
var idx = $(this).data('id');
|
let idx = $(this).data('id');
|
||||||
copy_answers(idx);
|
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 answers = answersDiv.find('input, select, textarea');
|
||||||
|
|
||||||
|
copy_answers(elements, answers);
|
||||||
|
})
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$(".js-copy-answers-addon").click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
const id = $(this).data('id');
|
||||||
|
const addonId = $(this).data('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);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
var copy_to_first_ticket = true;
|
var copy_to_first_ticket = true;
|
||||||
@@ -424,45 +444,41 @@ $(function () {
|
|||||||
lightbox.init();
|
lightbox.init();
|
||||||
});
|
});
|
||||||
|
|
||||||
function copy_answers(idx) {
|
function copy_answers(elements, answers) {
|
||||||
var elements = $('*[data-idx="' + idx + '"] input, *[data-idx="' + idx + '"] select, *[data-idx="' + idx + '"] textarea');
|
elements.each(function (index) {
|
||||||
var firstAnswers = $('*[data-idx="0"] input, *[data-idx="0"] select, *[data-idx="0"] textarea');
|
|
||||||
elements.each(function (index) {
|
|
||||||
var input = $(this),
|
var input = $(this),
|
||||||
tagName = input.prop('tagName').toLowerCase(),
|
tagName = input.prop('tagName').toLowerCase(),
|
||||||
attributeType = input.attr('type'),
|
attributeType = input.attr('type'),
|
||||||
suffix = input.attr('name').split('-')[1];
|
suffix = input.attr('name').split('-')[1];
|
||||||
|
|
||||||
|
|
||||||
switch (tagName) {
|
switch (tagName) {
|
||||||
case "textarea":
|
case "textarea":
|
||||||
input.val(firstAnswers.filter("[name$=" + suffix + "]").val());
|
input.val(answers.filter("[name$=" + suffix + "]").val());
|
||||||
break;
|
break;
|
||||||
case "select":
|
case "select":
|
||||||
input.val(firstAnswers.filter("[name$=" + suffix + "]").find(":selected").val()).change();
|
input.val(answers.filter("[name$=" + suffix + "]").find(":selected").val()).change();
|
||||||
break;
|
break;
|
||||||
case "input":
|
case "input":
|
||||||
switch (attributeType) {
|
switch (attributeType) {
|
||||||
case "text":
|
case "text":
|
||||||
case "number":
|
case "number":
|
||||||
input.val(firstAnswers.filter("[name$=" + suffix + "]").val());
|
input.val(answers.filter("[name$=" + suffix + "]").val());
|
||||||
break;
|
break;
|
||||||
case "checkbox":
|
case "checkbox":
|
||||||
case "radio":
|
case "radio":
|
||||||
if (input.attr('value')) {
|
if (input.attr('value')) {
|
||||||
input.prop("checked", firstAnswers.filter("[name$=" + suffix + "][value=" + input.attr('value') + "]").prop("checked"));
|
input.prop("checked", answers.filter("[name$=" + suffix + "][value=" + input.attr('value') + "]").prop("checked"));
|
||||||
} else {
|
} else {
|
||||||
input.prop("checked", firstAnswers.filter("[name$=" + suffix + "]").prop("checked"));
|
input.prop("checked", answers.filter("[name$=" + suffix + "]").prop("checked"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
input.val(firstAnswers.filter("[name$=" + suffix + "]").val());
|
input.val(answers.filter("[name$=" + suffix + "]").val());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
input.val(firstAnswers.filter("[name$=" + suffix + "]").val());
|
input.val(answers.filter("[name$=" + suffix + "]").val());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
questions_toggle_dependent(true);
|
questions_toggle_dependent(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user