Skip to content

Commit

Permalink
chore(plugin-chart-pivot-table): migrate react-pivottable into supers…
Browse files Browse the repository at this point in the history
…et codebase (#17769)

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

* Fix lint errors

* Use named export

* Clean up the code
  • Loading branch information
kgabryje authored Dec 17, 2021
1 parent c5af7a4 commit 9c9edbe
Show file tree
Hide file tree
Showing 8 changed files with 2,033 additions and 133 deletions.
76 changes: 1 addition & 75 deletions superset-frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
},
"dependencies": {
"@superset-ui/chart-controls": "0.18.25",
"@superset-ui/core": "0.18.25",
"@superset-ui/react-pivottable": "^0.12.12"
"@superset-ui/core": "0.18.25"
},
"peerDependencies": {
"@ant-design/icons": "^4.2.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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),
Expand Down Expand Up @@ -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(
() =>
Expand All @@ -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],
);

const sorters = useMemo(
() => ({
[METRIC_KEY]: sortAs(metricNames),
}),
[metricNames],
);

let [rows, cols] = transposePivot
? [groupbyColumns, groupbyRows]
: [groupbyRows, groupbyColumns];
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];
}
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) => {
Expand Down Expand Up @@ -235,7 +263,7 @@ export default function PivotTableChart(props: PivotTableProps) {
},
});
},
[setDataMask],
[groupbyColumnsRaw, groupbyRowsRaw, setDataMask],
);

const toggleFilter = useCallback(
Expand Down Expand Up @@ -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>
Expand All @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React from 'react';
import { PivotData } from './utilities';
import { TableRenderer } from './TableRenderers';

class PivotTable extends React.PureComponent {
render() {
return <TableRenderer {...this.props} />;
}
}

PivotTable.propTypes = PivotData.propTypes;
PivotTable.defaultProps = PivotData.defaultProps;

export default PivotTable;
Loading

0 comments on commit 9c9edbe

Please sign in to comment.