122 lines
4.7 KiB
Cheetah
122 lines
4.7 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. Real-time status.</p>
|
|
</div>
|
|
|
|
<hr class="divider">
|
|
|
|
<div class="section container">
|
|
<div class="glass-grid">
|
|
{{range .Pops}}
|
|
<div class="glass-pop {{if eq .Status "live"}}glass-live{{else}}glass-planned{{end}}">
|
|
<div class="glass-header">
|
|
<span class="glass-city">{{.City}}</span>
|
|
<span class="glass-status {{if eq .Status "live"}}glass-status-live{{else}}glass-status-planned{{end}}">{{.Status}}</span>
|
|
</div>
|
|
<div class="glass-details">
|
|
<div class="glass-row">
|
|
<span class="glass-key">Region</span>
|
|
<span class="glass-val mono">{{.RegionName}}</span>
|
|
</div>
|
|
<div class="glass-row">
|
|
<span class="glass-key">Provider</span>
|
|
<span class="glass-val">{{.Provider}}</span>
|
|
</div>
|
|
{{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 class="glass-row">
|
|
<span class="glass-key">Latency</span>
|
|
<span class="glass-val glass-latency" data-dns="{{.DNS}}" data-status="{{.Status}}">{{if eq .Status "live"}}—{{else}}<span class="glass-muted">Q2 2026</span>{{end}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{define "glass-script"}}
|
|
<script>
|
|
(function() {
|
|
const grid = document.querySelector('.glass-grid');
|
|
let pending = 0;
|
|
const pops = grid.querySelectorAll('.glass-pop');
|
|
|
|
document.querySelectorAll('.glass-latency[data-status="live"][data-dns]').forEach(el => {
|
|
const dns = el.dataset.dns;
|
|
if (!dns) { el.textContent = '—'; return; }
|
|
pending++;
|
|
const t0 = performance.now();
|
|
const t0 = performance.now();
|
|
fetch('https://' + dns + ':1984/ping').then(() => {
|
|
const ms = Math.round(performance.now() - t0);
|
|
el.textContent = ms + ' ms';
|
|
el.dataset.ms = ms;
|
|
el.classList.add(ms < 100 ? 'glass-fast' : ms < 250 ? 'glass-ok' : 'glass-slow');
|
|
if (--pending === 0) sortGrid();
|
|
}).catch(() => {
|
|
const ms = Math.round(performance.now() - t0);
|
|
if (ms < 4900) {
|
|
el.textContent = ms + ' ms';
|
|
el.dataset.ms = ms;
|
|
el.classList.add(ms < 100 ? 'glass-fast' : ms < 250 ? 'glass-ok' : 'glass-slow');
|
|
} else {
|
|
el.textContent = 'down';
|
|
el.dataset.ms = 99999;
|
|
el.classList.add('glass-slow');
|
|
}
|
|
if (--pending === 0) sortGrid();
|
|
});
|
|
});
|
|
|
|
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 pingAll() {
|
|
document.querySelectorAll('.glass-latency[data-status="live"][data-dns]').forEach(el => {
|
|
const dns = el.dataset.dns;
|
|
if (!dns) return;
|
|
el.textContent = '...';
|
|
el.className = 'glass-val glass-latency';
|
|
const t0 = performance.now();
|
|
fetch('https://' + dns + ':1984/ping').then(() => {
|
|
const ms = Math.round(performance.now() - t0);
|
|
el.textContent = ms + ' ms';
|
|
el.dataset.ms = ms;
|
|
el.classList.add(ms < 100 ? 'glass-fast' : ms < 250 ? 'glass-ok' : 'glass-slow');
|
|
}).catch(() => {
|
|
const ms = Math.round(performance.now() - t0);
|
|
if (ms < 4900) {
|
|
el.textContent = ms + ' ms';
|
|
el.dataset.ms = ms;
|
|
el.classList.add(ms < 100 ? 'glass-fast' : ms < 250 ? 'glass-ok' : 'glass-slow');
|
|
} else {
|
|
el.textContent = 'down';
|
|
el.dataset.ms = 99999;
|
|
el.classList.add('glass-slow');
|
|
}
|
|
});
|
|
});
|
|
setTimeout(sortGrid, 6000);
|
|
}
|
|
|
|
setInterval(pingAll, 60000);
|
|
})();
|
|
</script>
|
|
{{end}}
|