feat: simply the data processing logic

This commit is contained in:
Conglei Shi 2019-05-21 11:11:43 -07:00 committed by Yongjie Zhao
parent 7522f28ece
commit aa7ef1ad90
6 changed files with 130 additions and 117 deletions

View File

@ -33,7 +33,6 @@
"@superset-ui/chart": "^0.10.0",
"@superset-ui/number-format": "^0.10.0",
"@superset-ui/time-format": "^0.10.0",
"@superset-ui/translation": "^0.10.0",
"core-js": "^3.0.1"
"@superset-ui/translation": "^0.10.0"
}
}

View File

@ -3,13 +3,14 @@ import DataTable from '@airbnb/lunar/lib/components/DataTable';
import { Renderers, RendererProps } from '@airbnb/lunar/lib/components/DataTable/types';
import { HEIGHT_TO_PX } from '@airbnb/lunar/lib/components/DataTable/constants';
import { FormDataMetric, Metric } from '@superset-ui/chart';
import { getNumberFormatter, NumberFormats } from '@superset-ui/number-format';
import { getTimeFormatter } from '@superset-ui/time-format';
type ColumnType = {
key: string;
label: string;
format: string;
format?: (value: any) => string;
type: 'metric' | 'string';
maxValue?: number;
minValue?: number;
};
type Props = {
@ -58,8 +59,6 @@ type TableState = {
const NEGATIVE_COLOR = '#ff8787';
const POSITIVE_COLOR = '#ced4da';
const formatPercent = getNumberFormatter(NumberFormats.PERCENT_3_POINT);
class TableVis extends React.Component<TableProps, TableState> {
static defaultProps = defaultProps;
@ -91,7 +90,10 @@ class TableVis extends React.Component<TableProps, TableState> {
});
};
static getDerivedStateFromProps(props: TableProps, state: TableState) {
static getDerivedStateFromProps: React.GetDerivedStateFromProps<TableProps, TableState> = (
props: TableProps,
state: TableState,
) => {
const { filters } = props;
const { selectedCells } = state;
const newSelectedCells = new Set(Array.from(selectedCells));
@ -104,62 +106,25 @@ class TableVis extends React.Component<TableProps, TableState> {
...state,
selectedCells: newSelectedCells,
};
}
};
render() {
const {
metrics: rawMetrics,
metrics,
timeseriesLimitMetric,
orderDesc,
percentMetrics,
data,
alignPositiveNegative,
colorPositiveNegative,
columns,
tableTimestampFormat,
tableFilter,
} = this.props;
const { selectedCells } = this.state;
const metrics = (rawMetrics || [])
.map(m => (m as Metric).label || (m as string))
// Add percent metrics
.concat((percentMetrics || []).map(m => `%${m}`))
// Removing metrics (aggregates) that are strings
.filter(m => typeof data[0][m as string] === 'number');
const dataArray: {
[key: string]: any;
} = {};
const sortByKey =
timeseriesLimitMetric &&
((timeseriesLimitMetric as Metric).label || (timeseriesLimitMetric as string));
metrics.forEach(metric => {
const arr = [];
for (let i = 0; i < data.length; i += 1) {
arr.push(data[i][metric]);
}
dataArray[metric] = arr;
});
const maxes: {
[key: string]: number;
} = {};
const mins: {
[key: string]: number;
} = {};
for (let i = 0; i < metrics.length; i += 1) {
if (alignPositiveNegative) {
maxes[metrics[i]] = Math.max(...dataArray[metrics[i]].map(Math.abs));
} else {
maxes[metrics[i]] = Math.max(...dataArray[metrics[i]]);
mins[metrics[i]] = Math.min(...dataArray[metrics[i]]);
}
}
// const tsFormatter = getTimeFormatter(tableTimestampFormat);
let formattedData = data.map(row => ({
data: row,
}));
@ -183,8 +148,6 @@ class TableVis extends React.Component<TableProps, TableState> {
}
}
const tsFormatter = getTimeFormatter(tableTimestampFormat);
const heightType = 'small';
const getRenderer = (column: ColumnType) => (props: RendererProps) => {
const { key } = props;
@ -197,10 +160,12 @@ class TableVis extends React.Component<TableProps, TableState> {
let left = 0;
let width = 0;
if (alignPositiveNegative) {
width = Math.abs(Math.round((value / maxes[key]) * 100));
width = Math.abs(
Math.round((value / Math.max(column.maxValue!, Math.abs(column.minValue!))) * 100),
);
} else {
const posExtent = Math.abs(Math.max(maxes[key], 0));
const negExtent = Math.abs(Math.min(mins[key], 0));
const posExtent = Math.abs(Math.max(column.maxValue!, 0));
const negExtent = Math.abs(Math.min(column.minValue!, 0));
const tot = posExtent + negExtent;
left = Math.round((Math.min(negExtent + value, negExtent) / tot) * 100);
width = Math.round((Math.abs(value) / tot) * 100);
@ -236,16 +201,7 @@ class TableVis extends React.Component<TableProps, TableState> {
</div>
);
};
if (key[0] === '%') {
value = formatPercent(value);
} else {
value = getNumberFormatter(column.format)(value);
}
} else {
if (key === '__timestamp') {
value = tsFormatter(value);
}
Parent = ({ children }: { children: React.ReactNode }) => (
<React.Fragment>{children}</React.Fragment>
);
@ -255,10 +211,10 @@ class TableVis extends React.Component<TableProps, TableState> {
<div
onClick={this.handleCellSelected({
key,
value: props.row.rowData.data[key],
value,
})}
>
<Parent>{value}</Parent>
<Parent>{column.format ? column.format(value) : value}</Parent>
</div>
);
};

View File

@ -17,14 +17,15 @@
* under the License.
*/
import { ChartPlugin } from '@superset-ui/chart';
import Core from '@airbnb/lunar/lib';
import transformProps from './transformProps';
import createMetadata from './createMetadata';
import buildQuery from './buildQuery';
import Core from '@airbnb/lunar/lib';
import TableFormData from './TableFormData';
Core.initialize({ name: 'superset-datatable' });
export default class TableChartPlugin extends ChartPlugin {
export default class TableChartPlugin extends ChartPlugin<TableFormData> {
constructor() {
super({
buildQuery,

View File

@ -18,7 +18,9 @@
*/
/* eslint-disable sort-keys */
import { ChartProps } from '@superset-ui/chart';
import { ChartProps, FormDataMetric, Metric } from '@superset-ui/chart';
import { getNumberFormatter, NumberFormats, NumberFormatter } from '@superset-ui/number-format';
import { getTimeFormatter, TimeFormatter } from '@superset-ui/time-format';
export default function transformProps(chartProps: ChartProps) {
const { height, datasource, filters, formData, onAddFilter, payload } = chartProps;
@ -26,7 +28,7 @@ export default function transformProps(chartProps: ChartProps) {
alignPn,
colorPn,
includeSearch,
metrics,
metrics: rawMetrics,
orderDesc,
pageLength,
percentMetrics,
@ -37,22 +39,78 @@ export default function transformProps(chartProps: ChartProps) {
const { columnFormats, verboseMap } = datasource;
const { records, columns } = payload.data;
const metrics = ((rawMetrics as FormDataMetric[]) || [])
.map(m => (m as Metric).label || (m as string))
// Add percent metrics
.concat(((percentMetrics as string[]) || []).map(m => `%${m}`))
// Removing metrics (aggregates) that are strings
.filter(m => typeof records[0][m as string] === 'number');
const dataArray: {
[key: string]: any;
} = {};
metrics.forEach(metric => {
const arr = [];
for (let i = 0; i < records.length; i += 1) {
arr.push(records[i][metric]);
}
dataArray[metric] = arr;
});
const maxes: {
[key: string]: number;
} = {};
const mins: {
[key: string]: number;
} = {};
for (let i = 0; i < metrics.length; i += 1) {
maxes[metrics[i]] = Math.max(...dataArray[metrics[i]]);
mins[metrics[i]] = Math.min(...dataArray[metrics[i]]);
}
const formatPercent = getNumberFormatter(NumberFormats.PERCENT_3_POINT);
const tsFormatter = getTimeFormatter(tableTimestampFormat);
const processedColumns = columns.map((key: string) => {
let label = verboseMap[key];
let formatString = columnFormats && columnFormats[key];
let formatFunction: NumberFormatter | TimeFormatter | undefined;
let type = 'string';
// Handle verbose names for percents
if (!label) {
if (key[0] === '%') {
const cleanedKey = key.substring(1);
label = `% ${verboseMap[cleanedKey] || cleanedKey}`;
formatFunction = formatPercent;
} else {
label = key;
}
}
if (key === '__timestamp') {
formatFunction = tsFormatter;
}
const extraField: {
[key: string]: any;
} = {};
if (metrics.indexOf(key) >= 0) {
formatFunction = getNumberFormatter(formatString);
type = 'metric';
extraField['maxValue'] = maxes[key];
extraField['minValue'] = mins[key];
}
return {
key,
label,
format: columnFormats && columnFormats[key],
format: formatFunction,
type,
...extraField,
};
});

View File

@ -16,13 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
/* eslint-disable sort-keys */
import { ChartProps, Metric, FormDataMetric } from '@superset-ui/chart';
const DTTM_ALIAS = '__timestamp';
function transformData(data: ChartProps['payload'][], formData: ChartProps['formData']) {
type PlainObject = {
[key: string]: any;
};
function transformData(data: PlainObject[], formData: PlainObject) {
const columns = new Set(
[...formData.groupby, ...formData.metrics, ...formData.allColumns].map(
column => column.label || column,
@ -88,8 +91,7 @@ export default function transformProps(chartProps: ChartProps) {
timeseriesLimitMetric,
} = formData;
const { columnFormats, verboseMap } = datasource;
const data = payload.data || payload[0].data;
const { records, columns } = transformData(data, formData);
const { records, columns } = transformData(payload.data, formData);
const processedColumns = columns.map((key: string) => {
let label = verboseMap[key];

View File

@ -1,46 +1,43 @@
/* eslint-disable sort-keys */
export default {
columns: ['name', 'sum__num'],
records: [
{
name: 'Michael',
sum__num: 2467063,
},
{
name: 'Christopher',
sum__num: 1725265,
},
{
name: 'David',
sum__num: 1570516,
},
{
name: 'James',
sum__num: 1506025,
},
{
name: 'John',
sum__num: 1426074,
},
{
name: 'Matthew',
sum__num: 1355803,
},
{
name: 'Robert',
sum__num: 1314800,
},
{
name: 'Daniel',
sum__num: 1159354,
},
{
name: 'Joseph',
sum__num: 1114098,
},
{
name: 'William',
sum__num: 1113701,
},
],
};
export default [
{
name: 'Michael',
sum__num: 2467063,
},
{
name: 'Christopher',
sum__num: 1725265,
},
{
name: 'David',
sum__num: 1570516,
},
{
name: 'James',
sum__num: 1506025,
},
{
name: 'John',
sum__num: 1426074,
},
{
name: 'Matthew',
sum__num: 1355803,
},
{
name: 'Robert',
sum__num: 1314800,
},
{
name: 'Daniel',
sum__num: 1159354,
},
{
name: 'Joseph',
sum__num: 1114098,
},
{
name: 'William',
sum__num: 1113701,
},
];