mirror of
https://github.com/apache/superset.git
synced 2024-09-19 20:19:37 -04:00
feat: simply the data processing logic
This commit is contained in:
parent
7522f28ece
commit
aa7ef1ad90
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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,
|
||||
},
|
||||
];
|
||||
|
Loading…
Reference in New Issue
Block a user