import { AGGREGATION_FUNCTIONS } from '../data-tools/' import type { ColumnAggregationMapType, ColumnState } from '../state' import type { CellValueParams, Column, GridRowId, GridRowMeta } from '../types' type ValueReturnType = number | Date | null export const getAggregationValueFn = ( footer: Column['footer'], cell: Column['cell'] ): ((props: CellValueParams) => ValueReturnType) | null => { if (footer?.value) { return footer.value } else if (cell?.value) { return cell.value } return null } export const getAggregationConfig = ( columns: ColumnState[] ): ColumnAggregationMapType[] => columns.reduce((prev: ColumnAggregationMapType[], curr) => { if (curr.data.footer?.aggregation !== undefined) { prev.push({ id: curr.id, fn: curr.data.footer.aggregation, value: getAggregationValueFn(curr.data.footer, curr.data.cell), }) } return prev }, []) const NO_META = {} export const getRowValues = ( rowIds: GridRowId[], entities: Map, meta: Map, aggregationFns: ColumnAggregationMapType[] ) => { const values = new Map() const getRow = (rowId: GridRowId) => entities.get(rowId) const getMeta = (rowId: GridRowId) => meta.get(rowId) || NO_META for (const id of rowIds) { const row = getRow(id) as any const rowMeta = getMeta(id) for (const aggregation of aggregationFns) { const columnId = aggregation.id if (!values.get(columnId)) { values.set(columnId, []) } const entry = values.get(columnId) const value = aggregation.value === null ? row[columnId] : aggregation.value({ columnId, row, rowMeta, }) if (value !== null && value !== undefined) { //TODO: We are pushing any value here. This is pretty flexible, which might be useful but harder to work with. //We might want to make this a strict number (and Date if we want to allow it but that will make typing more complex) entry?.push(value) } } } return values } export const getAggregationResults = ( aggregationFns: ColumnAggregationMapType[], values: Map ) => { const results = new Map< string, { result: number | Date | null values: Array } >() aggregationFns.forEach((a) => { const _fn = typeof a.fn === 'string' && AGGREGATION_FUNCTIONS[a.fn] ? AGGREGATION_FUNCTIONS[a.fn] : typeof a.fn === 'function' ? a.fn : () => null const _values = values.get(a.id) || [] const _result = _fn(_values) results.set(a.id, { values: _values, result: _result }) }) return results }