mirror of
https://github.com/asimonson1125/asimonson1125.github.io.git
synced 2026-09-22 11:35:33 -05:00
fix architectural issues: SPA nav, error handling, CSS bugs, perf
- responsive.js: fix scroll race condition (scroll after innerHTML),
add error handling for fetch failures, fix implicit global `eid`,
dispatch `beforenavigate` event for cleanup hooks
- chessbed.js: fix implicit global `ratings` variable
- status.js: clear polling interval on SPA navigation via
`beforenavigate` event to prevent leak
- App.css: add font-display:swap to all @font-face, fix broken
media query (missing px unit), consolidate duplicate selectors
(.concentratedHead, .relative, strong), fix hardcoded bookshelf
background-image path to use relative URL
- header.html: defer chessbed.js, use p5.min.js instead of p5.js
- monitor.py: use ThreadPoolExecutor for concurrent service checks
- config.py: fix __import__('envs.py') → __import__('envs')
- app.py: rename misleading error handlers (page404→handle_http_error,
page500→handle_generic_error), fix error info leakage by not passing
raw exception to InternalServerError, fix hardcoded canonical "404"
https://claude.ai/code/session_01FUhPqQLahEoL6FMxhXkDKa
This commit is contained in:
@@ -1,23 +1,27 @@
|
||||
@font-face {
|
||||
font-family: "neon-future";
|
||||
src: url("../fonts/NeonFuture.ttf")
|
||||
src: url("../fonts/NeonFuture.ttf");
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: "shuttlex";
|
||||
src: url("../fonts/SHUTTLE-X.ttf");
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "sunset-club";
|
||||
src: url("../fonts/SunsetClub.otf")
|
||||
src: url("../fonts/SunsetClub.otf");
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: "robotoreg";
|
||||
src: url("../fonts/RobotoCondensed-Regular.ttf")
|
||||
src: url("../fonts/RobotoCondensed-Regular.ttf");
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
html, body {
|
||||
@@ -117,10 +121,6 @@ li {
|
||||
color: #a8a8a8;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: #ecebeb;
|
||||
}
|
||||
|
||||
p, li, span {
|
||||
color: rgb(212, 212, 212);
|
||||
font-size: 1rem;
|
||||
@@ -289,6 +289,9 @@ tr {
|
||||
padding-right: 4rem;
|
||||
border-bottom: #0f0f0f solid 5px;
|
||||
color: white;
|
||||
position: relative;
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.foreground {
|
||||
@@ -313,12 +316,6 @@ tr {
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.concentratedHead {
|
||||
position: relative;
|
||||
padding-bottom: 0.5em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.concentratedHead::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -442,10 +439,6 @@ tr {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.onRight {
|
||||
overflow: scroll;
|
||||
margin: auto;
|
||||
@@ -955,7 +948,7 @@ tr {
|
||||
padding: 10px;
|
||||
border: solid 2px #553;
|
||||
border-radius: 0.5em;
|
||||
background-image: url("/static/photos/wood.jpg");
|
||||
background-image: url("../photos/wood.jpg");
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
@@ -1125,9 +1118,10 @@ tr {
|
||||
@font-face {
|
||||
font-family: Chess New;
|
||||
src: url('../fonts/chessglyph-new.0cc8115c.woff2');
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600) {
|
||||
@media screen and (max-width: 600px) {
|
||||
#nametagContainer {
|
||||
width: unset;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ async function addChessEmbed(username) {
|
||||
if (user.status === 200) {
|
||||
user = await user.json();
|
||||
stats = await stats.json();
|
||||
ratings = {
|
||||
const ratings = {
|
||||
rapid: stats.chess_rapid.last.rating,
|
||||
blitz: stats.chess_blitz.last.rating,
|
||||
bullet: stats.chess_bullet.last.rating,
|
||||
|
||||
@@ -13,30 +13,46 @@ function toggleMenu(collapse=false) {
|
||||
}
|
||||
|
||||
async function goto(location, { push = true } = {}) {
|
||||
let a = await fetch("/api/goto/" + location, {
|
||||
credentials: "include",
|
||||
method: "GET",
|
||||
mode: "cors",
|
||||
});
|
||||
let a;
|
||||
try {
|
||||
a = await fetch("/api/goto/" + location, {
|
||||
credentials: "include",
|
||||
method: "GET",
|
||||
mode: "cors",
|
||||
});
|
||||
if (!a.ok) {
|
||||
console.error(`Navigation failed: HTTP ${a.status}`);
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Navigation fetch failed:", err);
|
||||
return;
|
||||
}
|
||||
|
||||
document.dispatchEvent(new Event('beforenavigate'));
|
||||
|
||||
const response = await a.json();
|
||||
const metadata = response[0];
|
||||
const content = response[1];
|
||||
const root = document.getElementById("root");
|
||||
root.innerHTML = content;
|
||||
root.querySelectorAll("script").forEach((oldScript) => {
|
||||
const newScript = document.createElement("script");
|
||||
Array.from(oldScript.attributes).forEach(attr => {
|
||||
newScript.setAttribute(attr.name, attr.value);
|
||||
});
|
||||
newScript.textContent = oldScript.textContent;
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
|
||||
if (!window.location.href.includes("#")) {
|
||||
window.scrollTo({top: 0, left: 0, behavior:"instant"});
|
||||
} else {
|
||||
eid = decodeURIComponent(window.location.hash.substring(1))
|
||||
document.getElementById(eid).scrollIntoView()
|
||||
const eid = decodeURIComponent(window.location.hash.substring(1));
|
||||
const el = document.getElementById(eid);
|
||||
if (el) el.scrollIntoView();
|
||||
}
|
||||
const metadata = response[0];
|
||||
const content = response[1];
|
||||
let root = document.getElementById("root");
|
||||
root.innerHTML = content;
|
||||
root.querySelectorAll("script").forEach((oldScript) => {
|
||||
const newScript = document.createElement("script");
|
||||
Array.from(oldScript.attributes).forEach(attr => {
|
||||
newScript.setAttribute(attr.name, attr.value);
|
||||
});
|
||||
newScript.textContent = oldScript.textContent;
|
||||
oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||
});
|
||||
|
||||
toggleMenu(collapse=true);
|
||||
document.querySelector("title").textContent = metadata["title"];
|
||||
if (push) {
|
||||
|
||||
@@ -248,6 +248,14 @@ function initStatusPage() {
|
||||
statusIntervalId = setInterval(fetchStatus, 300000);
|
||||
}
|
||||
|
||||
// Clean up interval when navigating away via SPA
|
||||
document.addEventListener('beforenavigate', () => {
|
||||
if (statusIntervalId !== null) {
|
||||
clearInterval(statusIntervalId);
|
||||
statusIntervalId = null;
|
||||
}
|
||||
});
|
||||
|
||||
// Start when page loads
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initStatusPage);
|
||||
|
||||
Reference in New Issue
Block a user