<!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); } hr.color { color: var(--accent); border-color: var(--accent); } hr.separator { margin: 2em; } 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); } </style> </head> <body> <div class="ma-1"> <h1>uppe.rs</h1> <p>%%DESCRIPTION%%</p> </div> <hr class="color"/> <small style="display: block" class="rev">now --></small> <main id="uppe-rs-content"> </main> </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 = ""; 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} </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>