spb/internetpressure
Public
TypeScript 36.3%
Python 31.8%
Go 18%
JavaScript 9.8%
Shell 1.9%
SQL 1.4%
CSS 0.5%
1'use client';23import { useState } from 'react';4import { fmtInt } from '@/lib/format';5import type { AdminRaw } from '@/lib/types';6import { AdminPage, ErrorNote, Field, inputCls, useAdmin } from './shared';78const TABLES = ['measurements', 'traceroutes', 'bgp_events', 'bgp_stats', 'pressure_history', 'signal_features', 'probe_health'];910export function Raw() {11 const [table, setTable] = useState('measurements');12 const [probe, setProbe] = useState('');13 const [target, setTarget] = useState('');14 const [limit, setLimit] = useState(100);15 const { data, err, loading } = useAdmin<AdminRaw>('/raw', { table, probe_id: probe || undefined, target_id: target || undefined, limit });16 return (17 <AdminPage title="Raw explorer" desc="Latest rows of a ClickHouse table, newest first. Read-only, capped at 200 rows.">18 <div className="grid grid-cols-2 gap-3 md:grid-cols-5">19 <Field label="table">20 <select value={table} onChange={(e) => setTable(e.target.value)} className={`${inputCls} num w-full`}>21 {TABLES.map((t) => (22 <option key={t}>{t}</option>23 ))}24 </select>25 </Field>26 <Field label="probe_id">27 <input value={probe} onChange={(e) => setProbe(e.target.value)} className={`${inputCls} num w-full`} />28 </Field>29 <Field label="target_id">30 <input value={target} onChange={(e) => setTarget(e.target.value)} className={`${inputCls} num w-full`} />31 </Field>32 <Field label="limit">33 <input type="number" min={1} max={200} value={limit} onChange={(e) => setLimit(Math.min(200, Math.max(1, Number(e.target.value) || 1)))} className={`${inputCls} num w-full`} />34 </Field>35 <div className="num flex items-end text-[11px] text-ink-3">{loading ? 'loading…' : data ? `${fmtInt(data.rows.length)} rows` : ''}</div>36 </div>37 <ErrorNote err={err} />38 {data && (39 <div className="scroll-x mt-3 max-h-[70vh] overflow-auto rounded-[4px] border border-line">40 <table className="tbl text-[11.5px]">41 <thead className="sticky top-0 bg-bg">42 <tr>43 {data.columns.map((c) => (44 <th key={c} className="num">45 {c}46 </th>47 ))}48 </tr>49 </thead>50 <tbody>51 {data.rows.map((r, i) => (52 <tr key={i}>53 {r.map((v, j) => (54 <td key={j} className="num max-w-[280px] truncate" title={String(v)}>55 {v === null || v === undefined ? <span className="text-ink-3">∅</span> : typeof v === 'boolean' ? (v ? 'true' : 'false') : String(v)}56 </td>57 ))}58 </tr>59 ))}60 </tbody>61 </table>62 </div>63 )}64 </AdminPage>65 );66}67