@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
198 lines (197 loc) • 9.62 kB
JavaScript
import * as React from 'react';
import { Box, Flex, Text } from 'rebass';
import { CheckBox } from '../../../../components/CheckBox';
import DropdownButton from '../../../../components/DropdownButton';
import FormLayout, { FormRow } from '../../../../components/FormLayout';
import { Tabs } from '../../../../components/Tabs';
import { Tag } from '../../../../components/Tag';
import { useAdaptable } from '../../../AdaptableContext';
import { ValueSelector } from '../../../Components/ValueSelector';
import { useOnePageAdaptableWizardContext } from '../../../Wizard/OnePageAdaptableWizard';
import { columnFilter } from './Utilities';
import ArrayExtensions from '../../../../Utilities/Extensions/ArrayExtensions';
const WEIGHTED_AVERAGE_AGG_FN_NAME = 'weightedAvg';
export const isAggregationsSectionValid = (data) => {
const weightedAvg = data.TableAggregationColumns
? (data.TableAggregationColumns || []).find(({ AggFunc }) => typeof AggFunc === 'object' &&
AggFunc.type === 'weightedAverage')?.AggFunc
: null;
if (weightedAvg && !weightedAvg.weightedColumnId) {
return 'The Weighted Average Aggregation requires a Weighted Column';
}
return true;
};
export const AggregationsSectionSummary = () => {
const adaptable = useAdaptable();
const { data: layout } = useOnePageAdaptableWizardContext();
const entries = layout.TableAggregationColumns || [];
let content = null;
if (entries.length) {
content = (React.createElement(FormLayout, null, entries.map(({ ColumnId, AggFunc }) => (React.createElement(FormRow, { key: ColumnId, label: adaptable.api.columnApi.getFriendlyNameForColumnId(ColumnId) },
React.createElement(Tag, null, typeof AggFunc === 'object' ? AggFunc.type : AggFunc))))));
}
else {
content = React.createElement(Tag, null, "No Aggregations");
}
return React.createElement(Box, null, content);
};
const ColumnRow = (props) => {
const adaptable = useAdaptable();
const aggValue = props.layout?.TableAggregationColumns?.find((agg) => agg.ColumnId === props.column.columnId)?.AggFunc;
const adaptableAggFunctions = [];
if (props.column.dataType === 'number') {
adaptableAggFunctions.push(WEIGHTED_AVERAGE_AGG_FN_NAME);
}
const aggOptions = [...props.column.availableAggregationFunctions, ...adaptableAggFunctions].map((fnName) => {
return {
label: fnName,
onClick: () => {
let aggCols = props.layout.TableAggregationColumns || [];
if (!aggCols) {
return;
}
const AggFuncValue = fnName === WEIGHTED_AVERAGE_AGG_FN_NAME
? {
type: 'weightedAverage',
weightedColumnId: null,
}
: fnName;
let found = false;
aggCols = aggCols.map(({ ColumnId, AggFunc }) => {
if (ColumnId === props.column.columnId) {
found = true;
return {
ColumnId,
AggFunc: AggFuncValue,
};
}
return { ColumnId, AggFunc };
});
if (!found) {
aggCols.push({
ColumnId: props.column.columnId,
AggFunc: AggFuncValue,
});
}
props.onChangeAggFunction(aggCols);
},
};
});
const numericColumnsOptions = props.numberColumns
.filter((col) => col.columnId !== props.column.columnId)
.map((col) => {
return {
label: col.friendlyName,
onClick: () => {
let aggCols = [...(props.layout.TableAggregationColumns || [])];
if (!aggCols || !aggCols.length) {
return;
}
const AggFuncValue = {
type: 'weightedAverage',
weightedColumnId: col.columnId,
};
let found = false;
aggCols = aggCols.map(({ ColumnId, AggFunc }) => {
if (ColumnId === props.column.columnId) {
found = true;
return {
ColumnId,
AggFunc: AggFuncValue,
};
}
return { ColumnId, AggFunc };
});
if (!found) {
aggCols.push({
ColumnId: props.column.columnId,
AggFunc: AggFuncValue,
});
}
props.onChangeAggFunction(aggCols);
},
};
});
const currentAggFnName = props.aggregationColumnsMap[props.column.columnId];
let weightName = null;
if (typeof aggValue === 'object' && aggValue.type === 'weightedAverage') {
weightName = aggValue.weightedColumnId
? adaptable.api.columnApi.getFriendlyNameForColumnId(aggValue.weightedColumnId)
: 'Select Weight';
}
return (React.createElement(Flex, { alignItems: "center" },
props.column.friendlyName,
aggValue && (React.createElement(DropdownButton, { columns: ['label'], items: aggOptions, ml: 2 }, currentAggFnName)),
currentAggFnName === WEIGHTED_AVERAGE_AGG_FN_NAME && (React.createElement(Flex, { backgroundColor: "primary", ml: 3, alignItems: "center" },
React.createElement(Text, null, "Weight"),
' ',
React.createElement(DropdownButton, { columns: ['label'], items: numericColumnsOptions, ml: 2 }, weightName)))));
};
export const AggregationsSection = (props) => {
const adaptable = useAdaptable();
const { data: layout } = useOnePageAdaptableWizardContext();
const allAggregableColumns = adaptable.api.columnApi.getAggregatableColumns();
const allColumns = adaptable.api.columnApi.getUIAvailableColumns();
const numberColumns = adaptable.api.columnApi.getNumericColumns();
const sortedAggregableColumns = React.useMemo(() => {
return ArrayExtensions.sortArrayWithOrder(allAggregableColumns.map((col) => col.columnId), (layout.TableAggregationColumns ?? []).map((agg) => agg.ColumnId), { sortUnorderedItems: false }).map((colId) => adaptable.api.columnApi.getColumnWithColumnId(colId));
}, [layout, allAggregableColumns]);
const handleColumnsSelectionChange = React.useCallback((columnIds) => {
const currentAggsMap = (layout.TableAggregationColumns || []).reduce((acc, { ColumnId, AggFunc }) => {
acc[ColumnId] = AggFunc;
return acc;
}, {});
props.onChange({
...layout,
TableAggregationColumns: columnIds.map((colId) => {
const AggFunc = currentAggsMap[colId] ?? adaptable.api.columnApi.getDefaultAggFunc(colId);
return {
ColumnId: colId,
AggFunc,
};
}),
});
}, [layout]);
const handleAggregationChange = React.useCallback((aggFunctions) => {
props.onChange({
...layout,
TableAggregationColumns: aggFunctions,
});
}, [layout]);
const aggregationColumnsMap = React.useMemo(() => {
const allColumnsMap = allColumns.reduce((acc, col) => {
acc[col.columnId] = col;
return acc;
}, {});
return (layout.TableAggregationColumns || []).reduce((acc, { ColumnId: colId, AggFunc }) => {
let fn = AggFunc;
let fnName = '';
if (typeof fn === 'boolean') {
fnName = allColumnsMap[colId].aggregationFunction;
}
if (typeof fn === 'object' && fn.type === 'weightedAverage') {
fnName = WEIGHTED_AVERAGE_AGG_FN_NAME;
}
else if (typeof fn === 'string') {
fnName = fn;
}
acc[colId] = fnName;
return acc;
}, {});
}, [layout]);
const handleSuppressAggFuncInHeader = (checked) => {
props.onChange({
...layout,
SuppressAggFuncInHeader: checked,
});
};
return (React.createElement(Tabs, { style: { height: '100%' } },
React.createElement(Tabs.Tab, null, "Column Aggregations"),
React.createElement(Tabs.Content, null,
React.createElement(Flex, null,
React.createElement(FormLayout, null,
React.createElement(CheckBox, { checked: layout.SuppressAggFuncInHeader, onChange: handleSuppressAggFuncInHeader }, "Suppress Aggregation Function Text in Column Header"))),
React.createElement(ValueSelector, { showFilterInput: true, showSelectedOnlyPosition: "top", filter: columnFilter, toIdentifier: (option) => `${option.columnId}`, toLabel: (option) => option.friendlyName ?? option.columnId, toListLabel: (column) => (React.createElement(ColumnRow, { onChangeAggFunction: handleAggregationChange, layout: layout, column: column, aggregationColumnsMap: aggregationColumnsMap, numberColumns: numberColumns })), options: sortedAggregableColumns, value: (layout.TableAggregationColumns || []).map((agg) => agg.ColumnId), allowReorder: () => true, xSelectedLabel: () => {
return `Active aggregations:`;
}, onChange: handleColumnsSelectionChange }))));
};