SPB Git forge
15commits 1branches 0releases
29.7 MBsize
maindefault branch
10 days agolast push
TypeScript 36.3% Python 31.8% Go 18% JavaScript 9.8% Shell 1.9% SQL 1.4% CSS 0.5%
7.8 KB · 189 lines tsx
Raw Blame History
1import Link from 'next/link';2import { Empty, PNum, StatusDot } from '@/components/ui/primitives';3import { fmt, fmtInt, fmtMs, fmtPct } from '@/lib/format';4import { Time } from '@/lib/time';5import type { CountryTargetRow, LatencyPair, Probe, TargetRow } from '@/lib/types';67export function TargetsTable({ targets, showCategory = false }: { targets: (TargetRow | CountryTargetRow)[]; showCategory?: boolean }) {8  if (!targets.length) return <Empty>No target anchored in this scope.</Empty>;9  const sorted = [...targets].sort((a, b) => b.pressure - a.pressure);10  return (11    <div className="scroll-x -mx-3 px-3">12      <table className="tbl">13        <thead>14          <tr>15            <th>Target</th>16            {showCategory && <th className="hidden sm:table-cell">Category</th>}17            <th className="r">Pressure</th>18            <th className="r">OK 1h</th>19            <th className="r hidden sm:table-cell">TTFB p50</th>20          </tr>21        </thead>22        <tbody>23          {sorted.map((t) => (24            <tr key={t.target_id}>25              <td>26                <span className="text-ink">{t.name}</span> <span className="num text-[10.5px] text-ink-3">{t.target_id}</span>27              </td>28              {showCategory && <td className="hidden text-ink-2 sm:table-cell">{'category' in t ? t.category : '—'}</td>}29              <td className="r">30                <PNum value={t.pressure} />31              </td>32              <td className="num r" style={{ color: t.ok_ratio_1h < 0.98 ? 'var(--p-high)' : 'var(--ink)' }}>33                {fmtPct(t.ok_ratio_1h, 1)}34              </td>35              <td className="num r hidden text-ink-2 sm:table-cell">{fmtMs(t.ttfb_ms_median)}</td>36            </tr>37          ))}38        </tbody>39      </table>40    </div>41  );42}4344export function ProbesTable({ probes, compact = false }: { probes: Probe[]; compact?: boolean }) {45  if (!probes.length) return <Empty>No probe in this scope — pressure here is the destination view only.</Empty>;46  return (47    <div className="scroll-x -mx-3 px-3">48      <table className="tbl">49        <thead>50          <tr>51            <th>Probe</th>52            <th>Status</th>53            <th className="hidden md:table-cell">Location</th>54            <th className="hidden sm:table-cell">Provider</th>55            <th className="r">ASN</th>56            {!compact && (57              <>58                <th className="r hidden sm:table-cell">Meas./h</th>59                <th className="r hidden md:table-cell">Uptime 24h</th>60                <th className="r hidden lg:table-cell">Clock</th>61                <th className="hidden lg:table-cell">Version</th>62                <th className="hidden md:table-cell">Capabilities</th>63              </>64            )}65            <th className="r">Last seen</th>66          </tr>67        </thead>68        <tbody>69          {probes.map((p) => (70            <tr key={p.probe_id}>71              <td>72                <span className="num text-ink">{p.probe_id}</span>73                <span className="ml-2 hidden text-ink-2 xl:inline">{p.name}</span>74              </td>75              <td>76                <StatusDot status={p.status} />77              </td>78              <td className="hidden text-ink-2 md:table-cell">79                {p.city}, {p.country} ·{' '}80                <Link href={`/internet/${p.region}`} className="hover:text-accent">81                  {p.region}82                </Link>83              </td>84              <td className="hidden text-ink-2 sm:table-cell">{p.provider}</td>85              <td className="num r">86                <Link href={`/asn/${p.asn}`} className="hover:text-accent">87                  {p.asn}88                </Link>89              </td>90              {!compact && (91                <>92                  <td className="num r hidden text-ink-2 sm:table-cell">{fmtInt(p.measurements_1h)}</td>93                  <td className="num r hidden md:table-cell" style={{ color: p.uptime_24h < 0.99 ? 'var(--warn)' : 'var(--ink)' }}>94                    {fmtPct(p.uptime_24h, 1)}95                  </td>96                  <td className="num r hidden text-ink-2 lg:table-cell" style={{ color: Math.abs(p.clock_offset_ms) > 50 ? 'var(--warn)' : undefined }}>97                    {p.clock_offset_ms > 0 ? '+' : ''}98                    {p.clock_offset_ms} ms99                  </td>100                  <td className="num hidden text-ink-2 lg:table-cell">{p.version}</td>101                  <td className="hidden text-[11px] text-ink-3 md:table-cell">{p.capabilities.join(' · ')}</td>102                </>103              )}104              <td className="num r text-ink-2">105                <Time ts={p.last_seen} style="time" />106              </td>107            </tr>108          ))}109        </tbody>110      </table>111    </div>112  );113}114115export function LatencyMatrixTable({ rows, highlight }: { rows: LatencyPair[]; highlight?: string }) {116  if (!rows.length) return <Empty>No inter-region latency pairs for this scope.</Empty>;117  return (118    <div className="scroll-x -mx-3 px-3">119      <table className="tbl">120        <thead>121          <tr>122            <th>From</th>123            <th>To</th>124            <th className="r">RTT</th>125            <th className="r hidden sm:table-cell">Baseline</th>126            <th className="r">Δ</th>127            <th className="r hidden sm:table-cell">TTFB</th>128            <th className="r">Loss</th>129            <th className="r">z</th>130            <th className="r hidden md:table-cell">Pairs</th>131          </tr>132        </thead>133        <tbody>134          {rows.map((m) => {135            const d = m.rtt_ms - m.rtt_ms_baseline;136            return (137              <tr key={`${m.from}-${m.to}`}>138                <td className={m.from === highlight ? 'text-ink' : 'text-ink-2'}>139                  <Link href={`/internet/${m.from}`} className="hover:text-accent">140                    {m.from}141                  </Link>142                </td>143                <td className={m.to === highlight ? 'text-ink' : 'text-ink-2'}>144                  <Link href={`/internet/${m.to}`} className="hover:text-accent">145                    {m.to}146                  </Link>147                </td>148                <td className="num r">{fmtMs(m.rtt_ms, 1)}</td>149                <td className="num r hidden text-ink-2 sm:table-cell">{fmtMs(m.rtt_ms_baseline, 1)}</td>150                <td className="num r" style={{ color: d > 5 ? 'var(--p-stressed)' : d < -5 ? 'var(--p-calm)' : 'var(--ink-2)' }}>151                  {d > 0 ? '+' : ''}152                  {fmt(d, 1)}153                </td>154                <td className="num r hidden text-ink-2 sm:table-cell">{fmtMs(m.ttfb_ms)}</td>155                <td className="num r" style={{ color: m.loss_pct >= 1 ? 'var(--p-high)' : 'var(--ink)' }}>156                  {fmt(m.loss_pct)} %157                </td>158                <td className="num r" style={{ color: Math.abs(m.z) >= 3 ? 'var(--p-high)' : Math.abs(m.z) >= 1.5 ? 'var(--p-elevated)' : 'var(--ink)' }}>159                  {fmt(m.z)}160                </td>161                <td className="num r hidden text-ink-2 md:table-cell">{fmtInt(m.pairs)}</td>162              </tr>163            );164          })}165        </tbody>166      </table>167    </div>168  );169}170171export function LinkList({ items, hrefFor, label }: { items: { key: string; name: string; pressure: number; sub?: string }[]; hrefFor: (k: string) => string; label: string }) {172  if (!items.length) return <Empty>No {label} in this scope.</Empty>;173  return (174    <ul className="divide-y divide-line">175      {[...items]176        .sort((a, b) => b.pressure - a.pressure)177        .map((i) => (178          <li key={i.key} className="flex items-baseline justify-between gap-3 py-1.5 text-[13px]">179            <Link href={hrefFor(i.key)} className="truncate text-ink hover:text-accent">180              {i.name}181              {i.sub && <span className="num ml-2 text-[10.5px] text-ink-3">{i.sub}</span>}182            </Link>183            <PNum value={i.pressure} />184          </li>185        ))}186    </ul>187  );188}189