Merge pull request #35 from asimonson1125/claude/review-architecture-hxQz0

Claude/review architecture hx qz0
This commit is contained in:
2026-02-12 10:15:35 -05:00
committed by GitHub
8 changed files with 86 additions and 55 deletions

View File

@@ -60,9 +60,9 @@ def goto(location='home'):
page = None
try:
page = flask.render_template(pagevars["template"], var=pagevars)
except Exception as e:
e = HTTPerror.InternalServerError(None, e)
page = page404(e)
except Exception:
e = HTTPerror.InternalServerError()
page = handle_http_error(e)
return [pagevars, page]
def funcGen(pagename, pages):
@@ -72,7 +72,7 @@ def funcGen(pagename, pages):
except Exception:
e = HTTPerror.InternalServerError()
print(e)
return page404(e)
return handle_http_error(e)
return dynamicRule
for i in pages:
@@ -86,14 +86,14 @@ def resume():
return flask.send_file("./static/Resume_Simonson_Andrew.pdf")
@app.errorhandler(HTTPerror.HTTPException)
def page404(e):
def handle_http_error(e):
eCode = e.code
message = e.description
pagevars = {
"template": "error.html",
"title": f"{eCode} - Simonson",
"description": "Error on Andrew Simonson's Digital Portfolio",
"canonical": "404",
"canonical": f"/{eCode}",
}
return (
flask.render_template(
@@ -107,12 +107,12 @@ def page404(e):
)
@app.errorhandler(Exception)
def page500(e):
def handle_generic_error(e):
pagevars = {
"template": "error.html",
"title": "500 - Simonson",
"description": "Error on Andrew Simonson's Digital Portfolio",
"canonical": "404",
"canonical": "/500",
}
return (
flask.render_template(

View File

@@ -1,6 +1,6 @@
from os import environ as env
# automatically updates some dev envs. need to remove for production.
try:
__import__('envs.py')
__import__('envs')
except ImportError:
pass

View File

@@ -5,6 +5,7 @@ Checks service availability and tracks uptime statistics
import requests
import time
import json
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timedelta
from threading import Thread, Lock
from pathlib import Path
@@ -125,12 +126,15 @@ class ServiceMonitor:
"""Check all services and update status data"""
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Checking all services...")
# Perform all network checks OUTSIDE the lock to avoid blocking API calls
# Perform all network checks concurrently and OUTSIDE the lock
results = {}
for service in SERVICES:
result = self.check_service(service)
results[service['id']] = result
print(f" {service['name']}: {result['status']} ({result['response_time']}ms)")
with ThreadPoolExecutor(max_workers=len(SERVICES)) as executor:
futures = {executor.submit(self.check_service, s): s for s in SERVICES}
for future in futures:
service = futures[future]
result = future.result()
results[service['id']] = result
print(f" {service['name']}: {result['status']} ({result['response_time']}ms)")
# Only acquire lock when updating the shared data structure
with self.lock:

View File

@@ -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,15 +121,15 @@ li {
color: #a8a8a8;
}
strong {
color: #ecebeb;
}
p, li, span {
color: rgb(212, 212, 212);
font-size: 1rem;
}
strong {
color: #ecebeb;
}
span {
font-size: .8rem;
}
@@ -289,6 +293,9 @@ tr {
padding-right: 4rem;
border-bottom: #0f0f0f solid 5px;
color: white;
position: relative;
padding-bottom: 0.5em;
margin-bottom: 1em;
}
.foreground {
@@ -313,12 +320,6 @@ tr {
line-height: 1.5em;
}
.concentratedHead {
position: relative;
padding-bottom: 0.5em;
margin-bottom: 1em;
}
.concentratedHead::after {
content: '';
position: absolute;
@@ -442,10 +443,6 @@ tr {
height: 0;
}
.relative {
position: relative;
}
.onRight {
overflow: scroll;
margin: auto;
@@ -456,6 +453,11 @@ tr {
margin-bottom: 5px;
}
.relative {
position: relative;
}
.bgi {
background-size: contain;
background-repeat: no-repeat;
@@ -955,7 +957,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 +1127,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;
}

View File

@@ -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,

View File

@@ -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) {

View File

@@ -236,7 +236,7 @@ function refreshStatus() {
/**
* Initialize on page load
*/
let statusIntervalId = null;
var statusIntervalId = null;
function initStatusPage() {
// Clear any existing interval from a previous SPA navigation
@@ -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);

View File

@@ -55,7 +55,7 @@
<script defer src="{{ url_for('static', filename='js/responsive.js') }}"></script>
<script src="{{ url_for('static', filename='js/chessbed.js') }}"></script>
<script defer src="{{ url_for('static', filename='js/idler.js') }}"></script>
<script defer src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.min.js"></script>
<title>{{ var['title'] }}</title>
</head>
{% block header %}