mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Improve UI to configure unavailable items handling (Z#23131828) (#3739)
* start impl of unavailability modes ui * add db migration * use new widget for more fields * improve contrast * use new widget for hide_without_voucher field * improved wording * rebase migration * undo changes to require_membership_hidden * code formatting * move unavail_reason logic around * enforce consistent state of hide_without_voucher / require_voucher * annotate unavailability info in get_grouped_items * remove MSIE6 compat * add unavailability reasons to widget * remove test output * Apply suggestions from code review text improvements Co-authored-by: Richard Schreiber <schreiber@rami.io> * add css fix for jumping items due to tooltip * dynamically retrieve unavailability reason message * widget: simplify logic conditions * add available_{from,until}_mode to api and api docs * rebase migration * rebase migration * add unavailable_*_mode to ItemVariation * add available_*_mode to API docs for items * fix wrong reference * fix test cases * add available_*_mode to item variation form * apply unavailability modes to subevents and variations (presale) * /o\ * apply unavailability modes to subevents and variations (widget) * display unavailability mode in subevent product settings * fix widget test * fix api item tests * copy available_*_mode when copying an item * Apply suggestions from code review Co-authored-by: Raphael Michel <michel@rami.io> * Add unavail mode indicator to bulk create and edit forms --------- Co-authored-by: Richard Schreiber <schreiber@rami.io> Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
@@ -100,6 +100,16 @@ input[type=number]::-webkit-outer-spin-button {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.btn-primary-if-active {
|
||||
@include button-variant($btn-default-color, $btn-default-bg, $btn-default-border);
|
||||
box-shadow: 0px 0px 0px 1px #cccccc inset;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.active {
|
||||
@include button-variant($btn-primary-color, $btn-primary-bg, $btn-primary-border);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-invisible {
|
||||
background: transparent;
|
||||
border: transparent;
|
||||
|
||||
@@ -908,6 +908,10 @@ tbody th {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.btn-group .btn:not(:first-child) {
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
@import "../../pretixbase/scss/_rtl.scss";
|
||||
@import "../../bootstrap/scss/_rtl.scss";
|
||||
@import "_rtl.scss";
|
||||
|
||||
@@ -31,7 +31,10 @@ var strings = {
|
||||
'tax_incl_mixed': django.pgettext('widget', 'incl. taxes'),
|
||||
'tax_plus_mixed': django.pgettext('widget', 'plus taxes'),
|
||||
'quota_left': django.pgettext('widget', 'currently available: %s'),
|
||||
'voucher_required': django.pgettext('widget', 'Only available with a voucher'),
|
||||
'unavailable_require_voucher': django.pgettext('widget', 'Only available with a voucher'),
|
||||
'unavailable_available_from': django.pgettext('widget', 'Not yet available'),
|
||||
'unavailable_available_until': django.pgettext('widget', 'Not available anymore'),
|
||||
'unavailable_active': django.pgettext('widget', 'Currently not available'),
|
||||
'order_min': django.pgettext('widget', 'minimum amount to order: %s'),
|
||||
'exit': django.pgettext('widget', 'Close ticket shop'),
|
||||
'loading_error': django.pgettext('widget', 'The ticket shop could not be loaded.'),
|
||||
@@ -118,17 +121,8 @@ var getISOWeeks = function (y) {
|
||||
|
||||
/* HTTP API Call helpers */
|
||||
var api = {
|
||||
'_getXHR': function () {
|
||||
try {
|
||||
return new window.XMLHttpRequest();
|
||||
} catch (e) {
|
||||
// explicitly bubble up the exception if not found
|
||||
return new window.ActiveXObject('Microsoft.XMLHTTP');
|
||||
}
|
||||
},
|
||||
|
||||
'_getJSON': function (endpoint, callback, err_callback) {
|
||||
var xhr = api._getXHR();
|
||||
var xhr = new window.XMLHttpRequest();
|
||||
xhr.open("GET", endpoint, true);
|
||||
xhr.onload = function (e) {
|
||||
if (xhr.readyState === 4) {
|
||||
@@ -160,7 +154,7 @@ var api = {
|
||||
return encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value);
|
||||
}).join('&');
|
||||
|
||||
var xhr = api._getXHR();
|
||||
var xhr = new window.XMLHttpRequest();
|
||||
xhr.open("POST", endpoint, true);
|
||||
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
||||
xhr.onload = function (e) {
|
||||
@@ -199,22 +193,27 @@ var widget_id = makeid(16);
|
||||
/* Vue Components */
|
||||
Vue.component('availbox', {
|
||||
template: ('<div class="pretix-widget-availability-box">'
|
||||
+ '<div class="pretix-widget-availability-unavailable" v-if="require_voucher">'
|
||||
+ '<small><a @click.prevent.stop="focus_voucher_field" role="button">' + strings.voucher_required + '</a></small>'
|
||||
+ '<div class="pretix-widget-availability-unavailable"'
|
||||
+ ' v-if="item.current_unavailability_reason === \'require_voucher\'">'
|
||||
+ '<small><a @click.prevent.stop="focus_voucher_field" role="button">{{unavailability_reason_message}}</a></small>'
|
||||
+ '</div>'
|
||||
+ '<div class="pretix-widget-availability-unavailable"'
|
||||
+ ' v-if="!require_voucher && avail[0] < 100 && avail[0] > 10">'
|
||||
+ ' v-else-if="unavailability_reason_message">'
|
||||
+ '<small>{{unavailability_reason_message}}</small>'
|
||||
+ '</div>'
|
||||
+ '<div class="pretix-widget-availability-unavailable"'
|
||||
+ ' v-else-if="avail[0] < 100 && avail[0] > 10">'
|
||||
+ strings.reserved
|
||||
+ '</div>'
|
||||
+ '<div class="pretix-widget-availability-gone" '
|
||||
+ ' v-if="!require_voucher && avail[0] <= 10">'
|
||||
+ ' v-else-if="avail[0] <= 10">'
|
||||
+ strings.sold_out
|
||||
+ '</div>'
|
||||
+ '<div class="pretix-widget-waiting-list-link"'
|
||||
+ ' v-if="waiting_list_show">'
|
||||
+ '<a :href="waiting_list_url" target="_blank" @click="$root.open_link_in_frame">' + strings.waiting_list + '</a>'
|
||||
+ '</div>'
|
||||
+ '<div class="pretix-widget-availability-available" v-if="!require_voucher && avail[0] === 100">'
|
||||
+ '<div class="pretix-widget-availability-available" v-if="!unavailability_reason_message && avail[0] === 100">'
|
||||
+ '<label class="pretix-widget-item-count-single-label pretix-widget-btn-checkbox" v-if="order_max === 1 && $root.single_item_select == \'button\'">'
|
||||
+ '<input type="checkbox" value="1" :checked="!!amount_selected" @change="amount_selected = $event.target.checked" :name="input_name"'
|
||||
+ ' v-bind:aria-label="label_select_item"'
|
||||
@@ -255,8 +254,12 @@ Vue.component('availbox', {
|
||||
'pretix-widget-item-count-group': !this.$root.use_native_spinners
|
||||
}
|
||||
},
|
||||
require_voucher: function () {
|
||||
return this.item.require_voucher && !this.$root.voucher_code
|
||||
unavailability_reason_message: function () {
|
||||
var reason = this.item.current_unavailability_reason || this.variation.current_unavailability_reason;
|
||||
if (reason) {
|
||||
return strings["unavailable_" + reason] || reason;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
amount_selected: {
|
||||
cache: false,
|
||||
|
||||
Reference in New Issue
Block a user