// Read-only dashboard HTML renderer (task sqsmupwn). // // This is the PRESENTATION half: a pure function from the typed `DashboardStats` // (see stats.ts) to a single HTML document. Charts are inline ``, styling // is one inline `

No events received in the last ${escapeHtml(trend.windowDays)} days.

`; } const width = 720; const height = 140; const pad = 8; const padLeft = 34; const padBottom = 22; const max = Math.max(1, ...pts.map((p) => Math.max(p.installs, p.usage))); const innerW = width - padLeft - pad; const innerH = height - pad - padBottom; const baseY = pad + innerH; const stepX = pts.length > 1 ? innerW / (pts.length - 1) : 0; const coordsFor = (value: (p: (typeof pts)[number]) => number) => pts.map((p, i) => { const x = padLeft + (pts.length > 1 ? i * stepX : innerW / 2); const y = pad + innerH - (value(p) / max) * innerH; return `${x.toFixed(1)},${y.toFixed(1)}`; }); const dotsFor = (coords: string[], value: (p: (typeof pts)[number]) => number, label: string, cls: string) => pts .map((p, i) => { const [x, y] = coords[i].split(","); return `${escapeHtml(p.day)}: ${escapeHtml( value(p), )} ${label}`; }) .join(""); const installCoords = coordsFor((p) => p.installs); const usageCoords = coordsFor((p) => p.usage); const yTicks = [...new Set([0, Math.round(max / 2), max])].map((value) => { const y = pad + innerH - (value / max) * innerH; return ` ${value > 0 ? `` : ""} ${escapeHtml(value)}`; }); const xLabelIndices = [...new Set(pts.length > 1 ? [0, Math.floor((pts.length - 1) / 2), pts.length - 1] : [0])]; const xTicks = xLabelIndices.map((i) => { const x = padLeft + (pts.length > 1 ? i * stepX : innerW / 2); const anchor = i === 0 && pts.length > 1 ? "start" : i === pts.length - 1 ? "end" : "middle"; return ` ${escapeHtml( pts[i].day.slice(5), )}`; }); return `
  • New installs / day
  • Usage / day
${yTicks.join("\n ")} ${xTicks.join("\n ")} ${dotsFor(usageCoords, (p) => p.usage, "active", "usage")} ${dotsFor(installCoords, (p) => p.installs, "new", "installs")}

peak ${escapeHtml(max)} / day · ${escapeHtml( pts.length, )} active day(s) in window

`; } function bar(value: number, max: number): string { const width = max > 0 ? Math.max(2, Math.round((value / max) * 100)) : 0; return ``; } function pie(buckets: OsBucket[]): string { const slices = buckets.filter((b) => b.installs > 0); const total = slices.reduce((s, b) => s + b.installs, 0); if (total === 0) return `

No platform data in window.

`; const r = 56; const cx = 80; const cy = 80; const stroke = 24; const circumference = 2 * Math.PI * r; let acc = 0; const ring = slices .map((b) => { const frac = b.installs / total; const len = frac * circumference; const dash = `${len.toFixed(2)} ${(circumference - len).toFixed(2)}`; const offset = (-acc * circumference).toFixed(2); acc += frac; return `${escapeHtml(OS_LABEL[b.family])}: ${escapeHtml( b.installs, )}`; }) .join(""); const legend = slices .map( (b) => `
  • ${escapeHtml(OS_LABEL[b.family])} ${escapeHtml(b.installs)} · ${pct(b.installs, total)}
  • `, ) .join(""); return `
    ${ring}
      ${legend}
    `; } function metric(value: number, label: string): string { return `
    ${escapeHtml(value)}
    ${escapeHtml(label)}
    `; } function windowControl(windowDays: number): string { return `
    days
    `; } function renderVersions(rows: VersionRow[]): string { if (rows.length === 0) return emptySection("Version adoption", "No events in window."); const max = Math.max(1, ...rows.map((r) => r.installs)); const body = rows .map( (r) => ` ${escapeHtml(r.app_version)} ${escapeHtml(r.installs)} ${bar(r.installs, max)} `, ) .join(""); return `

    Version adoption

    Distinct installs by their current app_version (latest event in window).

    ${body}
    VersionInstalls
    `; } function renderCrashList(items: string[], label: string): string { if (items.length === 0) return `

    no ${escapeHtml(label)}

    `; const lines = items.map((l) => `
  • ${escapeHtml(l)}
  • `).join(""); return `
    ${escapeHtml(label)}
      ${lines}
    `; } function renderCrashes(rows: CrashGroup[]): string { if (rows.length === 0) return emptySection("Crash groups", "No crashes reported."); const body = rows .map( (g) => `
    ${escapeHtml(g.count)}× ${escapeHtml(g.app_version)} ${escapeHtml(g.message)} last ${escapeHtml(g.lastSeen)} ${renderCrashList(g.backtrace, "backtrace")} ${renderCrashList(g.context_log, "context log")}
    `, ) .join(""); return `

    Crash groups

    Grouped by app_version + message. Expand a row for its most recent backtrace and context log.

    ${body}
    `; } function renderOverview(stats: DashboardStats): string { const tiles = `
    ${metric(stats.installs.totalDistinct, `distinct installs (last ${stats.windowDays} days)`)} ${metric(stats.crashTotal, `crashes (last ${stats.windowDays} days)`)}
    `; return `
    ${renderSchemas(stats.schemas)} ${windowControl(stats.windowDays)} ${tiles}

    Distinct anon_id = sha256(machine_id), one per install. This is install count, not user count.

    Installs by OS

    ${pie(stats.osBuckets)}

    Trends

    ${sparkline(stats.installs)}
    ${renderVersions(stats.versions)} ${renderCrashes(stats.crashes)}
    `; } function renderPlatforms(rows: PlatformRow[]): string { const inner = rows.length === 0 ? emptySection("Platform breakdown", "No environment rows yet.") : platformTable(rows); return `
    ${inner}
    `; } function platformTable(rows: PlatformRow[]): string { const max = Math.max(1, ...rows.map((r) => r.installs)); const body = rows .map( (r) => ` ${escapeHtml(r.os)} ${escapeHtml(r.os_version)} ${escapeHtml(r.arch)} ${escapeHtml(r.installs)} ${bar(r.installs, max)} `, ) .join(""); return `

    Platform breakdown

    Distinct installs by their current OS / version / arch (latest environment report in window), so each install is counted once. The literal "unknown" bucket is shown, never hidden.

    ${body}
    OSOS versionArchInstalls
    `; } function renderScreens(rows: ScreenRow[]): string { const inner = rows.length === 0 ? emptySection("Screen breakdown", "No environment rows yet.") : screenTable(rows); return `
    ${inner}
    `; } function screenTable(rows: ScreenRow[]): string { const max = Math.max(1, ...rows.map((r) => r.installs)); const body = rows .map( (r) => ` ${escapeHtml(r.window_size)} ${escapeHtml(r.screen_size)} ${escapeHtml(r.installs)} ${bar(r.installs, max)} `, ) .join(""); return `

    Screen breakdown

    Distinct installs by their current window size / screen size (latest environment report in window), so each install is counted once. The literal "unknown" bucket is shown, never hidden.

    ${body}
    Window sizeScreen sizeCount
    `; } function renderFeatures(features: FeatureRow[], performance: PerformanceRow[]): string { return `
    ${featuresTable(features)}
    ${performanceTable(performance)}
    `; } function featuresTable(rows: FeatureRow[]): string { if (rows.length === 0) return emptySection("Top features", "No usage events yet."); const max = Math.max(1, ...rows.map((r) => r.count)); const body = rows .map((r) => { const toggle = r.toggledOn === null ? "" : ` (${escapeHtml(r.toggledOn)} on / ${escapeHtml( r.count - r.toggledOn, )} off)`; return ` ${escapeHtml(r.event_kind)} ${escapeHtml(r.name)}${toggle} ${escapeHtml(r.count)} ${bar(r.count, max)} `; }) .join(""); return `

    Top features

    Usage events by kind and name. feature_toggle rows show the on/off split.

    ${body}
    KindNameEvents
    `; } function performanceTable(rows: PerformanceRow[]): string { if (rows.length === 0) return emptySection("Performance", "No performance rows yet."); const body = rows .map( (r) => ` ${escapeHtml(r.name)} ${escapeHtml(r.samples)} ${num(r.avgLoadMs)} ${num(r.avgFrameP95Ms)} ${num(r.avgHeapMb)} `, ) .join(""); return `

    Performance

    Averages per view over the performance stream.

    ${body}
    ViewSamplesAvg load (ms)Avg frame p95 (ms)Avg heap (MB)
    `; } function renderLanguages(rows: LanguageRow[]): string { const inner = rows.length === 0 ? emptySection("Language breakdown", "No environment rows yet.") : languageTable(rows); return `
    ${inner}
    `; } function languageTable(rows: LanguageRow[]): string { const max = Math.max(1, ...rows.map((r) => r.installs)); const body = rows .map( (r) => ` ${escapeHtml(r.app_language)} ${escapeHtml(r.installs)} ${bar(r.installs, max)} `, ) .join(""); return `

    Language breakdown

    Distinct installs by their current chosen UI app_language (the in-app language pick, not the OS locale; latest environment report in window), so each install is counted once. The literal "unknown" bucket is shown, never hidden.

    ${body}
    LanguageInstalls
    `; } function renderSchemas(rows: SchemaRow[]): string { if (rows.length <= 1) return ""; const body = rows .map( (r) => ` ${escapeHtml(r.schema)} ${escapeHtml(r.events)} ${escapeHtml(r.crashes)} `, ) .join(""); return `

    Schema mix

    More than one contract schema is present. Panels aggregate across versions; interpret with care.

    ${body}
    SchemaEvent rowsCrash rows
    `; } function emptySection(title: string, msg: string): string { return `

    ${escapeHtml(title)}

    ${escapeHtml(msg)}

    `; } const STYLE = ` :root { color-scheme: dark; } * { box-sizing: border-box; } body { font: 15px/1.5 'Space Grotesk', system-ui, -apple-system, sans-serif; margin: 0; padding: 2rem 1.25rem 4rem; max-width: 960px; margin-inline: auto; color: ${T.ink}; background: ${T.paperSunk}; } h1 { font-size: 1.5rem; margin: 0 0 .25rem; letter-spacing: -.01em; } h2 { font-size: 1.05rem; margin: 0 0 .5rem; } .sub-hd { color: ${T.muted}; margin: 0 0 1.5rem; font-size: .9rem; } section { background: ${T.paper}; border: 1px solid ${T.rule}; border-radius: 12px; padding: 1.25rem; margin-bottom: 1.25rem; } section section { background: ${T.paperRaised}; } section.warn { border-color: ${T.warning}; background: ${T.paperRaised}; } code { background: ${T.paperSunk}; padding: .05rem .3rem; border-radius: 4px; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: .85em; color: ${T.plasma}; } .note { color: ${T.muted}; font-size: .85rem; margin: .25rem 0 .75rem; } .empty { color: ${T.veryMuted}; font-style: italic; } table { width: 100%; border-collapse: collapse; } th, td { text-align: left; padding: .35rem .5rem; border-bottom: 1px solid ${T.rule}; vertical-align: middle; } th { font-size: .75rem; text-transform: uppercase; letter-spacing: .04em; color: ${T.veryMuted}; } td.n, th.n { text-align: right; font-variant-numeric: tabular-nums; font-family: 'JetBrains Mono', ui-monospace, monospace; } td.barcell { width: 30%; } .bar { display: inline-block; height: 10px; border-radius: 5px; background: ${T.plasma}; min-width: 2px; } .sub { color: ${T.veryMuted}; font-size: .8em; } .tiles { display: flex; gap: 1rem; flex-wrap: wrap; margin: .5rem 0 1rem; } .tile { flex: 1 1 180px; background: ${T.paperRaised}; border: 1px solid ${T.rule}; border-radius: 10px; padding: 1rem 1.1rem; } .tile-n { font-size: 2.1rem; font-weight: 700; font-variant-numeric: tabular-nums; color: ${T.ink}; } .tile-l { color: ${T.muted}; font-size: .8rem; } .window-control { display: flex; align-items: center; gap: .5rem; font-size: .85rem; color: ${T.muted}; margin-bottom: .5rem; } .window-control input { width: 5rem; background: ${T.paperSunk}; color: ${T.ink}; border: 1px solid ${T.ruleStrong}; border-radius: 6px; padding: .25rem .4rem; font: inherit; } .window-control button { background: ${T.plasmaSoft}; color: ${T.plasma}; border: 1px solid ${T.plasma}; border-radius: 6px; padding: .25rem .7rem; font: inherit; cursor: pointer; } .pie-wrap { display: flex; gap: 1.5rem; align-items: center; flex-wrap: wrap; } svg.pie { width: 160px; height: 160px; flex: 0 0 auto; } .legend { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; } .legend li { display: flex; align-items: center; gap: .5rem; } .swatch { width: .8rem; height: .8rem; border-radius: 3px; display: inline-block; } .lg-label { min-width: 5rem; } .lg-n { color: ${T.muted}; font-variant-numeric: tabular-nums; font-size: .85rem; } svg.spark { width: 100%; height: auto; display: block; margin: .5rem 0 .25rem; } svg.spark .line { stroke: ${T.plasma}; stroke-width: 2; } svg.spark .line.usage { stroke: ${T.success}; } svg.spark .axis { stroke: ${T.ruleStrong}; stroke-width: 1; } svg.spark .grid { stroke: ${T.rule}; stroke-width: 1; stroke-dasharray: 2 4; } svg.spark .tick { fill: ${T.veryMuted}; font: 9px 'JetBrains Mono', ui-monospace, monospace; } svg.spark circle { fill: ${T.plasma}; } svg.spark circle.usage { fill: ${T.success}; } .spark-legend { display: flex; gap: 1.25rem; margin-top: .25rem; } .caption { color: ${T.veryMuted}; font-size: .8rem; margin: 0; } details { border-bottom: 1px solid ${T.rule}; padding: .4rem 0; } summary { cursor: pointer; display: flex; gap: .6rem; align-items: baseline; flex-wrap: wrap; } .cr-count { font-weight: 700; color: ${T.danger}; font-variant-numeric: tabular-nums; } .cr-ver { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: .85em; color: ${T.muted}; } .cr-msg { flex: 1; } .cr-seen { color: ${T.veryMuted}; font-size: .8em; } .cr-block { margin: .5rem 0 .25rem 1rem; } .cr-block ol { margin: .25rem 0; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: .8rem; color: ${T.muted}; } .tab { position: absolute; left: -9999px; opacity: 0; } .tabnav { display: flex; gap: .25rem; border-bottom: 1px solid ${T.ruleStrong}; margin-bottom: 1.25rem; flex-wrap: wrap; } .tabnav label { cursor: pointer; padding: .5rem .9rem; color: ${T.muted}; border-bottom: 2px solid transparent; margin-bottom: -1px; font-weight: 500; } .tabnav label:hover { color: ${T.ink}; } .panel { display: none; } #tab-overview:checked ~ .tabnav label[for="tab-overview"], #tab-platforms:checked ~ .tabnav label[for="tab-platforms"], #tab-screens:checked ~ .tabnav label[for="tab-screens"], #tab-features:checked ~ .tabnav label[for="tab-features"], #tab-languages:checked ~ .tabnav label[for="tab-languages"] { color: ${T.ink}; border-bottom-color: ${T.plasma}; } #tab-overview:checked ~ #panel-overview, #tab-platforms:checked ~ #panel-platforms, #tab-screens:checked ~ #panel-screens, #tab-features:checked ~ #panel-features, #tab-languages:checked ~ #panel-languages { display: block; } .subtab { position: absolute; left: -9999px; opacity: 0; } .subnav { display: flex; gap: .25rem; margin-bottom: 1rem; } .subnav label { cursor: pointer; padding: .3rem .8rem; color: ${T.muted}; border: 1px solid ${T.rule}; border-radius: 6px; font-size: .85rem; } .subnav label:hover { color: ${T.ink}; } .subpanel { display: none; } #ftab-top:checked ~ .subnav label[for="ftab-top"], #ftab-perf:checked ~ .subnav label[for="ftab-perf"] { color: ${T.ink}; border-color: ${T.plasma}; } #ftab-top:checked ~ #subpanel-top, #ftab-perf:checked ~ #subpanel-perf { display: block; } footer { color: ${T.veryMuted}; font-size: .8rem; text-align: center; margin-top: 2rem; } `; export function renderDashboard(stats: DashboardStats): string { return ` pod telemetry · maintainer dashboard

    pod telemetry dashboard

    Read-only aggregates over opt-in telemetry. Generated ${escapeHtml(stats.generatedAt)}.

    ${renderOverview(stats)} ${renderPlatforms(stats.platforms)} ${renderScreens(stats.screens)} ${renderFeatures(stats.features, stats.performance)} ${renderLanguages(stats.languages)}
    `; }