Spreadsheet-UX op een echte relationele engine
Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.
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';
}
}