From e8f4be2893c603fd034238ad4704f74eb1eaae29 Mon Sep 17 00:00:00 2001 From: Ville Brofeldt <33317356+villebro@users.noreply.github.com> Date: Wed, 10 Nov 2021 14:56:44 +0200 Subject: [PATCH] feat(core): add support for adhoc columns (#1342) * feat(core): add support for adhoc columns * simplify import * revert simplification due to codecov * fix filter column type * fix pivot v2 groupbys * remove redundant import * Add new type guards * move ColumnMeta type guards to chart-controls * add type guard tests * Fix typing and import errors * Fix saved expression type guard * Fix typing * Remove redundant import * Make Echarts and PivotTable handle AdhocColumns properly * Fix lint Co-authored-by: Kamil Gabryjelski --- .../src/operators/boxplotOperator.ts | 7 +- .../src/operators/pivotOperator.ts | 3 +- .../src/operators/timeComparePivotOperator.ts | 4 +- .../superset-ui-chart-controls/src/types.ts | 27 +++++++- .../test/types.test.ts | 68 +++++++++++++++++++ .../src/query/buildQueryObject.ts | 10 ++- .../src/query/extractQueryFields.ts | 6 +- .../src/query/getColumnLabel.ts | 11 +++ .../src/query/getMetricLabel.ts | 8 +-- .../superset-ui-core/src/query/index.ts | 1 + .../src/query/types/Column.ts | 19 ++++++ .../src/query/types/Metric.ts | 7 ++ .../superset-ui-core/src/query/types/Query.ts | 2 +- .../src/query/types/QueryFormData.ts | 11 ++- .../test/query/getColumnLabel.test.ts | 42 ++++++++++++ .../test/query/getMetricLabel.test.ts | 1 - .../src/BoxPlot/transformProps.ts | 17 +++-- .../plugin-chart-echarts/src/BoxPlot/types.ts | 3 +- .../src/Funnel/transformProps.ts | 14 ++-- .../plugin-chart-echarts/src/Funnel/types.ts | 5 +- .../src/Gauge/transformProps.ts | 6 +- .../plugin-chart-echarts/src/Gauge/types.ts | 3 +- .../src/MixedTimeseries/types.ts | 9 +-- .../src/Pie/transformProps.ts | 10 +-- .../plugin-chart-echarts/src/Pie/types.ts | 5 +- .../src/Radar/transformProps.ts | 12 ++-- .../plugin-chart-echarts/src/Radar/types.ts | 5 +- .../Timeseries/Regular/Bar/controlPanel.tsx | 27 ++++++-- .../src/Timeseries/types.ts | 3 +- .../src/Treemap/transformProps.ts | 8 ++- .../plugin-chart-echarts/src/Treemap/types.ts | 5 +- .../plugins/plugin-chart-echarts/src/types.ts | 8 ++- .../plugin-chart-echarts/src/utils/series.ts | 3 +- .../src/PivotTableChart.tsx | 11 +-- .../src/plugin/buildQuery.ts | 6 +- .../plugin-chart-pivot-table/src/types.ts | 8 +-- 36 files changed, 315 insertions(+), 80 deletions(-) create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/test/types.test.ts create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/getColumnLabel.ts create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/query/getColumnLabel.test.ts diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/boxplotOperator.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/boxplotOperator.ts index 300bdcbc40be2..9b90c12862cd8 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/boxplotOperator.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/boxplotOperator.ts @@ -17,9 +17,10 @@ * under the License. */ import { - PostProcessingBoxplot, - getMetricLabel, ensureIsArray, + getColumnLabel, + getMetricLabel, + PostProcessingBoxplot, } from '@superset-ui/core'; import { PostProcessingFactory } from './types'; @@ -56,7 +57,7 @@ export const boxplotOperator: PostProcessingFactory< options: { whisker_type: whiskerType, percentiles, - groupby: ensureIsArray(groupby), + groupby: ensureIsArray(groupby).map(getColumnLabel), metrics: ensureIsArray(queryObject.metrics).map(getMetricLabel), }, }; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts index e29e33bd0e303..8789efb44e9ca 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/pivotOperator.ts @@ -18,6 +18,7 @@ */ import { ensureIsArray, + getColumnLabel, getMetricLabel, PostProcessingPivot, } from '@superset-ui/core'; @@ -38,7 +39,7 @@ export const pivotOperator: PostProcessingFactory< operation: 'pivot', options: { index: [TIME_COLUMN], - columns: queryObject.columns || [], + columns: ensureIsArray(queryObject.columns).map(getColumnLabel), // 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 aggregates: Object.fromEntries( diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts index 51ae7a061c33e..4b5458e67d841 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/operators/timeComparePivotOperator.ts @@ -21,6 +21,8 @@ import { ComparisionType, PostProcessingPivot, NumpyFunction, + ensureIsArray, + getColumnLabel, } from '@superset-ui/core'; import { getMetricOffsetsMap, @@ -56,7 +58,7 @@ export const timeComparePivotOperator: PostProcessingFactory< operation: 'pivot', options: { index: ['__timestamp'], - columns: queryObject.columns || [], + columns: ensureIsArray(queryObject.columns).map(getColumnLabel), aggregates: comparisonType === ComparisionType.Values ? valuesAgg : changeAgg, drop_missing_columns: false, diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/types.ts index 19cbbee48c89e..fa90d4d3ee2d0 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/src/types.ts @@ -19,11 +19,12 @@ */ import React, { ReactNode, ReactText, ReactElement } from 'react'; import { - QueryFormData, + AdhocColumn, + Column, DatasourceType, - Metric, JsonValue, - Column, + Metric, + QueryFormData, } from '@superset-ui/core'; import { sharedControls } from './shared-controls'; import sharedControlComponents from './shared-controls/components'; @@ -380,3 +381,23 @@ export type ColorFormatters = { }[]; export default {}; + +export function isColumnMeta( + column: AdhocColumn | ColumnMeta, +): column is ColumnMeta { + return 'column_name' in column; +} + +export function isSavedExpression( + column: AdhocColumn | ColumnMeta, +): column is ColumnMeta { + return ( + 'column_name' in column && 'expression' in column && !!column.expression + ); +} + +export function isAdhocColumn( + column: AdhocColumn | ColumnMeta, +): column is AdhocColumn { + return 'label' in column && 'sqlExpression' in column; +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/test/types.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/test/types.test.ts new file mode 100644 index 0000000000000..04b84602b8404 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart-controls/test/types.test.ts @@ -0,0 +1,68 @@ +/** + * 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 { AdhocColumn } from '@superset-ui/core'; +import { isAdhocColumn, isColumnMeta, isSavedExpression } from '../src'; +import { ColumnMeta } from '../lib'; + +const ADHOC_COLUMN: AdhocColumn = { + hasCustomLabel: true, + label: 'Adhoc column', + sqlExpression: 'case when 1 = 1 then 1 else 2 end', +}; +const COLUMN_META: ColumnMeta = { + column_name: 'my_col', +}; +const SAVED_EXPRESSION: ColumnMeta = { + column_name: 'Saved expression', + expression: 'case when 1 = 1 then 1 else 2 end', +}; + +describe('isColumnMeta', () => { + it('returns false for AdhocColumn', () => { + expect(isColumnMeta(ADHOC_COLUMN)).toEqual(false); + }); + + it('returns true for ColumnMeta', () => { + expect(isColumnMeta(COLUMN_META)).toEqual(true); + }); +}); + +describe('isAdhocColumn', () => { + it('returns true for AdhocColumn', () => { + expect(isAdhocColumn(ADHOC_COLUMN)).toEqual(true); + }); + + it('returns false for ColumnMeta', () => { + expect(isAdhocColumn(COLUMN_META)).toEqual(false); + }); +}); + +describe('isSavedExpression', () => { + it('returns false for AdhocColumn', () => { + expect(isSavedExpression(ADHOC_COLUMN)).toEqual(false); + }); + + it('returns false for ColumnMeta without expression', () => { + expect(isSavedExpression(COLUMN_META)).toEqual(false); + }); + + it('returns true for ColumnMeta with expression', () => { + expect(isSavedExpression(SAVED_EXPRESSION)).toEqual(true); + }); +}); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/buildQueryObject.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/buildQueryObject.ts index 5aab17bacb274..c49bc5ce6aa50 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/buildQueryObject.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/buildQueryObject.ts @@ -18,13 +18,17 @@ */ /* eslint-disable camelcase */ -import { QueryObject, QueryObjectFilterClause } from './types/Query'; -import { QueryFieldAliases, QueryFormData } from './types/QueryFormData'; +import { + AdhocFilter, + QueryFieldAliases, + QueryFormData, + QueryObject, + QueryObjectFilterClause, +} from './types'; import processFilters from './processFilters'; import extractExtras from './extractExtras'; import extractQueryFields from './extractQueryFields'; import { overrideExtraFormData } from './processExtraFormData'; -import { AdhocFilter } from './types'; /** * Build the common segments of all query objects (e.g. the granularity field derived from diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/extractQueryFields.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/extractQueryFields.ts index 162e4723547b7..860753405e7ba 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/extractQueryFields.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/extractQueryFields.ts @@ -19,6 +19,7 @@ import { t } from '../translation'; import { removeDuplicates } from '../utils'; import { DTTM_ALIAS } from './constants'; +import getColumnLabel from './getColumnLabel'; import getMetricLabel from './getMetricLabel'; import { QueryFields, @@ -109,7 +110,10 @@ export default function extractQueryFields( } return { - columns: removeDuplicates(columns.filter(x => typeof x === 'string' && x)), + columns: removeDuplicates( + columns.filter(col => col !== ''), + getColumnLabel, + ), metrics: queryMode === QueryMode.raw ? undefined diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/getColumnLabel.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/getColumnLabel.ts new file mode 100644 index 0000000000000..3364251a11329 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/getColumnLabel.ts @@ -0,0 +1,11 @@ +import { isPhysicalColumn, QueryFormColumn } from './types'; + +export default function getColumnLabel(column: QueryFormColumn): string { + if (isPhysicalColumn(column)) { + return column; + } + if (column.label) { + return column.label; + } + return column.sqlExpression; +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/getMetricLabel.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/getMetricLabel.ts index e4bd2d7cd9219..3f6f31af7b9f9 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/getMetricLabel.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/getMetricLabel.ts @@ -17,16 +17,16 @@ * under the License. */ -import { QueryFormMetric } from './types/QueryFormData'; +import { isAdhocMetricSimple, isSavedMetric, QueryFormMetric } from './types'; -export default function getMetricLabel(metric: QueryFormMetric) { - if (typeof metric === 'string') { +export default function getMetricLabel(metric: QueryFormMetric): string { + if (isSavedMetric(metric)) { return metric; } if (metric.label) { return metric.label; } - if (metric.expressionType === 'SIMPLE') { + if (isAdhocMetricSimple(metric)) { return `${metric.aggregate}(${ metric.column.columnName || metric.column.column_name })`; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/index.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/index.ts index 2e476b26208e3..9bbfbc59fba86 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/index.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/index.ts @@ -24,6 +24,7 @@ export { default as buildQueryContext } from './buildQueryContext'; export { default as buildQueryObject } from './buildQueryObject'; export { default as convertFilter } from './convertFilter'; export { default as extractTimegrain } from './extractTimegrain'; +export { default as getColumnLabel } from './getColumnLabel'; export { default as getMetricLabel } from './getMetricLabel'; export { default as DatasourceKey } from './DatasourceKey'; export { default as normalizeOrderBy } from './normalizeOrderBy'; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Column.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Column.ts index 039a33f4f13ba..8fcf871647e3c 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Column.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Column.ts @@ -20,6 +20,19 @@ import { GenericDataType } from './QueryResponse'; +export interface AdhocColumn { + hasCustomLabel?: boolean; + label?: string; + optionName?: string; + sqlExpression: string; + expressionType: 'SQL'; +} + +/** + * A column that is physically defined in datasource. + */ +export type PhysicalColumn = string; + /** * Column information defined in datasource. */ @@ -39,3 +52,9 @@ export interface Column { } export default {}; + +export function isPhysicalColumn( + column: AdhocColumn | PhysicalColumn, +): column is PhysicalColumn { + return typeof column === 'string'; +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Metric.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Metric.ts index 947380edc5dba..396ccd4c5b5a1 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Metric.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Metric.ts @@ -29,6 +29,7 @@ export type Aggregate = | 'SUM'; export interface AdhocMetricBase { + hasCustomLabel?: boolean; label?: string; optionName?: string; } @@ -72,3 +73,9 @@ export interface Metric { } export default {}; + +export function isAdhocMetricSimple( + metric: AdhocMetric, +): metric is AdhocMetricSimple { + return metric.expressionType === 'SIMPLE'; +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Query.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Query.ts index cdf465fecaa9d..e51b568e03ae1 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Query.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/Query.ts @@ -28,7 +28,7 @@ import { JsonObject } from '../../connection'; import { TimeGranularity } from '../../time-format'; export type QueryObjectFilterClause = { - col: string; + col: QueryFormColumn; grain?: TimeGranularity; isExtra?: boolean; } & ( diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/QueryFormData.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/QueryFormData.ts index 12f569f6a6a4b..e799f7cccd28a 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/QueryFormData.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/query/types/QueryFormData.ts @@ -33,6 +33,7 @@ import { import { TimeRange, TimeRangeEndpoints } from './Time'; import { TimeGranularity } from '../../time-format'; import { JsonObject } from '../../connection'; +import { AdhocColumn, PhysicalColumn } from './Column'; /** * Metric definition/reference in query object. @@ -41,9 +42,9 @@ export type QueryFormMetric = SavedMetric | AdhocMetric; /** * Column selects in query object (used as dimensions in both groupby or raw - * query mode). Only support referring existing columns. + * query mode). Can be either reference to physical column or expression. */ -export type QueryFormColumn = string; +export type QueryFormColumn = PhysicalColumn | AdhocColumn; /** * Order query results by columns. @@ -174,7 +175,7 @@ export interface BaseFormData extends TimeRange, FormDataResidual { /** row offset for server side pagination */ row_offset?: string | number | null; /** The metric used to order timeseries for limiting */ - timeseries_limit_metric?: QueryFormColumn; + timeseries_limit_metric?: QueryFormMetric; /** Force refresh */ force?: boolean; result_format?: string; @@ -222,4 +223,8 @@ export function isDruidFormData( return 'granularity' in formData; } +export function isSavedMetric(metric: QueryFormMetric): metric is SavedMetric { + return typeof metric === 'string'; +} + export default {}; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/query/getColumnLabel.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/query/getColumnLabel.test.ts new file mode 100644 index 0000000000000..865463481cdc4 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/query/getColumnLabel.test.ts @@ -0,0 +1,42 @@ +/** + * 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 { getColumnLabel } from '@superset-ui/core/src/query'; + +describe('getColumnLabel', () => { + it('should handle physical column', () => { + expect(getColumnLabel('gender')).toEqual('gender'); + }); + + it('should handle adhoc columns with label', () => { + expect( + getColumnLabel({ + sqlExpression: "case when 1 then 'a' else 'b' end", + label: 'my col', + }), + ).toEqual('my col'); + }); + + it('should handle adhoc columns without label', () => { + expect( + getColumnLabel({ + sqlExpression: "case when 1 then 'a' else 'b' end", + }), + ).toEqual("case when 1 then 'a' else 'b' end"); + }); +}); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/query/getMetricLabel.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/query/getMetricLabel.test.ts index bfd404df10ba5..434eb7215564d 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/query/getMetricLabel.test.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/query/getMetricLabel.test.ts @@ -17,7 +17,6 @@ * under the License. */ import { getMetricLabel } from '@superset-ui/core/src/query'; -import { GenericDataType } from '../../src'; describe('getMetricLabel', () => { it('should handle predefined metric name', () => { diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/BoxPlot/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/BoxPlot/transformProps.ts index 67a3d81db3d5a..929d63b987118 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/BoxPlot/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/BoxPlot/transformProps.ts @@ -19,6 +19,7 @@ import { CategoricalColorNamespace, DataRecordValue, + getColumnLabel, getMetricLabel, getNumberFormatter, getTimeFormatter, @@ -50,7 +51,7 @@ export default function transformProps( const { colorScheme, groupby = [], - metrics: formdataMetrics = [], + metrics = [], numberFormat, dateFormat, xTicksLayout, @@ -64,12 +65,14 @@ export default function transformProps( } = formData as BoxPlotQueryFormData; const colorFn = CategoricalColorNamespace.getScale(colorScheme as string); const numberFormatter = getNumberFormatter(numberFormat); - const metricLabels = formdataMetrics.map(getMetricLabel); + const metricLabels = metrics.map(getMetricLabel); + const groupbyLabels = groupby.map(getColumnLabel); + const transformedData = data .map((datum: any) => { const groupbyLabel = extractGroupbyLabel({ datum, - groupby, + groupby: groupbyLabels, coltypeMapping, timeFormatter: getTimeFormatter(dateFormat), }); @@ -107,7 +110,7 @@ export default function transformProps( metricLabels.map(metric => { const groupbyLabel = extractGroupbyLabel({ datum, - groupby, + groupby: groupbyLabels, coltypeMapping, timeFormatter: getTimeFormatter(dateFormat), }); @@ -127,7 +130,7 @@ export default function transformProps( tooltip: { formatter: (param: { data: [string, number] }) => { const [outlierName, stats] = param.data; - const headline = groupby + const headline = groupbyLabels.length ? `

${sanitizeHtml(outlierName)}

` : ''; return `${headline}${numberFormatter(stats)}`; @@ -148,13 +151,13 @@ export default function transformProps( (acc: Record, datum) => { const label = extractGroupbyLabel({ datum, - groupby, + groupby: groupbyLabels, coltypeMapping, timeFormatter: getTimeFormatter(dateFormat), }); return { ...acc, - [label]: groupby.map(col => datum[col]), + [label]: groupbyLabels.map(col => datum[col]), }; }, {}, diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/BoxPlot/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/BoxPlot/types.ts index a38113e309ac0..73072cb03bd99 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/BoxPlot/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/BoxPlot/types.ts @@ -20,6 +20,7 @@ import { ChartDataResponseResult, ChartProps, DataRecordValue, + QueryFormColumn, QueryFormData, SetDataMaskHook, } from '@superset-ui/core'; @@ -65,6 +66,6 @@ export interface BoxPlotChartTransformedProps { emitFilter: boolean; setDataMask: SetDataMaskHook; labelMap: Record; - groupby: string[]; + groupby: QueryFormColumn[]; selectedValues: Record; } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Funnel/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Funnel/transformProps.ts index ac8e72af63669..3f3d84816d28f 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Funnel/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Funnel/transformProps.ts @@ -24,6 +24,7 @@ import { getNumberFormatter, NumberFormats, NumberFormatter, + getColumnLabel, } from '@superset-ui/core'; import { CallbackDataParams } from 'echarts/types/src/util/types'; import { EChartsCoreOption, FunnelSeriesOption } from 'echarts'; @@ -108,19 +109,20 @@ export default function transformProps( ...formData, }; const metricLabel = getMetricLabel(metric); + const groupbyLabels = groupby.map(getColumnLabel); const keys = data.map(datum => - extractGroupbyLabel({ datum, groupby, coltypeMapping: {} }), + extractGroupbyLabel({ datum, groupby: groupbyLabels, coltypeMapping: {} }), ); const labelMap = data.reduce( (acc: Record, datum) => { const label = extractGroupbyLabel({ datum, - groupby, + groupby: groupbyLabels, coltypeMapping: {}, }); return { ...acc, - [label]: groupby.map(col => datum[col]), + [label]: groupbyLabels.map(col => datum[col]), }; }, {}, @@ -132,7 +134,11 @@ export default function transformProps( const numberFormatter = getNumberFormatter(numberFormat); const transformedData: FunnelSeriesOption[] = data.map(datum => { - const name = extractGroupbyLabel({ datum, groupby, coltypeMapping: {} }); + const name = extractGroupbyLabel({ + datum, + groupby: groupbyLabels, + coltypeMapping: {}, + }); const isFiltered = filterState.selectedValues && !filterState.selectedValues.includes(name); return { diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Funnel/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Funnel/types.ts index 2c979f030bdf9..39eb087ce6bfc 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Funnel/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Funnel/types.ts @@ -21,6 +21,7 @@ import { ChartDataResponseResult, ChartProps, DataRecordValue, + QueryFormColumn, QueryFormData, SetDataMaskHook, } from '@superset-ui/core'; @@ -34,7 +35,7 @@ import { export type EchartsFunnelFormData = QueryFormData & EchartsLegendFormData & { colorScheme?: string; - groupby: string[]; + groupby: QueryFormData[]; labelLine: boolean; labelType: EchartsFunnelLabelTypeType; metric?: string; @@ -84,6 +85,6 @@ export interface FunnelChartTransformedProps { emitFilter: boolean; setDataMask: SetDataMaskHook; labelMap: Record; - groupby: string[]; + groupby: QueryFormColumn[]; selectedValues: Record; } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts index 597c8d084a5e2..beecb475ace7a 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Gauge/transformProps.ts @@ -24,6 +24,7 @@ import { getNumberFormatter, getMetricLabel, DataRecordValue, + getColumnLabel, } from '@superset-ui/core'; import { EChartsCoreOption, GaugeSeriesOption } from 'echarts'; import { GaugeDataItemOption } from 'echarts/types/src/chart/gauge/GaugeSeries'; @@ -116,6 +117,7 @@ export default function transformProps( const axisLabelLength = Math.max( ...axisLabels.map(label => numberFormatter(label).length).concat([1]), ); + const groupbyLabels = groupby.map(getColumnLabel); const formatValue = (value: number) => valueFormatter.replace('{value}', numberFormatter(value)); const axisTickLength = FONT_SIZE_MULTIPLIERS.axisTickLength * fontSize; @@ -134,12 +136,12 @@ export default function transformProps( const transformedData: GaugeDataItemOption[] = data.map( (data_point, index) => { - const name = groupby + const name = groupbyLabels .map(column => `${column}: ${data_point[column]}`) .join(', '); columnsLabelMap.set( name, - groupby.map(col => data_point[col]), + groupbyLabels.map(col => data_point[col]), ); let item: GaugeDataItemOption = { value: data_point[getMetricLabel(metric as QueryFormMetric)] as number, diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Gauge/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Gauge/types.ts index a73632e09a931..32044d4ef648a 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Gauge/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Gauge/types.ts @@ -19,6 +19,7 @@ import { ChartDataResponseResult, ChartProps, + QueryFormColumn, QueryFormData, } from '@superset-ui/core'; import { DEFAULT_LEGEND_FORM_DATA, EChartTransformedProps } from '../types'; @@ -30,7 +31,7 @@ export type AxisTickLineStyle = { export type EchartsGaugeFormData = QueryFormData & { colorScheme?: string; - groupby: string[]; + groupby: QueryFormColumn[]; metric?: object; rowLimit: number; minVal: number; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts index a16c596aa1cbd..b5f37551e1d7c 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/MixedTimeseries/types.ts @@ -25,6 +25,7 @@ import { QueryFormData, ChartProps, ChartDataResponseResult, + QueryFormColumn, } from '@superset-ui/core'; import { DEFAULT_LEGEND_FORM_DATA, @@ -81,8 +82,8 @@ export type EchartsMixedTimeseriesFormData = QueryFormData & { stackB: boolean; yAxisIndex?: number; yAxisIndexB?: number; - groupby: string[]; - groupbyB: string[]; + groupby: QueryFormColumn[]; + groupbyB: QueryFormColumn[]; emitFilter: boolean; } & EchartsLegendFormData & EchartsTitleFormData; @@ -144,8 +145,8 @@ export type EchartsMixedTimeseriesChartTransformedProps = { emitFilter: boolean; emitFilterB: boolean; setDataMask: SetDataMaskHook; - groupby: string[]; - groupbyB: string[]; + groupby: QueryFormColumn[]; + groupbyB: QueryFormColumn[]; labelMap: Record; labelMapB: Record; selectedValues: Record; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Pie/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Pie/transformProps.ts index a7c35d5502453..a70855fa432f7 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Pie/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Pie/transformProps.ts @@ -19,6 +19,7 @@ import { CategoricalColorNamespace, DataRecordValue, + getColumnLabel, getMetricLabel, getNumberFormatter, getTimeFormatter, @@ -114,12 +115,13 @@ export default function transformProps( ...formData, }; const metricLabel = getMetricLabel(metric); + const groupbyLabels = groupby.map(getColumnLabel); const minShowLabelAngle = (showLabelsThreshold || 0) * 3.6; const keys = data.map(datum => extractGroupbyLabel({ datum, - groupby, + groupby: groupbyLabels, coltypeMapping, timeFormatter: getTimeFormatter(dateFormat), }), @@ -128,13 +130,13 @@ export default function transformProps( (acc: Record, datum) => { const label = extractGroupbyLabel({ datum, - groupby, + groupby: groupbyLabels, coltypeMapping, timeFormatter: getTimeFormatter(dateFormat), }); return { ...acc, - [label]: groupby.map(col => datum[col]), + [label]: groupbyLabels.map(col => datum[col]), }; }, {}, @@ -148,7 +150,7 @@ export default function transformProps( const transformedData: PieSeriesOption[] = data.map(datum => { const name = extractGroupbyLabel({ datum, - groupby, + groupby: groupbyLabels, coltypeMapping, timeFormatter: getTimeFormatter(dateFormat), }); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Pie/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Pie/types.ts index 3fe7d59e41c2a..b6411c8346214 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Pie/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Pie/types.ts @@ -21,6 +21,7 @@ import { ChartDataResponseResult, ChartProps, DataRecordValue, + QueryFormColumn, QueryFormData, SetDataMaskHook, } from '@superset-ui/core'; @@ -37,7 +38,7 @@ export type EchartsPieFormData = QueryFormData & currentOwnValue?: string[] | null; donut: boolean; defaultValue?: string[] | null; - groupby: string[]; + groupby: QueryFormColumn[]; innerRadius: number; labelLine: boolean; labelType: EchartsPieLabelType; @@ -92,6 +93,6 @@ export interface PieChartTransformedProps { emitFilter: boolean; setDataMask: SetDataMaskHook; labelMap: Record; - groupby: string[]; + groupby: QueryFormColumn[]; selectedValues: Record; } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Radar/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Radar/transformProps.ts index af1999c66c6f0..2c2a994d506a8 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Radar/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Radar/transformProps.ts @@ -20,6 +20,7 @@ import { CategoricalColorNamespace, DataRecordValue, ensureIsInt, + getColumnLabel, getMetricLabel, getNumberFormatter, getTimeFormatter, @@ -104,7 +105,8 @@ export default function transformProps( labelType, }); - const metricsLabel = metrics.map(metric => getMetricLabel(metric)); + const metricLabels = metrics.map(getMetricLabel); + const groupbyLabels = groupby.map(getColumnLabel); const metricLabelAndMaxValueMap = new Map(); const columnsLabelMap = new Map(); @@ -112,14 +114,14 @@ export default function transformProps( data.forEach(datum => { const joinedName = extractGroupbyLabel({ datum, - groupby, + groupby: groupbyLabels, coltypeMapping, timeFormatter: getTimeFormatter(dateFormat), }); // map(joined_name: [columnLabel_1, columnLabel_2, ...]) columnsLabelMap.set( joinedName, - groupby.map(col => datum[col]), + groupbyLabels.map(col => datum[col]), ); // put max value of series into metricLabelAndMaxValueMap @@ -147,7 +149,7 @@ export default function transformProps( // generate transformedData transformedData.push({ - value: metricsLabel.map(metricLabel => datum[metricLabel]), + value: metricLabels.map(metricLabel => datum[metricLabel]), name: joinedName, itemStyle: { color: colorFn(joinedName), @@ -181,7 +183,7 @@ export default function transformProps( {}, ); - const indicator = metricsLabel.map(metricLabel => { + const indicator = metricLabels.map(metricLabel => { const maxValueInControl = columnConfig?.[metricLabel]?.radarMetricMaxValue; // Ensure that 0 is at the center of the polar coordinates const metricValueAsMax = diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Radar/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Radar/types.ts index 4cdae51681235..9b053b6264554 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Radar/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Radar/types.ts @@ -21,6 +21,7 @@ import { ChartDataResponseResult, ChartProps, DataRecordValue, + QueryFormColumn, QueryFormData, QueryFormMetric, SetDataMaskHook, @@ -42,7 +43,7 @@ export type EchartsRadarFormData = QueryFormData & currentOwnValue?: string[] | null; currentValue?: string[] | null; defaultValue?: string[] | null; - groupby: string[]; + groupby: QueryFormColumn[]; labelType: EchartsRadarLabelType; labelPosition: LabelPositionEnum; metrics: QueryFormMetric[]; @@ -85,6 +86,6 @@ export interface RadarChartTransformedProps { echartOptions: EChartsCoreOption; setDataMask: SetDataMaskHook; labelMap: Record; - groupby: string[]; + groupby: QueryFormColumn[]; selectedValues: Record; } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx index 62c40e44fba1a..68460e1ece290 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Timeseries/Regular/Bar/controlPanel.tsx @@ -27,8 +27,15 @@ import { sharedControls, } from '@superset-ui/chart-controls'; -import { DEFAULT_FORM_DATA, EchartsTimeseriesContributionType } from '../../types'; -import { legendSection, richTooltipSection, showValueSection } from '../../../controls'; +import { + DEFAULT_FORM_DATA, + EchartsTimeseriesContributionType, +} from '../../types'; +import { + legendSection, + richTooltipSection, + showValueSection, +} from '../../../controls'; const { contributionMode, @@ -103,7 +110,9 @@ const config: ControlPanelConfig = { label: t('Marker'), renderTrigger: true, default: markerEnabled, - description: t('Draw a marker on data points. Only applicable for line types.'), + description: t( + 'Draw a marker on data points. Only applicable for line types.', + ), }, }, ], @@ -117,7 +126,9 @@ const config: ControlPanelConfig = { min: 0, max: 20, default: markerSize, - description: t('Size of marker. Also applies to forecast observations.'), + description: t( + 'Size of marker. Also applies to forecast observations.', + ), visibility: ({ controls }: ControlPanelsContainerProps) => Boolean(controls?.markerEnabled?.value), }, @@ -163,7 +174,9 @@ const config: ControlPanelConfig = { ], default: xAxisLabelRotation, renderTrigger: true, - description: t('Input field supports custom rotation. e.g. 30 for 30°'), + description: t( + 'Input field supports custom rotation. e.g. 30 for 30°', + ), }, }, ], @@ -205,7 +218,9 @@ const config: ControlPanelConfig = { label: t('Truncate Y Axis'), default: truncateYAxis, renderTrigger: true, - description: t('It’s not recommended to truncate y-axis in Bar chart.'), + description: t( + 'It’s not recommended to truncate y-axis in Bar chart.', + ), }, }, ], diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Timeseries/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Timeseries/types.ts index b776ec8dd53fa..ac634239229de 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Timeseries/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Timeseries/types.ts @@ -20,6 +20,7 @@ import { AnnotationLayer, ChartDataResponseResult, ChartProps, + QueryFormColumn, QueryFormData, TimeGranularity, } from '@superset-ui/core'; @@ -77,7 +78,7 @@ export type EchartsTimeseriesFormData = QueryFormData & { richTooltip: boolean; xAxisLabelRotation: number; emitFilter: boolean; - groupby: string[]; + groupby: QueryFormColumn[]; showValue: boolean; onlyTotal: boolean; } & EchartsLegendFormData & diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Treemap/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Treemap/transformProps.ts index 95bd8fd6bbf99..2face71250d1a 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Treemap/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Treemap/transformProps.ts @@ -20,6 +20,7 @@ import { CategoricalColorNamespace, DataRecord, DataRecordValue, + getColumnLabel, getMetricLabel, getNumberFormatter, getTimeFormatter, @@ -144,12 +145,12 @@ export default function transformProps( const transformer = ( data: DataRecord[], - groupbyData: string[], + groupbyLabels: string[], metric: string, depth: number, path: string[], ): TreemapSeriesNodeItemOption[] => { - const [currGroupby, ...restGroupby] = groupbyData; + const [currGroupby, ...restGroupby] = groupbyLabels; const currGrouping = groupBy(data, currGroupby); if (!restGroupby.length) { return transform( @@ -230,6 +231,7 @@ export default function transformProps( }; const metricLabel = getMetricLabel(metric); + const groupbyLabels = groupby.map(getColumnLabel); const initialDepth = 1; const transformedData: TreemapSeriesNodeItemOption[] = [ { @@ -243,7 +245,7 @@ export default function transformProps( upperLabel: { show: false, }, - children: transformer(data, groupby, metricLabel, initialDepth, []), + children: transformer(data, groupbyLabels, metricLabel, initialDepth, []), }, ]; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Treemap/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Treemap/types.ts index f84336f702770..e99874d157e60 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Treemap/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/Treemap/types.ts @@ -20,6 +20,7 @@ import { ChartDataResponseResult, ChartProps, DataRecordValue, + QueryFormColumn, QueryFormData, QueryFormMetric, SetDataMaskHook, @@ -30,7 +31,7 @@ import { LabelPositionEnum } from '../types'; export type EchartsTreemapFormData = QueryFormData & { colorScheme?: string; - groupby: string[]; + groupby: QueryFormColumn[]; metric?: QueryFormMetric; labelType: EchartsTreemapLabelType; labelPosition: LabelPositionEnum; @@ -81,6 +82,6 @@ export interface TreemapTransformedProps { emitFilter: boolean; setDataMask: SetDataMaskHook; labelMap: Record; - groupby: string[]; + groupby: QueryFormColumn[]; selectedValues: Record; } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/types.ts index ce745df137308..a66c8a34847db 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/types.ts @@ -16,7 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -import { DataRecordValue, SetDataMaskHook } from '@superset-ui/core'; +import { + DataRecordValue, + QueryFormColumn, + SetDataMaskHook, +} from '@superset-ui/core'; import { EChartsCoreOption, ECharts } from 'echarts'; import { TooltipMarker } from 'echarts/types/src/util/format'; import { OptionName } from 'echarts/types/src/util/types'; @@ -112,7 +116,7 @@ export interface EChartTransformedProps { emitFilter: boolean; setDataMask: SetDataMaskHook; labelMap: Record; - groupby: string[]; + groupby: QueryFormColumn[]; selectedValues: Record; legendData?: OptionName[]; } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/utils/series.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/utils/series.ts index 8eb1516e0b272..324ab06d10884 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/utils/series.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-echarts/src/utils/series.ts @@ -21,6 +21,7 @@ import { ChartDataResponseResult, DataRecord, DataRecordValue, + ensureIsArray, GenericDataType, NumberFormatter, TimeFormatter, @@ -120,7 +121,7 @@ export function extractGroupbyLabel({ timeFormatter?: TimeFormatter; coltypeMapping: Record; }): string { - return (groupby || []) + return ensureIsArray(groupby) .map(val => formatSeriesName(datum[val], { numberFormatter, diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/PivotTableChart.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/PivotTableChart.tsx index e04d471f88900..aab9575561a50 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/PivotTableChart.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/PivotTableChart.tsx @@ -19,11 +19,12 @@ import React, { useCallback, useMemo } from 'react'; import { PlusSquareOutlined, MinusSquareOutlined } from '@ant-design/icons'; import { - styled, AdhocMetric, - getNumberFormatter, DataRecordValue, + getColumnLabel, + getNumberFormatter, NumberFormatter, + styled, useTheme, } from '@superset-ui/core'; // @ts-ignore @@ -115,8 +116,8 @@ export default function PivotTableChart(props: PivotTableProps) { data, height, width, - groupbyRows, - groupbyColumns, + groupbyRows: groupbyRowsRaw, + groupbyColumns: groupbyColumnsRaw, metrics, colOrder, rowOrder, @@ -176,6 +177,8 @@ export default function PivotTableChart(props: PivotTableProps) { ), [data, metricNames], ); + const groupbyRows = groupbyRowsRaw.map(getColumnLabel); + const groupbyColumns = groupbyColumnsRaw.map(getColumnLabel); let [rows, cols] = transposePivot ? [groupbyColumns, groupbyRows] diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/plugin/buildQuery.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/plugin/buildQuery.ts index 43b55a1ffa646..cd5db2aedb0b2 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/plugin/buildQuery.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/plugin/buildQuery.ts @@ -21,6 +21,7 @@ import { ensureIsArray, getMetricLabel, normalizeOrderBy, + QueryFormColumn, } from '@superset-ui/core'; import { PivotTableQueryFormData } from '../types'; @@ -31,9 +32,10 @@ export default function buildQuery(formData: PivotTableQueryFormData) { order_desc = true, legacy_order_by, } = formData; + // TODO: add deduping of AdhocColumns const groupbySet = new Set([ - ...ensureIsArray(groupbyColumns), - ...ensureIsArray(groupbyRows), + ...ensureIsArray(groupbyColumns), + ...ensureIsArray(groupbyRows), ]); return buildQueryContext(formData, baseQueryObject => { const queryObject = normalizeOrderBy({ diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/types.ts index b9f1c8d768677..38d725e922b3a 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/plugin-chart-pivot-table/src/types.ts @@ -19,13 +19,13 @@ import { QueryFormData, DataRecord, - AdhocMetric, SetDataMaskHook, DataRecordValue, JsonObject, TimeFormatter, NumberFormatter, QueryFormMetric, + QueryFormColumn, } from '@superset-ui/core'; import { ColorFormatters } from '@superset-ui/chart-controls'; @@ -48,9 +48,9 @@ export enum MetricsLayoutEnum { } interface PivotTableCustomizeProps { - groupbyRows: string[]; - groupbyColumns: string[]; - metrics: (string | AdhocMetric)[]; + groupbyRows: QueryFormColumn[]; + groupbyColumns: QueryFormColumn[]; + metrics: QueryFormMetric[]; tableRenderer: string; colOrder: string; rowOrder: string;