Compare commits

...

3 Commits

Author SHA1 Message Date
Raphael Michel
b2237af4c0 Only show product settings that match quotas 2025-10-06 14:07:38 +02:00
Raphael Michel
43c2f15994 Make submit row sticky on really long forms 2025-10-06 12:50:41 +02:00
Raphael Michel
571724b1f7 Use select2 item input in newly added quotas 2025-10-06 12:45:25 +02:00
6 changed files with 106 additions and 55 deletions

View File

@@ -390,7 +390,8 @@ class QuotaFormSet(I18nInlineFormSet):
use_required_attribute=False,
locales=self.locales,
event=self.event,
items=self.items
items=self.items,
searchable_selection=self.searchable_selection,
)
self.add_fields(form, None)
return form

View File

@@ -487,30 +487,32 @@
{% trans "These settings are optional, if you leave them empty, the default values from the product settings will be used." %}
</p>
{% for f in itemvar_forms %}
{% bootstrap_form_errors f %}
<div class="form-group subevent-itemvar-group">
<label class="col-md-3 control-label" for="id_{{ f.prefix }}-price">
{% if f.variation %}{{ f.item }} {{ f.variation }}{% else %}{{ f.item }}{% endif %}
</label>
<div class="col-md-4">
<label for="{{ f.price.id_for_label }}" class="text-muted">{% trans "Price" %}</label><br>
{% bootstrap_field f.price addon_after=request.event.currency form_group_class="" layout="inline" %}
<div data-itemvar="{{ f.item.id }}{% if f.variation %}-{{ f.variation.id }}{% endif %}">
{% bootstrap_form_errors f %}
<div class="form-group subevent-itemvar-group">
<label class="col-md-3 control-label" for="id_{{ f.prefix }}-price">
{% if f.variation %}{{ f.item }} {{ f.variation }}{% else %}{{ f.item }}{% endif %}
</label>
<div class="col-md-4">
<label for="{{ f.price.id_for_label }}" class="text-muted">{% trans "Price" %}</label><br>
{% bootstrap_field f.price addon_after=request.event.currency form_group_class="" layout="inline" %}
</div>
<div class="col-md-4">
<br>
{% bootstrap_field f.disabled layout="inline" form_group_class="" %}
</div>
</div>
<div class="col-md-4">
<br>
{% bootstrap_field f.disabled layout="inline" form_group_class="" %}
</div>
</div>
<div class="form-group subevent-itemvar-group">
<div class="col-md-4 col-md-offset-3">
<label for="{{ f.rel_available_from.id_for_label }}" class="text-muted">{% trans "Available from" %}</label>
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_from_mode %}<br>
{% bootstrap_field f.rel_available_from form_group_class="" layout="inline" %}
</div>
<div class="col-md-4">
<label for="{{ f.rel_available_until.id_for_label }}" class="text-muted">{% trans "Available until" %}</label>
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_until_mode %}<br>
{% bootstrap_field f.rel_available_until form_group_class="" layout="inline" %}
<div class="form-group subevent-itemvar-group">
<div class="col-md-4 col-md-offset-3">
<label for="{{ f.rel_available_from.id_for_label }}" class="text-muted">{% trans "Available from" %}</label>
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_from_mode %}<br>
{% bootstrap_field f.rel_available_from form_group_class="" layout="inline" %}
</div>
<div class="col-md-4">
<label for="{{ f.rel_available_until.id_for_label }}" class="text-muted">{% trans "Available until" %}</label>
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_until_mode %}<br>
{% bootstrap_field f.rel_available_until form_group_class="" layout="inline" %}
</div>
</div>
</div>
{% endfor %}
@@ -625,7 +627,7 @@
{% endif %}
{% endfor %}
</fieldset>
<div class="form-group submit-group">
<div class="form-group submit-group submit-group-sticky">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>

View File

@@ -363,7 +363,7 @@
</div>
{% endif %}
</fieldset>
<div class="form-group submit-group">
<div class="form-group submit-group submit-group-sticky">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>

View File

@@ -130,30 +130,32 @@
{% trans "These settings are optional, if you leave them empty, the default values from the product settings will be used." %}
</p>
{% for f in itemvar_forms %}
{% bootstrap_form_errors f %}
<div class="form-group subevent-itemvar-group">
<label class="col-md-3 control-label" for="id_{{ f.prefix }}-price">
{% if f.variation %}{{ f.item }} {{ f.variation }}{% else %}{{ f.item }}{% endif %}
</label>
<div class="col-md-4">
<label for="{{ f.price.id_for_label }}" class="text-muted">{% trans "Price" %}</label><br>
{% bootstrap_field f.price addon_after=request.event.currency form_group_class="" layout="inline" %}
<div data-itemvar="{{ f.item.id }}{% if f.variation %}-{{ f.variation.id }}{% endif %}">
{% bootstrap_form_errors f %}
<div class="form-group subevent-itemvar-group">
<label class="col-md-3 control-label" for="id_{{ f.prefix }}-price">
{% if f.variation %}{{ f.item }} {{ f.variation }}{% else %}{{ f.item }}{% endif %}
</label>
<div class="col-md-4">
<label for="{{ f.price.id_for_label }}" class="text-muted">{% trans "Price" %}</label><br>
{% bootstrap_field f.price addon_after=request.event.currency form_group_class="" layout="inline" %}
</div>
<div class="col-md-4">
<br>
{% bootstrap_field f.disabled layout="inline" form_group_class="" %}
</div>
</div>
<div class="col-md-4">
<br>
{% bootstrap_field f.disabled layout="inline" form_group_class="" %}
</div>
</div>
<div class="form-group subevent-itemvar-group">
<div class="col-md-4 col-md-offset-3">
<label for="{{ f.available_from.id_for_label }}" class="text-muted">{% trans "Available from" %}</label>
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_from_mode %}<br>
{% bootstrap_field f.available_from form_group_class="foo" layout="inline" %}
</div>
<div class="col-md-4">
<label for="{{ f.available_until.id_for_label }}" class="text-muted">{% trans "Available until" %}</label>
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_until_mode %}<br>
{% bootstrap_field f.available_until form_group_class="" layout="inline" %}
<div class="form-group subevent-itemvar-group">
<div class="col-md-4 col-md-offset-3">
<label for="{{ f.available_from.id_for_label }}" class="text-muted">{% trans "Available from" %}</label>
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_from_mode %}<br>
{% bootstrap_field f.available_from form_group_class="foo" layout="inline" %}
</div>
<div class="col-md-4">
<label for="{{ f.available_until.id_for_label }}" class="text-muted">{% trans "Available until" %}</label>
{% include "pretixcontrol/subevents/fragment_unavail_mode_indicator.html" with mode=f.available_until_mode %}<br>
{% bootstrap_field f.available_until form_group_class="" layout="inline" %}
</div>
</div>
</div>
{% endfor %}
@@ -282,7 +284,7 @@
</div>
{% endif %}
</div>
<div class="form-group submit-group">
<div class="form-group submit-group submit-group-sticky">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>

View File

@@ -26,6 +26,7 @@ $(document).on("pretix:bind-forms", function () {
}
}
// RRule editor
function rrule_preview() {
var ruleset = new rrule.RRuleSet();
@@ -121,7 +122,14 @@ $(document).on("pretix:bind-forms", function () {
});
}
}
$("#rrule-formset").on("change keydown keyup keypress dp.change", "input, select", function () {
rrule_preview();
});
rrule_preview();
$("#rrule-formset").on("formAdded", "div", function (event) {rrule_bind_form($(event.target)); });
// Timeslot editor
$("#subevent_add_many_slots_go").on("click", function () {
$("#time-formset [data-formset-form]").each(function () {
var tf = $(this).find("[name$=time_from]").val()
@@ -167,13 +175,45 @@ $(document).on("pretix:bind-forms", function () {
$(this).addClass("hidden");
});
$("#rrule-formset").on("change keydown keyup keypress dp.change", "input, select", function () {
rrule_preview();
});
rrule_preview();
// Hide config for products that are not for sale
function quota_form_handlers(el) {
// searchable_selection = True
el.find('[id^="id_quotas-"]').on("select2:select select2:unselect", () => {
update_item_visibility();
});
// searchable_selection = False
el.find('input[id^="id_quotas-"][id*=itemvars_]').on("change", () => {
update_item_visibility();
});
}
function update_item_visibility() {
const itemvars = [];
$("#rrule-formset").on("formAdded", "div", function (event) { rrule_bind_form($(event.target)); });
// searchable_selection = True
$("select[id^=id_quotas-][id$=-itemvars]").filter((idx, el) => {
return !$(el).closest('[data-formset-form]').is('[data-formset-form-deleted]');
}).each((_, e) => itemvars.push(...$(e).val()));
// searchable_selection = False
$("input[id^=id_quotas-][id*=itemvars_]:checked").filter((idx, el) => {
return !$(el).closest('[data-formset-form]').is('[data-formset-form-deleted]');
}).each((_, e) => itemvars.push($(e).val()));
$("div[data-itemvar]").each(function (idx, e) {
const el = $(e);
el.prop("hidden", !itemvars.includes(el.attr("data-itemvar")) && !el.find(".has-error, .alert-danger").length);
});
}
$('[data-formset-prefix="quotas"]').on("formDeleted", "div", () => {
update_item_visibility();
}).on("formAdded", "div", (event) => {
quota_form_handlers($(event.target));
update_item_visibility();
})
quota_form_handlers($("body"));
update_item_visibility();
// Auto-set name of check-in list
var $namef = $("input[id^=id_name]").first();
var lastValue = $namef.val();
$namef.change(function () {

View File

@@ -95,6 +95,12 @@ div[data-formset-body], div[data-formset-form], div[data-nested-formset-form], d
}
}
.submit-group-sticky {
position: sticky;
bottom: 0;
z-index: 100;
}
.panel .form-group:last-child {
margin-bottom: 0;
}