import { isNumericColumn } from './format.js'; import type { AggFn, ColumnMeta } from './types.js'; /** * Which summaries a column can honestly carry. * * Type decides, as it does everywhere else here: a text column has no total, * and a checkbox has no average worth showing. Offering only what the type * supports means the footer never holds a function the database would have to * refuse — the same bargain the cell editors make. * * A link column summarises by the label the grid shows, not by the row id it * stores, so counting the filled ones counts the rows that point somewhere. */ export function aggsFor(col: ColumnMeta): AggFn[] { if (col.type === 'checkbox') return ['checked', 'empty']; if (isNumericColumn(col)) return ['sum', 'avg', 'min', 'max', 'filled', 'empty']; if (col.type === 'date') return ['min', 'max', 'filled', 'empty']; return ['filled', 'empty', 'unique']; } export function isAggAllowed(col: ColumnMeta, fn: AggFn): boolean { return aggsFor(col).includes(fn); } /** * Whether the result is in the column's own units. * * A sum of a currency column is money and formats like the cells above it; a * count of the filled ones is a number of rows and must not pick up a currency * sign it has no business wearing. */ export function aggKeepsUnits(fn: AggFn): boolean { return fn === 'sum' || fn === 'avg' || fn === 'min' || fn === 'max'; } /** What the menu and the footer call the function, given the column it is on. */ export function aggLabel(fn: AggFn, col?: ColumnMeta): string { if (col?.type === 'date') { if (fn === 'min') return 'Earliest'; if (fn === 'max') return 'Latest'; } if (col?.type === 'checkbox' && fn === 'empty') return 'Unchecked'; switch (fn) { case 'sum': return 'Sum'; case 'avg': return 'Average'; case 'min': return 'Min'; case 'max': return 'Max'; case 'filled': return 'Filled'; case 'empty': return 'Empty'; case 'unique': return 'Unique'; case 'checked': return 'Checked'; } }