SPB Git forge
7commits 1branches 0releases
229.0 KBsize
maindefault branch
12 days agolast push
TypeScript 91.8% HTML 3.2% JavaScript 3% SQL 1.4% CSS 0.7%
2.8 KB · 85 lines typescript
Raw Blame History
1export function fmtNum(n: number | string | null | undefined, digits = 0): string {2  if (n === null || n === undefined || n === "") return "—";3  const v = Number(n);4  if (Number.isNaN(v)) return String(n);5  if (Math.abs(v) >= 1e9) return (v / 1e9).toFixed(1) + "B";6  if (Math.abs(v) >= 1e6) return (v / 1e6).toFixed(1) + "M";7  if (Math.abs(v) >= 1e4) return (v / 1e3).toFixed(1) + "k";8  return v.toLocaleString("en-US", { maximumFractionDigits: digits });9}1011export function fmtPct(n: number | null | undefined, digits = 0): string {12  if (n === null || n === undefined || Number.isNaN(Number(n))) return "—";13  return `${(Number(n) * 100).toFixed(digits)}%`;14}1516export function fmtDuration(s: number | null | undefined): string {17  if (!s && s !== 0) return "—";18  const v = Math.round(Number(s));19  const h = Math.floor(v / 3600);20  const m = Math.floor((v % 3600) / 60);21  const sec = v % 60;22  return h ? `${h}:${String(m).padStart(2, "0")}:${String(sec).padStart(2, "0")}` : `${m}:${String(sec).padStart(2, "0")}`;23}2425export function fmtTime(ts: string | Date | null | undefined): string {26  if (!ts) return "—";27  const d = new Date(ts);28  return d.toLocaleTimeString("en-CA", { hour12: false });29}3031export function fmtDate(ts: string | Date | null | undefined): string {32  if (!ts) return "—";33  const d = new Date(ts);34  return d.toLocaleString("en-CA", { hour12: false, month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit" });35}3637export function ago(ts: string | Date | null | undefined): string {38  if (!ts) return "—";39  const diff = (Date.now() - new Date(ts).getTime()) / 1000;40  if (diff < 60) return `${Math.max(0, Math.round(diff))}s ago`;41  if (diff < 3600) return `${Math.round(diff / 60)}m ago`;42  if (diff < 86400) return `${Math.round(diff / 3600)}h ago`;43  return `${Math.round(diff / 86400)}d ago`;44}4546export function truncate(s: string | null | undefined, n: number): string {47  if (!s) return "";48  return s.length > n ? s.slice(0, n - 1) + "…" : s;49}5051export const TYPE_COLORS: Record<string, string> = {52  video: "#38e1ff",53  channel: "#9d7bff",54  profile: "#9d7bff",55  person: "#9d7bff",56  post: "#ffb347",57  comment: "#ff7ad9",58  community: "#43e69a",59  page: "#43e69a",60  hashtag: "#6b7a8c",61  image: "#38e1ff",62  organization: "#43e69a",63};6465export const EVENT_COLORS: Record<string, string> = {66  ACTION_PLANNED: "#ffb347",67  ACTION_EXECUTED: "#43e69a",68  ACTION_FAILED: "#ff5c7a",69  PAGE_OPENED: "#38e1ff",70  NETWORK_SCHEMA_DISCOVERED: "#9d7bff",71  CONNECTOR_PATTERN_LEARNED: "#9d7bff",72  CONNECTOR_DEGRADED: "#ff5c7a",73  CONNECTOR_REPAIRED: "#43e69a",74  LOOP_DETECTED: "#ff5c7a",75  AUTH_REQUIRED: "#ff5c7a",76  MEDIA_DISCOVERED: "#ff7ad9",77  VIDEO_DISCOVERED: "#38e1ff",78  POST_DISCOVERED: "#ffb347",79  PROFILE_DISCOVERED: "#9d7bff",80};8182export function eventColor(t: string): string {83  return EVENT_COLORS[t] ?? "#6b7a8c";84}85