mirror of
https://github.com/apache/superset.git
synced 2024-09-06 13:57:40 -04:00
fix(plugin-chart-echarts): support adhoc x-axis (#20055)
* fix(plugin-chart-echarts): support adhoc x-axis * simplify code
This commit is contained in:
parent
4f77824e55
commit
b53daa91ec
@ -31,11 +31,13 @@ export const pivotOperator: PostProcessingFactory<PostProcessingPivot> = (
|
|||||||
) => {
|
) => {
|
||||||
const metricLabels = ensureIsArray(queryObject.metrics).map(getMetricLabel);
|
const metricLabels = ensureIsArray(queryObject.metrics).map(getMetricLabel);
|
||||||
const { x_axis: xAxis } = formData;
|
const { x_axis: xAxis } = formData;
|
||||||
|
|
||||||
if ((xAxis || queryObject.is_timeseries) && metricLabels.length) {
|
if ((xAxis || queryObject.is_timeseries) && metricLabels.length) {
|
||||||
|
const index = [getColumnLabel(xAxis || DTTM_ALIAS)];
|
||||||
return {
|
return {
|
||||||
operation: 'pivot',
|
operation: 'pivot',
|
||||||
options: {
|
options: {
|
||||||
index: [xAxis || DTTM_ALIAS],
|
index,
|
||||||
columns: ensureIsArray(queryObject.columns).map(getColumnLabel),
|
columns: ensureIsArray(queryObject.columns).map(getColumnLabel),
|
||||||
// Create 'dummy' mean aggregates to assign cell values in pivot table
|
// Create 'dummy' mean aggregates to assign cell values in pivot table
|
||||||
// use the 'mean' aggregates to avoid drop NaN. PR: https://github.com/apache-superset/superset-ui/pull/1231
|
// use the 'mean' aggregates to avoid drop NaN. PR: https://github.com/apache-superset/superset-ui/pull/1231
|
||||||
|
@ -16,13 +16,18 @@
|
|||||||
* specific language governing permissions and limitationsxw
|
* specific language governing permissions and limitationsxw
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { DTTM_ALIAS, PostProcessingProphet } from '@superset-ui/core';
|
import {
|
||||||
|
DTTM_ALIAS,
|
||||||
|
getColumnLabel,
|
||||||
|
PostProcessingProphet,
|
||||||
|
} from '@superset-ui/core';
|
||||||
import { PostProcessingFactory } from './types';
|
import { PostProcessingFactory } from './types';
|
||||||
|
|
||||||
export const prophetOperator: PostProcessingFactory<PostProcessingProphet> = (
|
export const prophetOperator: PostProcessingFactory<PostProcessingProphet> = (
|
||||||
formData,
|
formData,
|
||||||
queryObject,
|
queryObject,
|
||||||
) => {
|
) => {
|
||||||
|
const index = getColumnLabel(formData.x_axis || DTTM_ALIAS);
|
||||||
if (formData.forecastEnabled) {
|
if (formData.forecastEnabled) {
|
||||||
return {
|
return {
|
||||||
operation: 'prophet',
|
operation: 'prophet',
|
||||||
@ -33,7 +38,7 @@ export const prophetOperator: PostProcessingFactory<PostProcessingProphet> = (
|
|||||||
yearly_seasonality: formData.forecastSeasonalityYearly,
|
yearly_seasonality: formData.forecastSeasonalityYearly,
|
||||||
weekly_seasonality: formData.forecastSeasonalityWeekly,
|
weekly_seasonality: formData.forecastSeasonalityWeekly,
|
||||||
daily_seasonality: formData.forecastSeasonalityDaily,
|
daily_seasonality: formData.forecastSeasonalityDaily,
|
||||||
index: formData.x_axis || DTTM_ALIAS,
|
index,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,12 @@ export const timeComparePivotOperator: PostProcessingFactory<PostProcessingPivot
|
|||||||
{ operator: 'mean' as NumpyFunction },
|
{ operator: 'mean' as NumpyFunction },
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
const index = [getColumnLabel(formData.x_axis || DTTM_ALIAS)];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
operation: 'pivot',
|
operation: 'pivot',
|
||||||
options: {
|
options: {
|
||||||
index: [formData.x_axis || DTTM_ALIAS],
|
index,
|
||||||
columns: ensureIsArray(queryObject.columns).map(getColumnLabel),
|
columns: ensureIsArray(queryObject.columns).map(getColumnLabel),
|
||||||
drop_missing_columns: false,
|
drop_missing_columns: false,
|
||||||
flatten_columns: false,
|
flatten_columns: false,
|
||||||
|
@ -136,3 +136,35 @@ test('pivot by x_axis with groupby', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('pivot by adhoc x_axis', () => {
|
||||||
|
expect(
|
||||||
|
pivotOperator(
|
||||||
|
{
|
||||||
|
...formData,
|
||||||
|
x_axis: {
|
||||||
|
label: 'my_case_expr',
|
||||||
|
expressionType: 'SQL',
|
||||||
|
expression: 'case when a = 1 then 1 else 0 end',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...queryObject,
|
||||||
|
columns: ['foo', 'bar'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
).toEqual({
|
||||||
|
operation: 'pivot',
|
||||||
|
options: {
|
||||||
|
index: ['my_case_expr'],
|
||||||
|
columns: ['foo', 'bar'],
|
||||||
|
aggregates: {
|
||||||
|
'count(*)': { operator: 'mean' },
|
||||||
|
'sum(val)': { operator: 'mean' },
|
||||||
|
},
|
||||||
|
drop_missing_columns: false,
|
||||||
|
flatten_columns: false,
|
||||||
|
reset_index: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -98,3 +98,36 @@ test('should do prophetOperator over named column', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should do prophetOperator over adhoc column', () => {
|
||||||
|
expect(
|
||||||
|
prophetOperator(
|
||||||
|
{
|
||||||
|
...formData,
|
||||||
|
x_axis: {
|
||||||
|
label: 'my_case_expr',
|
||||||
|
expressionType: 'SQL',
|
||||||
|
expression: 'case when a = 1 then 1 else 0 end',
|
||||||
|
},
|
||||||
|
forecastEnabled: true,
|
||||||
|
forecastPeriods: '3',
|
||||||
|
forecastInterval: '5',
|
||||||
|
forecastSeasonalityYearly: true,
|
||||||
|
forecastSeasonalityWeekly: false,
|
||||||
|
forecastSeasonalityDaily: false,
|
||||||
|
},
|
||||||
|
queryObject,
|
||||||
|
),
|
||||||
|
).toEqual({
|
||||||
|
operation: 'prophet',
|
||||||
|
options: {
|
||||||
|
time_grain: 'P1Y',
|
||||||
|
periods: 3.0,
|
||||||
|
confidence_interval: 5.0,
|
||||||
|
yearly_seasonality: true,
|
||||||
|
weekly_seasonality: false,
|
||||||
|
daily_seasonality: false,
|
||||||
|
index: 'my_case_expr',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -135,3 +135,44 @@ test('should pivot on x-axis', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should pivot on adhoc x-axis', () => {
|
||||||
|
expect(
|
||||||
|
timeComparePivotOperator(
|
||||||
|
{
|
||||||
|
...formData,
|
||||||
|
comparison_type: 'values',
|
||||||
|
time_compare: ['1 year ago', '1 year later'],
|
||||||
|
x_axis: {
|
||||||
|
label: 'my_case_expr',
|
||||||
|
expressionType: 'SQL',
|
||||||
|
expression: 'case when a = 1 then 1 else 0 end',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
queryObject,
|
||||||
|
),
|
||||||
|
).toEqual({
|
||||||
|
operation: 'pivot',
|
||||||
|
options: {
|
||||||
|
aggregates: {
|
||||||
|
'count(*)': { operator: 'mean' },
|
||||||
|
'count(*)__1 year ago': { operator: 'mean' },
|
||||||
|
'count(*)__1 year later': { operator: 'mean' },
|
||||||
|
'sum(val)': {
|
||||||
|
operator: 'mean',
|
||||||
|
},
|
||||||
|
'sum(val)__1 year ago': {
|
||||||
|
operator: 'mean',
|
||||||
|
},
|
||||||
|
'sum(val)__1 year later': {
|
||||||
|
operator: 'mean',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
drop_missing_columns: false,
|
||||||
|
columns: ['foo', 'bar'],
|
||||||
|
index: ['my_case_expr'],
|
||||||
|
flatten_columns: false,
|
||||||
|
reset_index: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -23,6 +23,7 @@ import {
|
|||||||
DataRecordValue,
|
DataRecordValue,
|
||||||
DTTM_ALIAS,
|
DTTM_ALIAS,
|
||||||
GenericDataType,
|
GenericDataType,
|
||||||
|
getColumnLabel,
|
||||||
getNumberFormatter,
|
getNumberFormatter,
|
||||||
isEventAnnotationLayer,
|
isEventAnnotationLayer,
|
||||||
isFormulaAnnotationLayer,
|
isFormulaAnnotationLayer,
|
||||||
@ -141,7 +142,8 @@ export default function transformProps(
|
|||||||
|
|
||||||
const colorScale = CategoricalColorNamespace.getScale(colorScheme as string);
|
const colorScale = CategoricalColorNamespace.getScale(colorScheme as string);
|
||||||
const rebasedData = rebaseForecastDatum(data, verboseMap);
|
const rebasedData = rebaseForecastDatum(data, verboseMap);
|
||||||
const xAxisCol = verboseMap[xAxisOrig] || xAxisOrig || DTTM_ALIAS;
|
const xAxisCol =
|
||||||
|
verboseMap[xAxisOrig] || getColumnLabel(xAxisOrig || DTTM_ALIAS);
|
||||||
const rawSeries = extractSeries(rebasedData, {
|
const rawSeries = extractSeries(rebasedData, {
|
||||||
fillNeighborValue: stack && !forecastEnabled ? 0 : undefined,
|
fillNeighborValue: stack && !forecastEnabled ? 0 : undefined,
|
||||||
xAxis: xAxisCol,
|
xAxis: xAxisCol,
|
||||||
|
Loading…
Reference in New Issue
Block a user