mirror of
https://github.com/apache/superset.git
synced 2026-05-06 16:34:32 +00:00
feat: add Advanced Analytics into mixed time series chart (#19851)
This commit is contained in:
@@ -21,83 +21,65 @@ import {
|
||||
QueryFormData,
|
||||
QueryObject,
|
||||
normalizeOrderBy,
|
||||
PostProcessingPivot,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
pivotOperator,
|
||||
renameOperator,
|
||||
flattenOperator,
|
||||
isTimeComparison,
|
||||
timeComparePivotOperator,
|
||||
rollingWindowOperator,
|
||||
timeCompareOperator,
|
||||
resampleOperator,
|
||||
} from '@superset-ui/chart-controls';
|
||||
import {
|
||||
retainFormDataSuffix,
|
||||
removeFormDataSuffix,
|
||||
} from '../utils/formDataSuffix';
|
||||
|
||||
export default function buildQuery(formData: QueryFormData) {
|
||||
const {
|
||||
adhoc_filters,
|
||||
adhoc_filters_b,
|
||||
groupby,
|
||||
groupby_b,
|
||||
limit,
|
||||
limit_b,
|
||||
timeseries_limit_metric,
|
||||
timeseries_limit_metric_b,
|
||||
metrics,
|
||||
metrics_b,
|
||||
order_desc,
|
||||
order_desc_b,
|
||||
...baseFormData
|
||||
} = formData;
|
||||
baseFormData.is_timeseries = true;
|
||||
const formData1 = {
|
||||
...baseFormData,
|
||||
adhoc_filters,
|
||||
columns: groupby,
|
||||
limit,
|
||||
timeseries_limit_metric,
|
||||
metrics,
|
||||
order_desc,
|
||||
};
|
||||
const formData2 = {
|
||||
...baseFormData,
|
||||
adhoc_filters: adhoc_filters_b,
|
||||
columns: groupby_b,
|
||||
limit: limit_b,
|
||||
timeseries_limit_metric: timeseries_limit_metric_b,
|
||||
metrics: metrics_b,
|
||||
order_desc: order_desc_b,
|
||||
const baseFormData = {
|
||||
...formData,
|
||||
is_timeseries: true,
|
||||
columns: formData.groupby,
|
||||
columns_b: formData.groupby_b,
|
||||
};
|
||||
const formData1 = removeFormDataSuffix(baseFormData, '_b');
|
||||
const formData2 = retainFormDataSuffix(baseFormData, '_b');
|
||||
|
||||
const queryContextA = buildQueryContext(formData1, baseQueryObject => {
|
||||
const queryObjectA = {
|
||||
...baseQueryObject,
|
||||
is_timeseries: true,
|
||||
post_processing: [
|
||||
pivotOperator(formData1, { ...baseQueryObject, is_timeseries: true }),
|
||||
renameOperator(formData1, {
|
||||
...baseQueryObject,
|
||||
...{ is_timeseries: true },
|
||||
}),
|
||||
flattenOperator(formData1, baseQueryObject),
|
||||
],
|
||||
} as QueryObject;
|
||||
return [normalizeOrderBy(queryObjectA)];
|
||||
});
|
||||
const queryContexts = [formData1, formData2].map(fd =>
|
||||
buildQueryContext(fd, baseQueryObject => {
|
||||
const queryObject = {
|
||||
...baseQueryObject,
|
||||
is_timeseries: true,
|
||||
};
|
||||
|
||||
const queryContextB = buildQueryContext(formData2, baseQueryObject => {
|
||||
const queryObjectB = {
|
||||
...baseQueryObject,
|
||||
is_timeseries: true,
|
||||
post_processing: [
|
||||
pivotOperator(formData2, { ...baseQueryObject, is_timeseries: true }),
|
||||
renameOperator(formData2, {
|
||||
...baseQueryObject,
|
||||
...{ is_timeseries: true },
|
||||
}),
|
||||
flattenOperator(formData2, baseQueryObject),
|
||||
],
|
||||
} as QueryObject;
|
||||
return [normalizeOrderBy(queryObjectB)];
|
||||
});
|
||||
const pivotOperatorInRuntime: PostProcessingPivot = isTimeComparison(
|
||||
fd,
|
||||
queryObject,
|
||||
)
|
||||
? timeComparePivotOperator(fd, queryObject)
|
||||
: pivotOperator(fd, queryObject);
|
||||
|
||||
const tmpQueryObject = {
|
||||
...queryObject,
|
||||
time_offsets: isTimeComparison(fd, queryObject) ? fd.time_compare : [],
|
||||
post_processing: [
|
||||
pivotOperatorInRuntime,
|
||||
rollingWindowOperator(fd, queryObject),
|
||||
timeCompareOperator(fd, queryObject),
|
||||
resampleOperator(fd, queryObject),
|
||||
renameOperator(fd, queryObject),
|
||||
flattenOperator(fd, queryObject),
|
||||
],
|
||||
} as QueryObject;
|
||||
return [normalizeOrderBy(tmpQueryObject)];
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
...queryContextA,
|
||||
queries: [...queryContextA.queries, ...queryContextB.queries],
|
||||
...queryContexts[0],
|
||||
queries: [...queryContexts[0].queries, ...queryContexts[1].queries],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import { t } from '@superset-ui/core';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import {
|
||||
ControlPanelConfig,
|
||||
ControlPanelSectionConfig,
|
||||
ControlSetRow,
|
||||
CustomControlItem,
|
||||
emitFilterControl,
|
||||
sections,
|
||||
sharedControls,
|
||||
@@ -253,11 +255,33 @@ function createCustomizeSection(
|
||||
];
|
||||
}
|
||||
|
||||
function createAdvancedAnalyticsSection(
|
||||
label: string,
|
||||
controlSuffix: string,
|
||||
): ControlPanelSectionConfig {
|
||||
const aaWithSuffix = cloneDeep(sections.advancedAnalyticsControls);
|
||||
aaWithSuffix.label = label;
|
||||
if (!controlSuffix) {
|
||||
return aaWithSuffix;
|
||||
}
|
||||
aaWithSuffix.controlSetRows.forEach(row =>
|
||||
row.forEach((control: CustomControlItem) => {
|
||||
if (control?.name) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
control.name = `${control.name}${controlSuffix}`;
|
||||
}
|
||||
}),
|
||||
);
|
||||
return aaWithSuffix;
|
||||
}
|
||||
|
||||
const config: ControlPanelConfig = {
|
||||
controlPanelSections: [
|
||||
sections.legacyTimeseriesTime,
|
||||
createQuerySection(t('Query A'), ''),
|
||||
createAdvancedAnalyticsSection(t('Advanced analytics Query A'), ''),
|
||||
createQuerySection(t('Query B'), '_b'),
|
||||
createAdvancedAnalyticsSection(t('Advanced analytics Query B'), '_b'),
|
||||
{
|
||||
label: t('Annotations and Layers'),
|
||||
expanded: false,
|
||||
|
||||
Reference in New Issue
Block a user