diff --git a/web/app/globals.css b/web/app/globals.css
index f581895..479fe85 100644
--- a/web/app/globals.css
+++ b/web/app/globals.css
@@ -14,4 +14,8 @@ body {
background: var(--background);
color: var(--foreground);
font-family: ui-sans-serif, system-ui, sans-serif;
+}
+
+.u-legend .u-series:first-child {
+ display: none;
}
\ No newline at end of file
diff --git a/web/components/ChartCard/CardShell.tsx b/web/components/ChartCard/CardShell.tsx
index 485dead..5de90db 100644
--- a/web/components/ChartCard/CardShell.tsx
+++ b/web/components/ChartCard/CardShell.tsx
@@ -46,7 +46,7 @@ export function CardShell({ title, onEdit, onDelete, empty, children, legendCont
{/* Legend scrolls independently, capped at 25% card height */}
>
)}
diff --git a/web/components/ChartCard/TableViz.tsx b/web/components/ChartCard/TableViz.tsx
index d719a64..e41783a 100644
--- a/web/components/ChartCard/TableViz.tsx
+++ b/web/components/ChartCard/TableViz.tsx
@@ -14,27 +14,11 @@ interface Props {
export default function TableViz({ config, rows, onEdit, onDelete }: Props) {
const { localeMap } = useApp();
- const sortCol = config.signal_type === 'red' ? 'red' : 'green';
-
const latest = new Map();
for (const row of rows) {
latest.set(`${row.combinator}::${row.item_key}`, { green: row.green, red: row.red });
}
- const tableRows = [...latest.entries()]
- .sort((a, b) => {
- const va = a[1][sortCol] ?? 0;
- const vb = b[1][sortCol] ?? 0;
- switch (config.order_by) {
- case 'value_asc':
- case 'delta_asc':
- return va - vb;
- case 'abs_desc':
- return Math.abs(vb) - Math.abs(va);
- default:
- return vb - va;
- }
- })
- .slice(0, config.series_limit);
+ const tableRows = [...latest.entries()].slice(0, config.series_limit);
return (
@@ -57,12 +41,12 @@ export default function TableViz({ config, rows, onEdit, onDelete }: Props) {
{combinator} |
{config.signal_type !== 'red' && (
- {vals.green != null ? formatSI(vals.green) : '--'}
+ {vals.green != null ? formatSI(vals.green, undefined, 0) : '--'}
|
)}
{config.signal_type !== 'green' && (
- {vals.red != null ? formatSI(vals.red) : '--'}
+ {vals.red != null ? formatSI(vals.red, undefined, 0) : '--'}
|
)}
diff --git a/web/components/ChartCard/UpsChart.tsx b/web/components/ChartCard/UpsChart.tsx
index f19887a..18b5447 100644
--- a/web/components/ChartCard/UpsChart.tsx
+++ b/web/components/ChartCard/UpsChart.tsx
@@ -32,9 +32,9 @@ export default function UpsChart({ config, upsRows, timeMode, onEdit, onDelete }
const xAxis: uPlot.Axis = {
...AXIS_BASE,
- ...(timeMode === 'real' && {
- values: (_u, vals) => vals.map(v => v == null ? '' : new Date(v * 1000).toLocaleTimeString()),
- }),
+ values: timeMode === 'real'
+ ? (_u, vals) => vals.map(v => v == null ? '' : new Date(v * 1000).toLocaleTimeString())
+ : (_u, vals) => vals.map(v => v == null ? '' : formatSI(v)),
};
return new uPlot({
diff --git a/web/components/ChartCard/plotHelpers.ts b/web/components/ChartCard/plotHelpers.ts
index c7e1512..085839d 100644
--- a/web/components/ChartCard/plotHelpers.ts
+++ b/web/components/ChartCard/plotHelpers.ts
@@ -169,10 +169,11 @@ export function makeSignalsAxes(timeMode: 'real' | 'tick', locale?: string): uPl
return [
{
...AXIS_BASE,
- ...(timeMode === 'real' && {
- values: (_u: uPlot, vals: (number | null)[]) =>
- vals.map(v => v == null ? '' : new Date(v * 1000).toLocaleTimeString()),
- }),
+ values: timeMode === 'real'
+ ? (_u: uPlot, vals: (number | null)[]) =>
+ vals.map(v => v == null ? '' : new Date(v * 1000).toLocaleTimeString())
+ : (_u: uPlot, vals: (number | null)[]) =>
+ vals.map(v => v == null ? '' : formatSI(v, locale)),
},
{
...AXIS_BASE,
diff --git a/web/lib/formatNumber.ts b/web/lib/formatNumber.ts
index 5eda4e0..0fd03fa 100644
--- a/web/lib/formatNumber.ts
+++ b/web/lib/formatNumber.ts
@@ -4,19 +4,20 @@ const SI_THRESHOLDS = [
{ limit: 1_000, divisor: 1_000, suffix: 'K' },
] as const;
-export function formatSI(v: number, locale?: string): string {
+export function formatSI(v: number, locale?: string, fractionDigits?: number): string {
const abs = Math.abs(v);
+ const fd = fractionDigits ?? 3;
for (const { limit, divisor, suffix } of SI_THRESHOLDS) {
if (abs >= limit) {
const formatted = new Intl.NumberFormat(locale, {
- maximumFractionDigits: 3,
+ maximumFractionDigits: fd,
minimumFractionDigits: 0,
}).format(v / divisor);
return `${formatted}${suffix}`;
}
}
return new Intl.NumberFormat(locale, {
- maximumFractionDigits: 0,
+ maximumFractionDigits: fractionDigits != null ? fractionDigits : 0,
minimumFractionDigits: 0,
}).format(v);
}