forked from CGM_Public/pretix_original
Dialog for cart renewal, async task without page refresh (#5148)
* async_task: deduplicate response handling code
* extend cart without full page reload
* update dialog markup
* fix error response from CartExtend
* refactor asynctask, make sure waitingDialog.show() re-initializes dialog contents
* add cart expiry notification
* add aria references to other dialogs
* improve error handling
* fix error if max_extend=None
* different message for expiring soon and expired carts
* refactor dialog css
* add classes to further dialog elements
* switch extend-cart-dialog and loadingmodal to <dialog>
* Backport simple_block_tag from Django 5.2
* Use simple_block_tag for {% dialog %} tag
* add alertdialog role
* Update src/pretix/static/pretixbase/scss/_dialogs.scss
Co-authored-by: Richard Schreiber <schreiber@rami.io>
* fix mobile dialog styles not being overwritten
* asynctask dialog: prevent close by escape on chrome
* remove dynamic aria-live from #cart-deadline
dynamic aria-live is generally not well supported and as we have the dialog now anyways, we can remove it
* move continue-button to right
* Update src/pretix/static/pretixpresale/js/ui/cart.js
Co-authored-by: Richard Schreiber <schreiber@rami.io>
* Fix CSS for old-style dialog
* fix heading display/level
* align dialogs at the top as they originally were
* fix </div> from merge-conflict
* fix missing grow for dialog-content
* improve cart-extend-button ui
* do not show cart-extend-dialog onload
* improve message if 0 minutes
* do not save messae in session if ajax_dont_redirect
* add ajax_dont_redirect to async_task_check_url
* improve draw_deadline to only update #cart-deadline if necessary
* add renew-confirmation-message
---------
Co-authored-by: Richard Schreiber <schreiber@rami.io>
Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
@@ -495,7 +495,7 @@
|
||||
<form class="text-muted" id="cart-extend-form" data-asynctask data-asynctask-no-redirect
|
||||
method="post" action="{% eventurl request.event "presale:event.cart.extend" cart_namespace=cart_namespace %}">
|
||||
{% csrf_token %}
|
||||
<span id="cart-deadline" data-expires="{{ cart.first_expiry|date:"Y-m-d H:i:sO" }}" data-max-expiry-extend="{{ cart.max_expiry_extend|date:"Y-m-d H:i:sO" }}">
|
||||
<p id="cart-deadline" data-expires="{{ cart.first_expiry|date:"Y-m-d H:i:sO" }}" data-max-expiry-extend="{{ cart.max_expiry_extend|date:"Y-m-d H:i:sO" }}">
|
||||
{% if cart.minutes_left > 0 or cart.seconds_left > 0 %}
|
||||
{% blocktrans trimmed with minutes=cart.minutes_left %}
|
||||
The items in your cart are reserved for you for {{ minutes }} minutes.
|
||||
@@ -503,9 +503,12 @@
|
||||
{% else %}
|
||||
{% trans "The items in your cart are no longer reserved for you. You can still complete your order as long as they’re available." %}
|
||||
{% endif %}
|
||||
</span>
|
||||
<button class="btn btn-link" type="submit" id="cart-extend-button">
|
||||
<i class="fa fa-refresh" aria-hidden="true"></i> {% trans "Extend" %}</button>
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-default" type="submit" id="cart-extend-button" aria-describedby="cart-deadline">
|
||||
<i class="fa fa-refresh" aria-hidden="true"></i> {% trans "Extend reservation" %}
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
||||
{% else %}
|
||||
<p class="sr-only" id="cart-description">{% trans "Overview of your ordered products." %}</p>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{% load rich_text %}
|
||||
{% load money %}
|
||||
<details class="panel {% if open %}panel-primary{% else %}panel-default{% endif %} cart" {% if open %}open{% endif %}>
|
||||
<summary class="panel-heading">
|
||||
<summary class="panel-heading" aria-describedby="cart-deadline">
|
||||
<h2 class="panel-title">
|
||||
<span>
|
||||
<i class="fa fa-shopping-cart" aria-hidden="true"></i>
|
||||
|
||||
@@ -4,18 +4,19 @@
|
||||
{% load escapejson %}
|
||||
{% load icon %}
|
||||
{% load dialog %}
|
||||
<div id="ajaxerr">
|
||||
<div id="ajaxerr" class="modal-wrapper" hidden>
|
||||
</div>
|
||||
<div id="popupmodal" hidden aria-live="polite">
|
||||
<div id="popupmodal" class="modal-wrapper" hidden aria-live="polite" role="dialog"
|
||||
aria-labelledby="popupmodal-title">
|
||||
<div class="modal-card">
|
||||
<div class="modal-card-icon">
|
||||
<i class="fa fa-window-restore big-icon" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="modal-card-content">
|
||||
<div>
|
||||
<h3>
|
||||
<h2 id="popupmodal-title" class="h3">
|
||||
{% trans "We've started the requested process in a new window." %}
|
||||
</h3>
|
||||
</h2>
|
||||
<p class="text">
|
||||
{% trans "If you do not see the new window, we can help you launch it again." %}
|
||||
</p>
|
||||
@@ -32,20 +33,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="loadingmodal" hidden aria-live="polite">
|
||||
<div class="modal-card">
|
||||
<div class="modal-card-icon">
|
||||
<i class="fa fa-cog big-rotating-icon" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="modal-card-content">
|
||||
<h3 id="loadingmodal-label"></h3>
|
||||
<div id="loadingmodal-description">
|
||||
<p class="text"></p>
|
||||
<p class="status">{% trans "If this takes longer than a few minutes, please contact us." %}</p>
|
||||
</div>
|
||||
|
||||
{% dialog "loadingmodal" "" "" icon="cog rotating" %}
|
||||
<p class="status">{% trans "If this takes longer than a few minutes, please contact us." %}</p>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="steps">
|
||||
</div>
|
||||
{% enddialog %}
|
||||
|
||||
{% trans "Please let us know you're still there." as label_cart_extend_dialog %}
|
||||
{% dialog "dialog-cart-extend" label_cart_extend_dialog "" icon="clock-o" alert=true %}
|
||||
<p class="modal-card-confirm"><button class="btn btn-lg btn-primary">{% trans "Continue" %}</button></p>
|
||||
{% enddialog %}
|
||||
|
||||
<dialog id="lightbox-dialog" role="alertdialog" aria-labelledby="lightbox-label">
|
||||
<form method="dialog" class="modal-card">
|
||||
|
||||
@@ -229,11 +229,13 @@ class CartMixin:
|
||||
|
||||
try:
|
||||
first_expiry = min(p.expires for p in positions) if positions else now()
|
||||
max_expiry_extend = min((p.max_extend for p in positions if p.max_extend), default=None)
|
||||
total_seconds_left = max(first_expiry - now(), timedelta()).total_seconds()
|
||||
minutes_left = int(total_seconds_left // 60)
|
||||
seconds_left = int(total_seconds_left % 60)
|
||||
except AttributeError:
|
||||
first_expiry = None
|
||||
max_expiry_extend = None
|
||||
minutes_left = None
|
||||
seconds_left = None
|
||||
|
||||
@@ -250,6 +252,7 @@ class CartMixin:
|
||||
'minutes_left': minutes_left,
|
||||
'seconds_left': seconds_left,
|
||||
'first_expiry': first_expiry,
|
||||
'max_expiry_extend': max_expiry_extend,
|
||||
'is_ordered': bool(order),
|
||||
'itemcount': sum(c.count for c in positions if not c.addon_to),
|
||||
'current_selected_payments': [p for p in self.current_selected_payments(total) if p.get('multi_use_supported')]
|
||||
|
||||
@@ -542,8 +542,14 @@ class CartExtendReservation(EventViewMixin, CartActionMixin, AsyncAction, View):
|
||||
task = extend_cart_reservation
|
||||
known_errortypes = ['CartError']
|
||||
|
||||
def _ajax_response_data(self, value):
|
||||
if isinstance(value, dict):
|
||||
return value
|
||||
else:
|
||||
return {}
|
||||
|
||||
def get_success_message(self, value):
|
||||
if value > 0:
|
||||
if value['success'] > 0:
|
||||
return _('Your cart timeout was extended.')
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
@@ -561,7 +567,7 @@ class CartAdd(EventViewMixin, CartActionMixin, AsyncAction, View):
|
||||
def get_success_message(self, value):
|
||||
return _('The products have been successfully added to your cart.')
|
||||
|
||||
def _ajax_response_data(self):
|
||||
def _ajax_response_data(self, value):
|
||||
cart_id = get_or_create_cart_id(self.request)
|
||||
return {
|
||||
'cart_id': cart_id,
|
||||
|
||||
Reference in New Issue
Block a user