mirror of
https://github.com/apache/superset.git
synced 2026-04-20 00:24:38 +00:00
feat(plugin-chart-echarts): support non-timeseries x-axis (#17917)
* feat(plugin-chart-echarts): support non-timeseries x-axis * fix tests * change formula return type from Date to number * add x_axis test coverage * rename func and improve coverage * add x-axis control to bar chart * remove redundant console.log * fix description * make x-axis control mandatory * 🙃 * fix x-axis formatter * fix showValues * fix implicit rDTTM_ALIAS references in postProcessing * replace TIME_COLUMN with DTTM_ALIAS * fix remaining implicit indexes * fix: Disable filtering on wide result sets (#18021) * fix: handle null values in time-series table (#18039) * cleanup column_type_mappings (#17569) Signed-off-by: Đặng Minh Dũng <dungdm93@live.com> * important change to MakeFile (#18037) * add missing is_timeseries to pivot op Co-authored-by: Erik Ritter <erik.ritter@airbnb.com> Co-authored-by: Grace Guo <grace.guo@airbnb.com> Co-authored-by: Đặng Minh Dũng <dungdm93@live.com> Co-authored-by: AAfghahi <48933336+AAfghahi@users.noreply.github.com>
This commit is contained in:
@@ -34,11 +34,11 @@ import {
|
||||
export function evalFormula(
|
||||
formula: FormulaAnnotationLayer,
|
||||
data: TimeseriesDataRecord[],
|
||||
): [Date, number][] {
|
||||
): [number, number][] {
|
||||
const { value: expression } = formula;
|
||||
|
||||
return data.map(row => [
|
||||
new Date(Number(row.__timestamp)),
|
||||
Number(row.__timestamp),
|
||||
evalExpression(expression, row.__timestamp as number),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { TimeseriesDataRecord, NumberFormatter } from '@superset-ui/core';
|
||||
import {
|
||||
TimeseriesDataRecord,
|
||||
NumberFormatter,
|
||||
DTTM_ALIAS,
|
||||
} from '@superset-ui/core';
|
||||
import { CallbackDataParams, OptionName } from 'echarts/types/src/util/types';
|
||||
import { TooltipMarker } from 'echarts/types/src/util/format';
|
||||
import {
|
||||
@@ -117,7 +121,7 @@ export function rebaseTimeseriesDatum(
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
return data.map(row => {
|
||||
const newRow: TimeseriesDataRecord = { __timestamp: '' };
|
||||
const newRow: TimeseriesDataRecord = { [DTTM_ALIAS]: '' };
|
||||
keys.forEach(key => {
|
||||
const forecastContext = extractForecastSeriesContext(key);
|
||||
const lowerKey = `${forecastContext.name}${ForecastSeriesEnum.ForecastLower}`;
|
||||
@@ -131,7 +135,7 @@ export function rebaseTimeseriesDatum(
|
||||
value -= row[lowerKey] as number;
|
||||
}
|
||||
const newKey =
|
||||
key !== '__timestamp' && verboseMap[key] ? verboseMap[key] : key;
|
||||
key !== DTTM_ALIAS && verboseMap[key] ? verboseMap[key] : key;
|
||||
newRow[newKey] = value;
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||
|
||||
@@ -21,11 +21,11 @@ import {
|
||||
ChartDataResponseResult,
|
||||
DataRecord,
|
||||
DataRecordValue,
|
||||
DTTM_ALIAS,
|
||||
ensureIsArray,
|
||||
GenericDataType,
|
||||
NumberFormatter,
|
||||
TimeFormatter,
|
||||
TimeseriesDataRecord,
|
||||
} from '@superset-ui/core';
|
||||
import { format, LegendComponentOption, SeriesOption } from 'echarts';
|
||||
import { NULL_STRING, TIMESERIES_CONSTANTS } from '../constants';
|
||||
@@ -36,37 +36,40 @@ function isDefined<T>(value: T | undefined | null): boolean {
|
||||
return value !== undefined && value !== null;
|
||||
}
|
||||
|
||||
export function extractTimeseriesSeries(
|
||||
data: TimeseriesDataRecord[],
|
||||
opts: { fillNeighborValue?: number } = {},
|
||||
export function extractSeries(
|
||||
data: DataRecord[],
|
||||
opts: {
|
||||
fillNeighborValue?: number;
|
||||
xAxis?: string;
|
||||
removeNulls?: boolean;
|
||||
} = {},
|
||||
): SeriesOption[] {
|
||||
const { fillNeighborValue } = opts;
|
||||
const { fillNeighborValue, xAxis = DTTM_ALIAS, removeNulls = false } = opts;
|
||||
if (data.length === 0) return [];
|
||||
const rows: TimeseriesDataRecord[] = data.map(datum => ({
|
||||
const rows: DataRecord[] = data.map(datum => ({
|
||||
...datum,
|
||||
__timestamp:
|
||||
datum.__timestamp || datum.__timestamp === 0
|
||||
? new Date(datum.__timestamp)
|
||||
: null,
|
||||
[xAxis]: datum[xAxis],
|
||||
}));
|
||||
|
||||
return Object.keys(rows[0])
|
||||
.filter(key => key !== '__timestamp')
|
||||
.filter(key => key !== xAxis && key !== DTTM_ALIAS)
|
||||
.map(key => ({
|
||||
id: key,
|
||||
name: key,
|
||||
data: rows.map((row, idx) => {
|
||||
const isNextToDefinedValue =
|
||||
isDefined(rows[idx - 1]?.[key]) || isDefined(rows[idx + 1]?.[key]);
|
||||
return [
|
||||
row.__timestamp,
|
||||
!isDefined(row[key]) &&
|
||||
isNextToDefinedValue &&
|
||||
fillNeighborValue !== undefined
|
||||
? fillNeighborValue
|
||||
: row[key],
|
||||
];
|
||||
}),
|
||||
data: rows
|
||||
.map((row, idx) => {
|
||||
const isNextToDefinedValue =
|
||||
isDefined(rows[idx - 1]?.[key]) || isDefined(rows[idx + 1]?.[key]);
|
||||
return [
|
||||
row[xAxis],
|
||||
!isDefined(row[key]) &&
|
||||
isNextToDefinedValue &&
|
||||
fillNeighborValue !== undefined
|
||||
? fillNeighborValue
|
||||
: row[key],
|
||||
];
|
||||
})
|
||||
.filter(obs => !removeNulls || (obs[0] !== null && obs[1] !== null)),
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -102,7 +105,10 @@ export function formatSeriesName(
|
||||
export const getColtypesMapping = ({
|
||||
coltypes = [],
|
||||
colnames = [],
|
||||
}: ChartDataResponseResult): Record<string, GenericDataType> =>
|
||||
}: Pick<ChartDataResponseResult, 'coltypes' | 'colnames'>): Record<
|
||||
string,
|
||||
GenericDataType
|
||||
> =>
|
||||
colnames.reduce(
|
||||
(accumulator, item, index) => ({ ...accumulator, [item]: coltypes[index] }),
|
||||
{},
|
||||
@@ -119,7 +125,7 @@ export function extractGroupbyLabel({
|
||||
groupby?: string[] | null;
|
||||
numberFormatter?: NumberFormatter;
|
||||
timeFormatter?: TimeFormatter;
|
||||
coltypeMapping: Record<string, GenericDataType>;
|
||||
coltypeMapping?: Record<string, GenericDataType>;
|
||||
}): string {
|
||||
return ensureIsArray(groupby)
|
||||
.map(val =>
|
||||
|
||||
Reference in New Issue
Block a user