upp/web/index.html

170 lines
3.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link crossorigin rel="stylesheet" href="https://cdn.alemi.dev/web/alemi.css">
<title>uppe.rs</title>
<style>
span.cell {
position: relative;
display: inline-block;
width: .5rem;
height: 1.2rem;
border: 1px solid var(--secondary);
font-size: 8pt;
line-height: 1.2rem;
background-color: rgba(var(--secondary-rgb), 0.4);
margin-top: .3rem;
margin-bottom: .3rem;
padding-top: 0;
padding-bottom: 0;
transition: .1s;
text-align: center;
cursor: default;
border-radius: .3rem;
color: #ffffff00;
}
span.cell:hover {
padding-top: .3rem;
padding-bottom: .3rem;
width: 2rem;
font-size: 8pt;
margin-top: 0;
margin-bottom: 0;
margin-right: -0.75rem;
margin-left: -0.75rem;
color: var(--background);
background-color: rgba(var(--secondary-rgb), 1);
z-index: 1;
font-weight: bold;
}
span.cell.warning {
border-color: var(--accent);
}
span.cell.error {
border-color: var(--accent);
background-color: rgba(var(--accent-rgb), 0.4);
}
span.cell.error:hover {
background-color: rgba(var(--accent-rgb), 1);
}
span.sep {
color: var(--background-secondary);
margin-right: 1em;
margin-left: 1em;
}
hr.color {
color: var(--accent);
border-color: var(--accent);
}
div.card {
display: inline-block;
white-space: nowrap;
overflow-x: scroll;
max-width: 100%;
margin-top: 2em;
border-radius: 1em;
border: 1px solid var(--background-secondary);
padding: 1em;
box-sizing: border-box;
transition: .3s;
}
div.card:hover {
background-color: var(--background-dim);
}
body {
margin: 0;
}
footer {
width: 100%;
}
div.content {
min-height: calc(100vh - 3.5rem);
}
</style>
</head>
<body>
<div class="content">
<div class="ml-1">
<h1 class="mt-0 pt-1">uppe.rs</h1>
<p>%%DESCRIPTION%%</p>
</div>
<hr class="color"/>
<main id="uppe-rs-content">
</main>
</div>
<footer>
<hr />
<p class="mt-s mb-s">
<span class="cell error">...</span> down <span class="sep">|</span>
<span class="cell warning">...</span> slow <span class="sep">|</span>
<span class="cell">...</span> up
</p>
</footer>
</body>
<script>
function cell(timestamp, rtt) {
let d = new Date(timestamp * 1000);
let warning = "";
if (rtt !== null && rtt >= %%THRESHOLD%%) {
warning = " warning";
}
if (rtt === null) {
return `<span class="cell error" title="${d}"></span>`;
} else {
return `<span class="cell${warning}" title="${rtt}ms -- ${d}">${rtt}</span>`;
}
}
function card(key, history, last_rtt) {
let bar = "";
let now = Math.floor(Date.now() / 1000);
let first = history[0][0];
let hrs_ago = (now - first) / 3600;
for (let el of history) {
bar += cell(el[0], el[1]);
}
return `<div class="card">
<h3 class="mt-0">${key} <code class="color">${last_rtt ? last_rtt + 'ms' : 'DOWN'}</code></h3>
<div class="box">
${bar}
<p class="ma-0"><small>^ ~${hrs_ago.toFixed(1)}h ago</small></p>
</div>
</div>`;
}
let main = document.getElementById("uppe-rs-content");
async function updateStatus() {
let res = await fetch("/api/status")
let status = await res.json()
if (status.error) {
console.error("server error:", status);
return;
}
let keys = Object.keys(status);
keys.sort();
let out = "";
for (let key of keys) {
let res = await fetch(`/api/status/${key}?limit=120`);
let history = await res.json();
out += card(key, history, status[key]);
out += "\n";
}
main.innerHTML = out;
}
setInterval(updateStatus, 60 * 1000)
updateStatus()
</script>
</html>