Files
inbuxa-admin/src/features/dashboard/rhythm.ts
T
jcoffey-dev 5bf09ceed5 Dashboard: every number leads somewhere, real counts, and new charts
- Cards and charts link to the page they're about: pending messages to the
  queue, bans to blocked IPs, report warnings to the reports, and so on,
  shown only to viewers who may open that page.
- A one-line status under the greeting: what needs a look (failed tasks,
  messages retrying, recipients given up on) or, when nothing does, what's
  there. Each phrase is a link.
- Counts from the server's own objects stand in for live metrics it can't
  report, and a live number with no source reads as unknown, not zero.
- Who uses the space: a treemap of people sized by storage, colored by how
  near their quota they are, each tile opening the account.
- Where mail is waiting: queued recipients by destination, split into
  waiting, retrying and given up, each row opening the filtered queue.
- The weekly rhythm: messages by hour and weekday, shown once metric
  history exists.
- Dashboard tabs are titled by their label.
2026-09-19 01:50:07 -07:00

29 lines
890 B
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* SPDX-FileCopyrightText: 2026 Coffey Labs
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import type { Metric } from './types/metrics';
/** Received plus sent: every message the server handled. */
export const RHYTHM_METRICS = [
'queue.message-queued',
'queue.authenticated-message-queued',
'queue.dsn-queued',
'queue.report-queued',
];
/** Sum the samples into a 7×24 grid, Monday first, in the viewer's time zone. */
export function weeklyGrid(samples: Metric[], metrics: string[] = RHYTHM_METRICS): number[][] {
const want = new Set(metrics);
const grid = Array.from({ length: 7 }, () => new Array<number>(24).fill(0));
for (const s of samples) {
if (!want.has(s.metric) || !s.timestamp) continue;
const d = new Date(s.timestamp);
if (Number.isNaN(d.getTime())) continue;
grid[(d.getDay() + 6) % 7][d.getHours()] += s.count;
}
return grid;
}