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:
@@ -5,74 +5,94 @@ var async_task_check_url = null;
|
||||
var async_task_old_url = null;
|
||||
var async_task_is_download = false;
|
||||
var async_task_is_long = false;
|
||||
var async_task_dont_redirect = false;
|
||||
|
||||
function async_task_check() {
|
||||
var async_task_status_messages = {
|
||||
long_task_started: gettext(
|
||||
'Your request is currently being processed. Depending on the size of your event, this might take up to ' +
|
||||
'a few minutes.'
|
||||
),
|
||||
long_task_pending: gettext(
|
||||
'Your request has been queued on the server and will soon be ' +
|
||||
'processed.'
|
||||
),
|
||||
short_task: gettext(
|
||||
'Your request arrived on the server but we still wait for it to be ' +
|
||||
'processed. If this takes longer than two minutes, please contact us or go ' +
|
||||
'back in your browser and try again.'
|
||||
)
|
||||
};
|
||||
|
||||
function async_task_schedule_check(context, timeout) {
|
||||
"use strict";
|
||||
$.ajax(
|
||||
{
|
||||
'type': 'GET',
|
||||
'url': async_task_check_url,
|
||||
'success': async_task_check_callback,
|
||||
'error': async_task_check_error,
|
||||
'context': this,
|
||||
'dataType': 'json'
|
||||
async_task_timeout = window.setTimeout(function() {
|
||||
$.ajax(
|
||||
{
|
||||
'type': 'GET',
|
||||
'url': async_task_check_url,
|
||||
'success': async_task_check_callback,
|
||||
'error': async_task_check_error,
|
||||
'context': context,
|
||||
'dataType': 'json'
|
||||
}
|
||||
);
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
function async_task_on_success(data) {
|
||||
"use strict";
|
||||
if ((async_task_is_download && data.success) || async_task_dont_redirect) {
|
||||
waitingDialog.hide();
|
||||
if (location.href.indexOf("async_id") !== -1) {
|
||||
history.replaceState({}, "pretix", async_task_old_url);
|
||||
}
|
||||
);
|
||||
}
|
||||
if (!async_task_dont_redirect)
|
||||
location.href = data.redirect;
|
||||
$(this).trigger('pretix:async-task-success', data);
|
||||
}
|
||||
|
||||
function async_task_check_callback(data, textStatus, jqXHR) {
|
||||
"use strict";
|
||||
if (data.ready && data.redirect) {
|
||||
if (async_task_is_download && data.success) {
|
||||
waitingDialog.hide();
|
||||
if (location.href.indexOf("async_id") !== -1) {
|
||||
history.replaceState({}, "pretix", async_task_old_url);
|
||||
}
|
||||
}
|
||||
location.href = data.redirect;
|
||||
async_task_on_success.call(this, data);
|
||||
return;
|
||||
} else if (typeof data.percentage === "number") {
|
||||
$("#loadingmodal .progress").show();
|
||||
$("#loadingmodal .progress .progress-bar").css("width", data.percentage + "%");
|
||||
if (typeof data.steps === "object" && Array.isArray(data.steps)) {
|
||||
var $steps = $("#loadingmodal .steps");
|
||||
$steps.html("").show()
|
||||
for (var step of data.steps) {
|
||||
$steps.append(
|
||||
$("<span>").addClass("fa fa-fw")
|
||||
.toggleClass("fa-check text-success", step.done)
|
||||
.toggleClass("fa-cog fa-spin text-muted", !step.done)
|
||||
).append(
|
||||
$("<span>").text(step.label)
|
||||
).append(
|
||||
$("<br>")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
async_task_timeout = window.setTimeout(async_task_check, 250);
|
||||
|
||||
if (typeof data.percentage === "number") {
|
||||
waitingDialog.setProgress(data.percentage);
|
||||
}
|
||||
if (typeof data.steps === "object" && Array.isArray(data.steps)) {
|
||||
waitingDialog.setSteps(data.steps);
|
||||
}
|
||||
async_task_schedule_check(this, 250);
|
||||
|
||||
async_task_update_status(data);
|
||||
}
|
||||
|
||||
function async_task_update_status(data) {
|
||||
if (async_task_is_long) {
|
||||
if (data.started) {
|
||||
$("#loadingmodal p.status").text(gettext(
|
||||
'Your request is currently being processed. Depending on the size of your event, this might take up to ' +
|
||||
'a few minutes.'
|
||||
));
|
||||
waitingDialog.setStatus(async_task_status_messages.long_task_started);
|
||||
} else {
|
||||
$("#loadingmodal p.status").text(gettext(
|
||||
'Your request has been queued on the server and will soon be ' +
|
||||
'processed.'
|
||||
));
|
||||
waitingDialog.setStatus(async_task_status_messages.long_task_pending);
|
||||
}
|
||||
} else {
|
||||
$("#loadingmodal p.status").text(gettext(
|
||||
'Your request arrived on the server but we still wait for it to be ' +
|
||||
'processed. If this takes longer than two minutes, please contact us or go ' +
|
||||
'back in your browser and try again.'
|
||||
));
|
||||
waitingDialog.setStatus(async_task_status_messages.short_task);
|
||||
}
|
||||
}
|
||||
|
||||
function async_task_replace_page(target, new_html) {
|
||||
"use strict";
|
||||
waitingDialog.hide();
|
||||
$(target).html(new_html);
|
||||
setup_basics($(target));
|
||||
form_handlers($(target));
|
||||
setup_collapsible_details($(target));
|
||||
window.setTimeout(function () { $(window).scrollTop(0) }, 200)
|
||||
$(document).trigger("pretix:bind-forms");
|
||||
}
|
||||
|
||||
function async_task_check_error(jqXHR, textStatus, errorThrown) {
|
||||
"use strict";
|
||||
var respdom = $(jqXHR.responseText);
|
||||
@@ -80,16 +100,10 @@ function async_task_check_error(jqXHR, textStatus, errorThrown) {
|
||||
if (respdom.filter('form') && (respdom.filter('.has-error') || respdom.filter('.alert-danger'))) {
|
||||
// This is a failed form validation, let's just use it
|
||||
$("body").data('ajaxing', false);
|
||||
waitingDialog.hide();
|
||||
$("body").html(jqXHR.responseText.substring(
|
||||
async_task_replace_page("body", jqXHR.responseText.substring(
|
||||
jqXHR.responseText.indexOf("<body"),
|
||||
jqXHR.responseText.indexOf("</body")
|
||||
));
|
||||
setup_basics($("body"));
|
||||
form_handlers($("body"));
|
||||
setup_collapsible_details($("body"));
|
||||
window.setTimeout(function () { $(window).scrollTop(0) }, 200)
|
||||
$(document).trigger("pretix:bind-forms");
|
||||
} else if (c.length > 0) {
|
||||
// This is some kind of 500/404/403 page, show it in an overlay
|
||||
$("body").data('ajaxing', false);
|
||||
@@ -105,9 +119,9 @@ function async_task_check_error(jqXHR, textStatus, errorThrown) {
|
||||
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status));
|
||||
} else {
|
||||
// 500 can be an application error or overload in some cases :(
|
||||
$("#loadingmodal p.status").text(gettext('We currently cannot reach the server, but we keep trying.' +
|
||||
' Last error code: {code}').replace(/\{code\}/, jqXHR.status));
|
||||
async_task_timeout = window.setTimeout(async_task_check, 5000);
|
||||
waitingDialog.setStatus(gettext('We currently cannot reach the server, but we keep trying.' +
|
||||
' Last error code: {code}').replace(/\{code\}/, jqXHR.status));
|
||||
async_task_schedule_check(this, 5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,38 +130,19 @@ function async_task_callback(data, jqXHR, status) {
|
||||
"use strict";
|
||||
$("body").data('ajaxing', false);
|
||||
if (data.redirect) {
|
||||
if (async_task_is_download && data.success) {
|
||||
waitingDialog.hide();
|
||||
if (location.href.indexOf("async_id") !== -1) {
|
||||
history.replaceState({}, "pretix", async_task_old_url);
|
||||
}
|
||||
}
|
||||
location.href = data.redirect;
|
||||
async_task_on_success.call(this, data);
|
||||
return;
|
||||
}
|
||||
async_task_id = data.async_id;
|
||||
async_task_check_url = data.check_url;
|
||||
async_task_timeout = window.setTimeout(async_task_check, 100);
|
||||
|
||||
if (async_task_is_long) {
|
||||
if (data.started) {
|
||||
$("#loadingmodal p.status").text(gettext(
|
||||
'Your request is currently being processed. Depending on the size of your event, this might take up to ' +
|
||||
'a few minutes.'
|
||||
));
|
||||
} else {
|
||||
$("#loadingmodal p.status").text(gettext(
|
||||
'Your request has been queued on the server and will soon be ' +
|
||||
'processed.'
|
||||
));
|
||||
}
|
||||
} else {
|
||||
$("#loadingmodal p.status").text(gettext(
|
||||
'Your request arrived on the server but we still wait for it to be ' +
|
||||
'processed. If this takes longer than two minutes, please contact us or go ' +
|
||||
'back in your browser and try again.'
|
||||
));
|
||||
var check_url = new URL(data.check_url);
|
||||
if (async_task_dont_redirect) {
|
||||
check_url.searchParams.set('ajax_dont_redirect', '1');
|
||||
}
|
||||
async_task_id = data.async_id;
|
||||
async_task_check_url = check_url.toString();
|
||||
async_task_schedule_check(this, 100);
|
||||
|
||||
async_task_update_status(data);
|
||||
|
||||
if (location.href.indexOf("async_id") === -1) {
|
||||
history.pushState({}, "Waiting", async_task_check_url.replace(/ajax=1/, ''));
|
||||
}
|
||||
@@ -156,48 +151,34 @@ function async_task_callback(data, jqXHR, status) {
|
||||
function async_task_error(jqXHR, textStatus, errorThrown) {
|
||||
"use strict";
|
||||
$("body").data('ajaxing', false);
|
||||
waitingDialog.hide();
|
||||
if (textStatus === "timeout") {
|
||||
alert(gettext("The request took too long. Please try again."));
|
||||
waitingDialog.hide();
|
||||
} else if (jqXHR.responseText.indexOf('<html') > 0) {
|
||||
var respdom = $(jqXHR.responseText);
|
||||
var c = respdom.filter('.container');
|
||||
if (respdom.filter('form') && (respdom.filter('.has-error') || respdom.filter('.alert-danger'))) {
|
||||
// This is a failed form validation, let's just use it
|
||||
waitingDialog.hide();
|
||||
|
||||
if (respdom.filter('#page-wrapper') && $('#page-wrapper').length) {
|
||||
$("#page-wrapper").html(respdom.find("#page-wrapper").html());
|
||||
setup_basics($("#page-wrapper"));
|
||||
form_handlers($("#page-wrapper"));
|
||||
setup_collapsible_details($("#page-wrapper"));
|
||||
$(document).trigger("pretix:bind-forms");
|
||||
window.setTimeout(function () { $(window).scrollTop(0) }, 200)
|
||||
async_task_replace_page("#page-wrapper", respdom.find("#page-wrapper").html());
|
||||
} else {
|
||||
$("body").html(jqXHR.responseText.substring(
|
||||
async_task_replace_page("body", jqXHR.responseText.substring(
|
||||
jqXHR.responseText.indexOf("<body"),
|
||||
jqXHR.responseText.indexOf("</body")
|
||||
));
|
||||
setup_basics($("body"));
|
||||
form_handlers($("body"));
|
||||
setup_collapsible_details($("body"));
|
||||
$(document).trigger("pretix:bind-forms");
|
||||
window.setTimeout(function () { $(window).scrollTop(0) }, 200)
|
||||
}
|
||||
|
||||
} else if (c.length > 0) {
|
||||
waitingDialog.hide();
|
||||
// This is some kind of 500/404/403 page, show it in an overlay
|
||||
ajaxErrDialog.show(c.first().html());
|
||||
} else {
|
||||
waitingDialog.hide();
|
||||
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status));
|
||||
}
|
||||
} else {
|
||||
if (jqXHR.status >= 400 && jqXHR.status < 500) {
|
||||
waitingDialog.hide();
|
||||
alert(gettext('An error of type {code} occurred.').replace(/\{code\}/, jqXHR.status));
|
||||
} else {
|
||||
waitingDialog.hide();
|
||||
alert(gettext('We currently cannot reach the server. Please try again. ' +
|
||||
'Error code: {code}').replace(/\{code\}/, jqXHR.status));
|
||||
}
|
||||
@@ -221,28 +202,26 @@ $(function () {
|
||||
}
|
||||
async_task_id = null;
|
||||
async_task_is_download = $(this).is("[data-asynctask-download]");
|
||||
async_task_dont_redirect = $(this).is("[data-asynctask-no-redirect]");
|
||||
async_task_is_long = $(this).is("[data-asynctask-long]");
|
||||
async_task_old_url = location.href;
|
||||
$("body").data('ajaxing', true);
|
||||
if ($(this).is("[data-asynctask-headline]")) {
|
||||
waitingDialog.show($(this).attr("data-asynctask-headline"));
|
||||
} else {
|
||||
waitingDialog.show(gettext('We are processing your request …'));
|
||||
}
|
||||
if ($(this).is("[data-asynctask-text]")) {
|
||||
$("#loadingmodal p.text").text($(this).attr("data-asynctask-text")).show();
|
||||
} else {
|
||||
$("#loadingmodal p.text").hide();
|
||||
}
|
||||
$("#loadingmodal p.status").text(gettext(
|
||||
'We are currently sending your request to the server. If this takes longer ' +
|
||||
'than one minute, please check your internet connection and then reload ' +
|
||||
'this page and try again.'
|
||||
));
|
||||
waitingDialog.show(
|
||||
$(this).attr("data-asynctask-headline") || gettext('We are processing your request …'),
|
||||
$(this).attr("data-asynctask-text") || '',
|
||||
gettext(
|
||||
'We are currently sending your request to the server. If this takes longer ' +
|
||||
'than one minute, please check your internet connection and then reload ' +
|
||||
'this page and try again.'
|
||||
)
|
||||
);
|
||||
|
||||
var action = this.action;
|
||||
var formData = new FormData(this);
|
||||
formData.append('ajax', '1');
|
||||
if (async_task_dont_redirect) {
|
||||
formData.append('ajax_dont_redirect', '1');
|
||||
}
|
||||
if (submitter && submitter.name) {
|
||||
formData.append(submitter.name, submitter.value);
|
||||
}
|
||||
@@ -275,21 +254,66 @@ $(function () {
|
||||
}, 10);
|
||||
}
|
||||
}, false);
|
||||
|
||||
$("#ajaxerr").on("click", ".ajaxerr-close", ajaxErrDialog.hide);
|
||||
$("#loadingmodal").on("cancel", function() {
|
||||
return false;
|
||||
});
|
||||
$("#loadingmodal").prop("closedBy", "none");
|
||||
});
|
||||
|
||||
var waitingDialog = {
|
||||
show: function (message) {
|
||||
show: function (title, text, status) {
|
||||
"use strict";
|
||||
$("#loadingmodal h3").html(message);
|
||||
$("#loadingmodal .progress").hide();
|
||||
$("#loadingmodal .steps").hide();
|
||||
$("body").addClass("loading");
|
||||
$("#loadingmodal").removeAttr("hidden");
|
||||
this.setTitle(title);
|
||||
this.setText(text);
|
||||
this.setStatus(status || gettext('If this takes longer than a few minutes, please contact us.'));
|
||||
this.setProgress(null);
|
||||
this.setSteps(null);
|
||||
document.getElementById("loadingmodal").showModal();
|
||||
},
|
||||
hide: function () {
|
||||
"use strict";
|
||||
$("body").removeClass("loading");
|
||||
$("#loadingmodal").attr("hidden", true);
|
||||
document.getElementById("loadingmodal").close();
|
||||
},
|
||||
setTitle: function(title) {
|
||||
$("#loadingmodal .modal-card-title").text(title);
|
||||
},
|
||||
setStatus: function(statusText) {
|
||||
$("#loadingmodal p.status").text(statusText);
|
||||
},
|
||||
setText: function(text) {
|
||||
if (text)
|
||||
$("#loadingmodal .modal-card-description").text(text).show();
|
||||
else
|
||||
$("#loadingmodal .modal-card-description").hide();
|
||||
},
|
||||
setProgress: function(percentage) {
|
||||
if (typeof percentage === 'number') {
|
||||
$("#loadingmodal .progress").show();
|
||||
$("#loadingmodal .progress .progress-bar").css("width", percentage + "%");
|
||||
} else {
|
||||
$("#loadingmodal .progress").hide();
|
||||
}
|
||||
},
|
||||
setSteps: function(steps) {
|
||||
var $steps = $("#loadingmodal .steps");
|
||||
if (steps) {
|
||||
$steps.html("").show()
|
||||
for (var step of steps) {
|
||||
$steps.append(
|
||||
$("<span>").addClass("fa fa-fw")
|
||||
.toggleClass("fa-check text-success", step.done)
|
||||
.toggleClass("fa-cog fa-spin text-muted", !step.done)
|
||||
).append(
|
||||
$("<span>").text(step.label)
|
||||
).append(
|
||||
$("<br>")
|
||||
)
|
||||
}
|
||||
} else {
|
||||
$steps.hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -299,10 +323,10 @@ var ajaxErrDialog = {
|
||||
$("#ajaxerr").html(c);
|
||||
$("#ajaxerr .links").html("<a class='btn btn-default ajaxerr-close'>"
|
||||
+ gettext("Close message") + "</a>");
|
||||
$("body").addClass("ajaxerr");
|
||||
$("body").addClass("ajaxerr has-modal-dialog");
|
||||
},
|
||||
hide: function () {
|
||||
"use strict";
|
||||
$("body").removeClass("ajaxerr");
|
||||
}
|
||||
$("body").removeClass("ajaxerr has-modal-dialog");
|
||||
},
|
||||
};
|
||||
|
||||
174
src/pretix/static/pretixbase/scss/_dialogs.scss
Normal file
174
src/pretix/static/pretixbase/scss/_dialogs.scss
Normal file
@@ -0,0 +1,174 @@
|
||||
/* Modal dialogs using HTML5 dialog tags for accessibility */
|
||||
dialog.modal-card {
|
||||
border: none;
|
||||
width: 80%;
|
||||
max-width: 43em;
|
||||
padding: 0;
|
||||
margin-top: 60px;
|
||||
box-shadow: 0 7px 14px 0 rgba(78, 50, 92, 0.1),0 3px 6px 0 rgba(0,0,0,.07);
|
||||
background: white;
|
||||
border-radius: $border-radius-large;
|
||||
|
||||
opacity: 0;
|
||||
transition: opacity .5s allow-discrete;
|
||||
}
|
||||
.modal-card-inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-content: stretch;
|
||||
}
|
||||
dialog.modal-card .modal-card-icon {
|
||||
background: $brand-primary;
|
||||
font-size: 2em;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 3px;
|
||||
.rotating {
|
||||
-webkit-animation: fa-spin 8s infinite linear;
|
||||
animation: fa-spin 8s infinite linear;
|
||||
}
|
||||
}
|
||||
dialog.modal-card .modal-card-content {
|
||||
padding: 1.5em;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.modal-card-content>*:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.modal-card-content>*:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.modal-card-confirm {
|
||||
margin-top: 2em;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 1em;
|
||||
align-items: center;
|
||||
}
|
||||
.modal-card-confirm-spread {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
dialog::backdrop {
|
||||
background-color: rgba(255, 255, 255, .5);
|
||||
opacity: 0;
|
||||
transition: opacity .5s allow-discrete;
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
dialog[open], dialog[open]::backdrop {
|
||||
opacity: 1;
|
||||
}
|
||||
@starting-style {
|
||||
dialog[open], dialog[open]::backdrop {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: $screen-sm-min) {
|
||||
dialog.modal-card:has(.modal-card-icon) .modal-card-inner {
|
||||
flex-direction: row;
|
||||
}
|
||||
dialog.modal-card .modal-card-content {
|
||||
padding: 2em;
|
||||
}
|
||||
dialog.modal-card .modal-card-icon {
|
||||
font-size: 4em;
|
||||
padding: 6px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.shake-once {
|
||||
animation: shake .2s;
|
||||
transform: translate3d(0, 0, 0);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0% { transform: skewX(0deg); }
|
||||
20% { transform: skewX(-5deg); }
|
||||
40% { transform: skewX(5deg); }
|
||||
60% { transform: skewX(-5deg); }
|
||||
80% { transform: skewX(5deg); }
|
||||
100% { transform: skewX(0deg); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Legacy dialogs (still used for #ajaxerr and #popupmodal) */
|
||||
body.has-modal-dialog .container, body.has-modal-dialog #wrapper {
|
||||
-webkit-filter: blur(2px);
|
||||
-moz-filter: blur(2px);
|
||||
-ms-filter: blur(2px);
|
||||
-o-filter: blur(2px);
|
||||
filter: blur(2px);
|
||||
}
|
||||
|
||||
.modal-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(255, 255, 255, .7);
|
||||
z-index: 900000;
|
||||
padding: 10px;
|
||||
.modal-card {
|
||||
margin: 50px auto 0;
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
max-height: calc(100vh - 100px);
|
||||
overflow-y: auto;
|
||||
background: white;
|
||||
border-radius: $border-radius-large;
|
||||
box-shadow: 0 7px 14px 0 rgba(78, 50, 92, 0.1),0 3px 6px 0 rgba(0,0,0,.07);
|
||||
padding: 20px;
|
||||
min-height: 160px;
|
||||
border: 0;
|
||||
|
||||
.modal-card-icon {
|
||||
float: left;
|
||||
width: 150px;
|
||||
text-align: center;
|
||||
.big-icon {
|
||||
margin-top: 10px;
|
||||
font-size: 100px;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
.modal-card-content {
|
||||
margin-left: 160px;
|
||||
text-align: left;
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.modal-wrapper .modal-card {
|
||||
margin: 25px auto 0;
|
||||
max-height: calc(100vh - 50px - 20px);
|
||||
.modal-card-icon {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
.modal-card-content {
|
||||
text-align: center;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ajaxerr {
|
||||
background: rgba(236, 236, 236, .9);
|
||||
|
||||
.big-icon {
|
||||
margin-top: 50px;
|
||||
font-size: 200px;
|
||||
color: $brand-primary;
|
||||
}
|
||||
}
|
||||
@@ -263,117 +263,3 @@ svg.svg-icon {
|
||||
@include table-row-variant('warning', var(--pretix-brand-warning-lighten-40), var(--pretix-brand-warning-lighten-35));
|
||||
@include table-row-variant('danger', var(--pretix-brand-danger-lighten-30), var(--pretix-brand-danger-lighten-25));
|
||||
|
||||
|
||||
|
||||
|
||||
dialog {
|
||||
border: none;
|
||||
width: 80%;
|
||||
max-width: 43em;
|
||||
padding: 0;
|
||||
box-shadow: 0 7px 14px 0 rgba(78, 50, 92, 0.1),0 3px 6px 0 rgba(0,0,0,.07);
|
||||
background: white;
|
||||
border-radius: $border-radius-large;
|
||||
|
||||
opacity: 0;
|
||||
transition: opacity .5s allow-discrete;
|
||||
|
||||
.modal-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-content: stretch;
|
||||
}
|
||||
.modal-card-icon {
|
||||
background: $brand-primary;
|
||||
font-size: 2em;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 3px;
|
||||
}
|
||||
.modal-card-content {
|
||||
padding: 1.5em;
|
||||
}
|
||||
.modal-card-content>*:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.modal-card-content>*:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.modal-card-confirm {
|
||||
margin-top: 2em;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 1em;
|
||||
align-items: center;
|
||||
}
|
||||
.modal-card-confirm-spread {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
dialog::backdrop {
|
||||
background-color: rgba(255, 255, 255, .5);
|
||||
opacity: 0;
|
||||
transition: opacity .5s allow-discrete;
|
||||
}
|
||||
dialog[open], dialog[open]::backdrop {
|
||||
opacity: 1;
|
||||
}
|
||||
@starting-style {
|
||||
dialog[open], dialog[open]::backdrop {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: $screen-sm-min) {
|
||||
dialog {
|
||||
.modal-card:has(.modal-card-icon) {
|
||||
flex-direction: row;
|
||||
}
|
||||
.modal-card-content {
|
||||
padding: 2em;
|
||||
}
|
||||
.modal-card-icon {
|
||||
font-size: 4em;
|
||||
padding: 6px 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shake-once {
|
||||
animation: shake .2s;
|
||||
transform: translate3d(0, 0, 0);
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
0% { transform: skewX(0deg); }
|
||||
20% { transform: skewX(-5deg); }
|
||||
40% { transform: skewX(5deg); }
|
||||
60% { transform: skewX(-5deg); }
|
||||
80% { transform: skewX(5deg); }
|
||||
100% { transform: skewX(0deg); }
|
||||
}
|
||||
|
||||
#lightbox-dialog {
|
||||
width: fit-content;
|
||||
max-width: 80%;
|
||||
min-width: 24em;
|
||||
.modal-card-content {
|
||||
padding: 2.5em;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
figcaption {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user