chore(plugin-chart-pivot-table): migrate react-pivottable into superset codebase (#17769)

* chore(plugin-chart-pivot-table): migrate react-pivottable into superset codebase

* Fix lint errors

* Use named export

* Clean up the code
This commit is contained in:
Kamil Gabryjelski
2021-12-17 12:00:32 +01:00
committed by GitHub
parent c5af7a48df
commit 9c9edbe8bc
8 changed files with 2033 additions and 133 deletions

View File

@@ -28,15 +28,8 @@ import {
styled,
useTheme,
} from '@superset-ui/core';
// @ts-ignore
import PivotTable from '@superset-ui/react-pivottable/PivotTable';
import {
sortAs,
aggregatorTemplates,
// @ts-ignore
} from '@superset-ui/react-pivottable/Utilities';
import '@superset-ui/react-pivottable/pivottable.css';
import { isAdhocColumn } from '@superset-ui/chart-controls';
import { PivotTable, sortAs, aggregatorTemplates } from './react-pivottable';
import {
FilterType,
MetricsLayoutEnum,
@@ -63,6 +56,7 @@ const PivotTableWrapper = styled.div`
const METRIC_KEY = 'metric';
const iconStyle = { stroke: 'black', strokeWidth: '16px' };
const vals = ['value'];
const aggregatorsFactory = (formatter: NumberFormatter) => ({
Count: aggregatorTemplates.count(formatter),
@@ -142,17 +136,29 @@ export default function PivotTableChart(props: PivotTableProps) {
} = props;
const theme = useTheme();
const defaultFormatter = getNumberFormatter(valueFormat);
const columnFormatsArray = Object.entries(columnFormats);
const defaultFormatter = useMemo(
() => getNumberFormatter(valueFormat),
[valueFormat],
);
const columnFormatsArray = useMemo(
() => Object.entries(columnFormats),
[columnFormats],
);
const hasCustomMetricFormatters = columnFormatsArray.length > 0;
const metricFormatters =
hasCustomMetricFormatters &&
Object.fromEntries(
columnFormatsArray.map(([metric, format]) => [
metric,
getNumberFormatter(format),
]),
);
const metricFormatters = useMemo(
() =>
hasCustomMetricFormatters
? {
[METRIC_KEY]: Object.fromEntries(
columnFormatsArray.map(([metric, format]) => [
metric,
getNumberFormatter(format),
]),
),
}
: undefined,
[columnFormatsArray, hasCustomMetricFormatters],
);
const metricNames = useMemo(
() =>
@@ -179,18 +185,40 @@ export default function PivotTableChart(props: PivotTableProps) {
),
[data, metricNames],
);
const groupbyRows = groupbyRowsRaw.map(getColumnLabel);
const groupbyColumns = groupbyColumnsRaw.map(getColumnLabel);
const groupbyRows = useMemo(
() => groupbyRowsRaw.map(getColumnLabel),
[groupbyRowsRaw],
);
const groupbyColumns = useMemo(
() => groupbyColumnsRaw.map(getColumnLabel),
[groupbyColumnsRaw],
);
let [rows, cols] = transposePivot
? [groupbyColumns, groupbyRows]
: [groupbyRows, groupbyColumns];
const sorters = useMemo(
() => ({
[METRIC_KEY]: sortAs(metricNames),
}),
[metricNames],
);
if (metricsLayout === MetricsLayoutEnum.ROWS) {
rows = combineMetric ? [...rows, METRIC_KEY] : [METRIC_KEY, ...rows];
} else {
cols = combineMetric ? [...cols, METRIC_KEY] : [METRIC_KEY, ...cols];
}
const [rows, cols] = useMemo(() => {
let [rows_, cols_] = transposePivot
? [groupbyColumns, groupbyRows]
: [groupbyRows, groupbyColumns];
if (metricsLayout === MetricsLayoutEnum.ROWS) {
rows_ = combineMetric ? [...rows_, METRIC_KEY] : [METRIC_KEY, ...rows_];
} else {
cols_ = combineMetric ? [...cols_, METRIC_KEY] : [METRIC_KEY, ...cols_];
}
return [rows_, cols_];
}, [
combineMetric,
groupbyColumns,
groupbyRows,
metricsLayout,
transposePivot,
]);
const handleChange = useCallback(
(filters: SelectedFiltersType) => {
@@ -235,7 +263,7 @@ export default function PivotTableChart(props: PivotTableProps) {
},
});
},
[setDataMask],
[groupbyColumnsRaw, groupbyRowsRaw, setDataMask],
);
const toggleFilter = useCallback(
@@ -290,6 +318,39 @@ export default function PivotTableChart(props: PivotTableProps) {
[emitFilter, selectedFilters, handleChange],
);
const tableOptions = useMemo(
() => ({
clickRowHeaderCallback: toggleFilter,
clickColumnHeaderCallback: toggleFilter,
colTotals,
rowTotals,
highlightHeaderCellsOnHover: emitFilter,
highlightedHeaderCells: selectedFilters,
omittedHighlightHeaderGroups: [METRIC_KEY],
cellColorFormatters: { [METRIC_KEY]: metricColorFormatters },
dateFormatters,
}),
[
colTotals,
dateFormatters,
emitFilter,
metricColorFormatters,
rowTotals,
selectedFilters,
toggleFilter,
],
);
const subtotalOptions = useMemo(
() => ({
colSubtotalDisplay: { displayOnTop: colSubtotalPosition },
rowSubtotalDisplay: { displayOnTop: rowSubtotalPosition },
arrowCollapsed: <PlusSquareOutlined style={iconStyle} />,
arrowExpanded: <MinusSquareOutlined style={iconStyle} />,
}),
[colSubtotalPosition, rowSubtotalPosition],
);
return (
<Styles height={height} width={width} margin={theme.gridUnit * 4}>
<PivotTableWrapper>
@@ -299,36 +360,14 @@ export default function PivotTableChart(props: PivotTableProps) {
cols={cols}
aggregatorsFactory={aggregatorsFactory}
defaultFormatter={defaultFormatter}
customFormatters={
hasCustomMetricFormatters
? { [METRIC_KEY]: metricFormatters }
: undefined
}
customFormatters={metricFormatters}
aggregatorName={aggregateFunction}
vals={['value']}
rendererName="Table With Subtotal"
vals={vals}
colOrder={colOrder}
rowOrder={rowOrder}
sorters={{
metric: sortAs(metricNames),
}}
tableOptions={{
clickRowHeaderCallback: toggleFilter,
clickColumnHeaderCallback: toggleFilter,
colTotals,
rowTotals,
highlightHeaderCellsOnHover: emitFilter,
highlightedHeaderCells: selectedFilters,
omittedHighlightHeaderGroups: [METRIC_KEY],
cellColorFormatters: { [METRIC_KEY]: metricColorFormatters },
dateFormatters,
}}
subtotalOptions={{
colSubtotalDisplay: { displayOnTop: colSubtotalPosition },
rowSubtotalDisplay: { displayOnTop: rowSubtotalPosition },
arrowCollapsed: <PlusSquareOutlined style={iconStyle} />,
arrowExpanded: <MinusSquareOutlined style={iconStyle} />,
}}
sorters={sorters}
tableOptions={tableOptions}
subtotalOptions={subtotalOptions}
namesMapping={verboseMap}
/>
</PivotTableWrapper>