102 lines
4.1 KiB
Cheetah
102 lines
4.1 KiB
Cheetah
{{define "glass"}}
|
|
<div class="hero container">
|
|
<p class="label accent mb-4">Network</p>
|
|
<h1 class="mb-4">Looking Glass</h1>
|
|
<p class="lead">{{len .Pops}} points of presence. Find the fastest node for you.</p>
|
|
</div>
|
|
|
|
<div class="section container" style="padding-top:24px">
|
|
<div style="background:#fffbeb;border:1px solid #fde68a;border-radius:var(--radius-sm);padding:16px 20px;margin-bottom:24px;font-size:0.85rem;color:#854d0e">
|
|
<strong style="text-transform:uppercase;letter-spacing:0.06em;font-size:0.75rem">Dubai (me-central-1)</strong><br>
|
|
The AWS UAE region remains offline following drone strikes on March 1, 2026. No customer data was affected. We are awaiting updates from AWS on restoration, expected in the coming weeks.
|
|
</div>
|
|
<div class="glass-grid">
|
|
{{range .Pops}}
|
|
<div class="glass-pop {{if eq .Status "live"}}glass-live{{else}}glass-planned{{end}}">
|
|
<div class="glass-header">
|
|
<div><div class="pop-city">{{.City}}</div><div class="pop-country">{{.CountryFull}}</div></div>
|
|
<span class="glass-status {{if eq .Status "live"}}glass-status-live{{else if eq .Status "outage"}}glass-status-outage{{else}}glass-status-planned{{end}}">{{.Status}}</span>
|
|
</div>
|
|
{{if eq .Status "live"}}<div class="glass-latency-block">
|
|
<div class="glass-latency-left"><span class="glass-latency-title">Response time</span><span class="glass-latency-hint">lower is better</span></div>
|
|
<div class="glass-latency-hero glass-latency" data-dns="{{.DNS}}" data-status="{{.Status}}">—</div>
|
|
</div>
|
|
<div class="glass-details">
|
|
{{if .IP}}<div class="glass-row">
|
|
<span class="glass-key">IPv4</span>
|
|
<span class="glass-val mono">{{.IP}}</span>
|
|
</div>{{end}}
|
|
{{if .DNS}}<div class="glass-row">
|
|
<span class="glass-key">DNS</span>
|
|
<span class="glass-val mono">{{.DNS}}</span>
|
|
</div>{{end}}
|
|
</div>{{end}}
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{define "glass-script"}}
|
|
<script>
|
|
(function() {
|
|
const grid = document.querySelector('.glass-grid');
|
|
|
|
function classify(ms) {
|
|
if (ms < 60) return 'glass-fast';
|
|
if (ms < 120) return 'glass-ok';
|
|
return 'glass-slow';
|
|
}
|
|
|
|
function applyResult(el, ms) {
|
|
el.classList.remove('glass-fast', 'glass-ok', 'glass-slow');
|
|
if (ms < 4900) {
|
|
el.textContent = ms + ' ms';
|
|
el.dataset.ms = ms;
|
|
el.classList.add(classify(ms));
|
|
} else {
|
|
el.textContent = 'down';
|
|
el.dataset.ms = 99999;
|
|
el.classList.add('glass-slow');
|
|
}
|
|
}
|
|
|
|
function sortGrid() {
|
|
const arr = Array.from(grid.querySelectorAll('.glass-pop'));
|
|
arr.sort((a, b) => {
|
|
const aMs = parseInt(a.querySelector('.glass-latency')?.dataset.ms || 99998);
|
|
const bMs = parseInt(b.querySelector('.glass-latency')?.dataset.ms || 99998);
|
|
return aMs - bMs;
|
|
});
|
|
arr.forEach(el => grid.appendChild(el));
|
|
}
|
|
|
|
function ping(el) {
|
|
const dns = el.dataset.dns;
|
|
if (!dns) { el.textContent = '—'; return Promise.resolve(); }
|
|
el.textContent = '...';
|
|
// Warm-up: first fetch establishes TLS, second measures actual latency
|
|
return fetch('https://' + dns + ':1984/ping').then(() => {}).catch(() => {}).then(() => {
|
|
const t0 = performance.now();
|
|
return fetch('https://' + dns + ':1984/ping').then(() => {}).catch(() => {}).then(() => {
|
|
applyResult(el, Math.round(performance.now() - t0));
|
|
sortGrid();
|
|
});
|
|
});
|
|
}
|
|
|
|
async function pingAll() {
|
|
const els = Array.from(document.querySelectorAll('.glass-latency[data-status="live"][data-dns]'));
|
|
if (window.innerWidth < 768) {
|
|
for (const el of els) { await ping(el); sortGrid(); }
|
|
} else {
|
|
els.forEach(el => ping(el));
|
|
}
|
|
}
|
|
|
|
pingAll();
|
|
setInterval(pingAll, 60000);
|
|
})();
|
|
</script>
|
|
{{end}}
|