Add Prettier and ESLint tooling (Refs #77)
This commit is contained in:
+32
-10
@@ -1,17 +1,28 @@
|
||||
const numberFormat = new Intl.NumberFormat('en-US', { maximumFractionDigits: 1 });
|
||||
|
||||
/** Label the actual bucket start in the chosen timezone; never imply local calendar-day buckets. */
|
||||
export function metricPeriodLabels(points: readonly { startAt: number }[], days: 1 | 7 | 30, timeZone: string) {
|
||||
export function metricPeriodLabels(
|
||||
points: readonly { startAt: number }[],
|
||||
days: 1 | 7 | 30,
|
||||
timeZone: string
|
||||
) {
|
||||
const stride = days === 7 ? 1 : Math.max(1, Math.ceil(points.length / 6));
|
||||
const weekday = new Intl.DateTimeFormat('en-US', { timeZone, weekday: 'short' });
|
||||
const date = new Intl.DateTimeFormat('en-US', { timeZone, day: 'numeric' });
|
||||
const clock = new Intl.DateTimeFormat('en-US', { timeZone, hour: 'numeric' });
|
||||
return points.flatMap((point, index) => index % stride ? [] : [{
|
||||
index,
|
||||
position: (index + 0.5) / points.length * 100,
|
||||
label: days === 1 ? clock.format(point.startAt) : weekday.format(point.startAt),
|
||||
date: days === 30 ? date.format(point.startAt) : ''
|
||||
}]);
|
||||
return points.flatMap((point, index) =>
|
||||
index % stride
|
||||
? []
|
||||
: [
|
||||
{
|
||||
index,
|
||||
position: ((index + 0.5) / points.length) * 100,
|
||||
label:
|
||||
days === 1 ? clock.format(point.startAt) : weekday.format(point.startAt),
|
||||
date: days === 30 ? date.format(point.startAt) : ''
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
export function metricNumber(value: number): string {
|
||||
@@ -22,7 +33,7 @@ export function metricNumber(value: number): string {
|
||||
|
||||
export function metricPercent(value: number, total: number): string {
|
||||
if (!Number.isFinite(value) || !Number.isFinite(total) || total <= 0) return '—';
|
||||
const percent = 100 * value / total;
|
||||
const percent = (100 * value) / total;
|
||||
return percent > 0 && percent < 0.1 ? '<0.1%' : `${percent.toFixed(1)}%`;
|
||||
}
|
||||
|
||||
@@ -38,7 +49,11 @@ export function metricDuration(hours: number): string {
|
||||
}
|
||||
|
||||
/** Missing evidence always sorts last, in either direction. */
|
||||
export function compareMetricValues(left: number | null, right: number | null, direction: 'asc' | 'desc'): number {
|
||||
export function compareMetricValues(
|
||||
left: number | null,
|
||||
right: number | null,
|
||||
direction: 'asc' | 'desc'
|
||||
): number {
|
||||
const a = left !== null && Number.isFinite(left) ? left : null;
|
||||
const b = right !== null && Number.isFinite(right) ? right : null;
|
||||
if (a === null || b === null) return a === b ? 0 : a === null ? 1 : -1;
|
||||
@@ -51,5 +66,12 @@ export function metricPage<T>(rows: T[], requested: string | null, size = 15) {
|
||||
const pages = Math.max(1, Math.ceil(rows.length / size));
|
||||
const page = Math.min(pages, Number.isSafeInteger(parsed) && parsed > 0 ? parsed : 1);
|
||||
const start = (page - 1) * size;
|
||||
return { page, pages, rows: rows.slice(start, start + size), start: rows.length ? start + 1 : 0, end: Math.min(rows.length, start + size), total: rows.length };
|
||||
return {
|
||||
page,
|
||||
pages,
|
||||
rows: rows.slice(start, start + size),
|
||||
start: rows.length ? start + 1 : 0,
|
||||
end: Math.min(rows.length, start + size),
|
||||
total: rows.length
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user