editor service errors are displayed better
This commit is contained in:
parent
5ce8973ca3
commit
0c98df8526
@ -1007,7 +1007,7 @@
|
||||
location.reload(true);
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
$('#savecorrections').show();
|
||||
$('#saving').text('');
|
||||
}
|
||||
@ -1024,7 +1024,7 @@
|
||||
id: poemId
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
},
|
||||
success: function (rhyme) {
|
||||
$(elementId).val(rhyme);
|
||||
@ -1049,7 +1049,7 @@
|
||||
poemid: id,
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || 'خطا رخ داد.', 'error');
|
||||
upShowError(e.responseText || 'خطا رخ داد.');
|
||||
},
|
||||
success: function () {
|
||||
location.reload(true);
|
||||
@ -1074,7 +1074,7 @@
|
||||
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
},
|
||||
success: function () {
|
||||
location.reload(true);
|
||||
@ -1161,7 +1161,7 @@
|
||||
location.href = '/?p=' + String(id);
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
$('#breakpoem-' + String(vOrder)).show();
|
||||
}
|
||||
|
||||
@ -1182,7 +1182,7 @@
|
||||
upToast('انجام شد.');
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
}
|
||||
|
||||
});
|
||||
@ -1210,7 +1210,7 @@
|
||||
id: id,
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
},
|
||||
success: function () {
|
||||
upToast('انجام شد.');
|
||||
@ -1235,7 +1235,7 @@
|
||||
id: id,
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
},
|
||||
success: function () {
|
||||
upToast('انجام شد.');
|
||||
@ -1268,7 +1268,7 @@
|
||||
location.reload();
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
}
|
||||
|
||||
});
|
||||
@ -1289,7 +1289,7 @@
|
||||
location.reload();
|
||||
},
|
||||
error: function (e) {
|
||||
upToast(e.responseText || String(e), 'error');
|
||||
upShowError(e.responseText || String(e));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
14
GanjooRazor/Pages/Shared/_ErrorModal.cshtml
Normal file
14
GanjooRazor/Pages/Shared/_ErrorModal.cshtml
Normal file
@ -0,0 +1,14 @@
|
||||
@* Styled, non-auto-dismissing display for a service error's full text (these often carry the
|
||||
backend's exception message and stack trace, which upToast's few-second toast never gave
|
||||
anyone enough time to actually read before it faded out). Included once by
|
||||
_UserPanelLayout.cshtml. Trigger with JS: upShowError(message) *@
|
||||
<div class="up-modal-backdrop" id="upErrorBackdrop" hidden>
|
||||
<div class="up-modal up-modal--error" role="alertdialog" aria-modal="true" aria-labelledby="upErrorTitle">
|
||||
<p id="upErrorTitle" class="up-modal__message">خطایی در ارتباط با سرویس رخ داد:</p>
|
||||
<pre id="upErrorDetails" class="up-modal__details"></pre>
|
||||
<div class="up-modal__actions">
|
||||
<button type="button" class="up-btn up-btn--ghost" id="upErrorCopy">کپی متن خطا</button>
|
||||
<button type="button" class="up-btn up-btn--danger" id="upErrorClose">بستن</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -205,10 +205,11 @@
|
||||
|
||||
<partial name="_Toasts" />
|
||||
<partial name="_ConfirmModal" />
|
||||
<partial name="_ErrorModal" />
|
||||
|
||||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||
<script src="/js/user-panel.js?version=3"></script>
|
||||
<script src="/js/user-panel.js?version=4"></script>
|
||||
|
||||
@await RenderSectionAsync("Scripts", required: false)
|
||||
<div id="footer"></div>
|
||||
|
||||
@ -475,6 +475,33 @@ body.up-modal-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ---------- error modal (persistent service-error display, see _ErrorModal.cshtml) ---------- */
|
||||
|
||||
.up-modal--error {
|
||||
max-width: 700px;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.up-modal__details {
|
||||
max-height: 50vh;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
/* backend error text/stack traces are English - keep them LTR regardless of the page's own
|
||||
RTL direction, same reasoning as .linputText elsewhere in this file */
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
font-family: 'Consolas', 'Courier New', monospace;
|
||||
font-size: 0.82rem;
|
||||
line-height: 1.5;
|
||||
color: var(--up-text);
|
||||
background: var(--up-bg);
|
||||
border: 1px solid var(--up-border);
|
||||
border-radius: var(--up-radius-sm);
|
||||
padding: var(--up-space-2);
|
||||
margin: 0 0 var(--up-space-4);
|
||||
}
|
||||
|
||||
/* ---------- dashboard quick links ---------- */
|
||||
|
||||
.up-quick-links {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
// User area (پیشخان کاربر) shared UI helpers.
|
||||
// Provides upConfirm() and upToast() as drop-in, styled replacements for
|
||||
// Provides upConfirm(), upToast() and upShowError() as drop-in, styled replacements for
|
||||
// window.confirm()/window.alert(), used across the panel's AJAX actions.
|
||||
// Requires the markup from Areas/User/Pages/Shared/_ConfirmModal.cshtml and
|
||||
// _Toasts.cshtml to be present on the page (included once by _UserPanelLayout).
|
||||
// Requires the markup from Pages/Shared/_ConfirmModal.cshtml, _Toasts.cshtml and
|
||||
// _ErrorModal.cshtml to be present on the page (included once by _UserPanelLayout).
|
||||
|
||||
/**
|
||||
* Shows a styled confirmation dialog and resolves to true/false.
|
||||
@ -88,3 +88,72 @@ function upToast(message, type) {
|
||||
}, 250);
|
||||
}, 4000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a service error's full text (often a backend exception message plus its stack trace) in
|
||||
* a modal that stays on screen until closed, with a copy button - unlike upToast(), which fades
|
||||
* out after 4 seconds and gives no way to get back the text it just showed. Falls back to
|
||||
* upToast() if the modal markup isn't on the page.
|
||||
* @param {string} message
|
||||
*/
|
||||
function upShowError(message) {
|
||||
message = message == null ? '' : String(message);
|
||||
var backdrop = document.getElementById('upErrorBackdrop');
|
||||
var detailsEl = document.getElementById('upErrorDetails');
|
||||
var closeBtn = document.getElementById('upErrorClose');
|
||||
var copyBtn = document.getElementById('upErrorCopy');
|
||||
|
||||
if (!backdrop || !detailsEl || !closeBtn || !copyBtn) {
|
||||
upToast(message, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
detailsEl.textContent = message;
|
||||
|
||||
backdrop.hidden = false;
|
||||
document.body.classList.add('up-modal-open');
|
||||
|
||||
function cleanup() {
|
||||
backdrop.hidden = true;
|
||||
document.body.classList.remove('up-modal-open');
|
||||
closeBtn.removeEventListener('click', onClose);
|
||||
copyBtn.removeEventListener('click', onCopy);
|
||||
backdrop.removeEventListener('click', onBackdropClick);
|
||||
document.removeEventListener('keydown', onKeyDown);
|
||||
}
|
||||
|
||||
function onClose() { cleanup(); }
|
||||
function onBackdropClick(e) { if (e.target === backdrop) cleanup(); }
|
||||
function onKeyDown(e) { if (e.key === 'Escape') cleanup(); }
|
||||
|
||||
function onCopy() {
|
||||
var restoreText = copyBtn.textContent;
|
||||
function showCopied(ok) {
|
||||
copyBtn.textContent = ok ? '✓ کپی شد' : 'کپی ممکن نشد';
|
||||
setTimeout(function () { copyBtn.textContent = restoreText; }, 1500);
|
||||
}
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(message).then(function () { showCopied(true); }, function () { showCopied(false); });
|
||||
} else {
|
||||
// clipboard API unavailable (e.g. non-HTTPS context) - fall back to a temporary,
|
||||
// off-screen textarea and the legacy execCommand copy path
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = message;
|
||||
ta.style.position = 'fixed';
|
||||
ta.style.left = '-9999px';
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
var ok = false;
|
||||
try { ok = document.execCommand('copy'); } catch (e) { ok = false; }
|
||||
document.body.removeChild(ta);
|
||||
showCopied(ok);
|
||||
}
|
||||
}
|
||||
|
||||
closeBtn.addEventListener('click', onClose);
|
||||
copyBtn.addEventListener('click', onCopy);
|
||||
backdrop.addEventListener('click', onBackdropClick);
|
||||
document.addEventListener('keydown', onKeyDown);
|
||||
|
||||
closeBtn.focus();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user