upp/web/index.html

194 lines
4.3 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);
}
span.dots {
&:after {
animation: dots 1.5s linear infinite;
display: inline-block;
content: "\00a0\00a0\00a0";
}
}
@keyframes dots {
0% { content: "\00a0\00a0\00a0"; }
25% { content: ".\00a0\00a0"; }
50% { content: "..\00a0"; }
75% { content: "..."; }
100% { content: "\00a0\00a0\00a0"; }
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
}
</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">
<h2 class="center mt-3">loading<span class="dots"></span></h2>
</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[history.length - 1][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>
<table class="align">
<tr>
<td colspan="2">${bar}</td>
</tr>
<tr>
<td><small>^ now</small></td>
<td class="rev"><small>~${hrs_ago.toFixed(1)}h ago ^</small></td>
</tr>
</table>
</div>`;
}
const main = document.getElementById("uppe-rs-content");
const batchsize = (new URLSearchParams(window.location.search)).get('batch') || '%%BATCHSIZE%%';
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=${batchsize}`);
let history = await res.json();
out += card(key, history, status[key]);
out += "\n";
}
main.innerHTML = out;
}
setInterval(updateStatus, 5 * 60 * 1000)
updateStatus()
</script>
</html>