feat(dashboard): bug report, play key and system log pages update without reloading

reloadInPlace() and goTo(url) (common.js) show the page again or open
another one through nav.js, or reload/load normally without it.
Resolving a bug report updates the page in place; deleting a bug
report or play key goes back to its list without leaving the deleted
page in the history. The System Log's server and file pickers and its
Refresh button swap the page in (Refresh keeps the scroll position).
The AI helper's "open the account" goes through nav.js too.

Check: resolve a bug report: the Resolved badge and text appear with no
reload. Delete a play key: back on Play Keys, and Back doesn't return
to the deleted key. System Log: picking a server or file and Refresh
change the log without a white flash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 01:59:42 -05:00
parent b66bae6a9c
commit 172706ee51
5 changed files with 25 additions and 7 deletions

View File

@@ -206,7 +206,7 @@
var prefill = { account: String(data.account_id), action: s.action, days: s.days, strike: s.strike,
reason: s.action === 'note' ? clip(s.staff_explanation, 300) : s.player_reason, at: Date.now() };
try { sessionStorage.setItem(PREFILL_KEY, JSON.stringify(prefill)); } catch (e) { return toast('Could not pass the suggestion on (browser storage is off)', 'warning'); }
window.location.href = '/accounts/' + encodeURIComponent(data.account_id);
goTo('/accounts/' + encodeURIComponent(data.account_id));
}
// On an account page: fill in the form a suggestion was passed to. Nothing is submitted.

View File

@@ -92,6 +92,21 @@
});
};
/**
* Show this page again with what the server has now, after a change made from it: in place when nav.js is there
* (Nav.refresh), otherwise a reload. goTo(url) opens another page the same way (Nav.go, or a normal load).
*/
window.reloadInPlace = function () {
if (window.Nav && Nav.refresh) return Nav.refresh({ force: true });
window.location.reload();
return Promise.resolve();
};
window.goTo = function (url, options) {
if (window.Nav && Nav.go) return Nav.go(url, options);
if (options && options.replace) window.location.replace(url); else window.location.href = url;
return Promise.resolve();
};
window.toast = function (message, type) {
var container = document.getElementById('toast-container');
if (!container) {

View File

@@ -61,12 +61,12 @@ if (window.Live) Live.refreshPage('bug_reports', document.getElementById('report
function resolveReport() {
api.action(reportUrl + '/resolve', { resolution: document.getElementById('resolution').value.trim() })
.then(function () { location.reload(); }).catch(function () {});
.then(function () { reloadInPlace(); }).catch(function () {});
}
function deleteReport() {
if (!confirm('Delete this bug report?')) return;
api.action(reportUrl + '/delete').then(function () { window.location.href = '/bug_reports'; }).catch(function () {});
api.action(reportUrl + '/delete').then(function () { goTo('/bug_reports', { replace: true }); }).catch(function () {});
}
</script>
{% endblock %}

View File

@@ -75,7 +75,7 @@ function saveKey() {
function deleteKey() {
if (!confirm('Delete this play key? Accounts that used it keep working but lose the link to it.')) return;
api.action(keyUrl + '/delete').then(function () { window.location.href = '/play_keys'; }).catch(function () {});
api.action(keyUrl + '/delete').then(function () { goTo('/play_keys', { replace: true }); }).catch(function () {});
}
</script>
{% endblock %}

View File

@@ -28,7 +28,7 @@
</select>
</div>
<div class="col-sm-3 d-flex gap-2">
<button type="button" class="btn btn-sm btn-outline-secondary flex-fill" onclick="location.reload()">Refresh</button>
<button type="button" class="btn btn-sm btn-outline-secondary flex-fill" onclick="showLogAgain()">Refresh</button>
{% if exists("log_file") %}<a class="btn btn-sm btn-outline-secondary flex-fill" href="/api/logs/file?name={{ log_file }}">Download</a>{% endif %}
</div>
</form>
@@ -128,8 +128,11 @@ document.querySelectorAll('#logFilePick option').forEach(function (o) {
var started = Number((o.value.match(/_(\d{9,})\.log$/) || [])[1]);
o.textContent = (started ? 'Started ' + fmt.unix(started) + ', ' : '') + 'last written ' + fmt.unix(Number(o.dataset.time)) + ' (' + fileSize(o.dataset.size) + ')';
});
document.getElementById('logServerPick').addEventListener('change', function () { location.href = '/system_log?server=' + encodeURIComponent(this.value); });
document.getElementById('logFilePick').addEventListener('change', function () { this.form.submit(); });
document.getElementById('logServerPick').addEventListener('change', function () { goTo('/system_log?server=' + encodeURIComponent(this.value)); });
// requestSubmit, so the change goes through nav.js like a click on a link
document.getElementById('logFilePick').addEventListener('change', function () { if (this.form.requestSubmit) this.form.requestSubmit(); else this.form.submit(); });
// The same file again with its newest lines, where the page was scrolled to
function showLogAgain() { goTo(location.href, { replace: true, scroll: window.scrollY }); }
// Download logs
function bundleLocal(date) { var d = new Date(date.getTime() - date.getTimezoneOffset() * 60000); return d.toISOString().slice(0, 16); }