mirror of
https://github.com/apache/superset.git
synced 2024-09-18 19:49:37 -04:00
feat(plugin-chart-echarts): add x-axis sort to multi series (#23644)
This commit is contained in:
parent
587e7759b1
commit
f49702feff
@ -24,7 +24,7 @@ import {
|
|||||||
QueryColumn,
|
QueryColumn,
|
||||||
DatasourceType,
|
DatasourceType,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
import { ColumnMeta } from './types';
|
import { ColumnMeta, SortSeriesData, SortSeriesType } from './types';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export const TIME_FILTER_LABELS = {
|
export const TIME_FILTER_LABELS = {
|
||||||
@ -57,3 +57,21 @@ export const QueryModeLabel = {
|
|||||||
[QueryMode.aggregate]: t('Aggregate'),
|
[QueryMode.aggregate]: t('Aggregate'),
|
||||||
[QueryMode.raw]: t('Raw records'),
|
[QueryMode.raw]: t('Raw records'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_SORT_SERIES_DATA: SortSeriesData = {
|
||||||
|
sort_series_type: SortSeriesType.Sum,
|
||||||
|
sort_series_ascending: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SORT_SERIES_CHOICES = [
|
||||||
|
[SortSeriesType.Name, t('Category name')],
|
||||||
|
[SortSeriesType.Sum, t('Total value')],
|
||||||
|
[SortSeriesType.Min, t('Minimum value')],
|
||||||
|
[SortSeriesType.Max, t('Maximum value')],
|
||||||
|
[SortSeriesType.Avg, t('Average value')],
|
||||||
|
];
|
||||||
|
|
||||||
|
export const DEFAULT_XAXIS_SORT_SERIES_DATA: SortSeriesData = {
|
||||||
|
sort_series_type: SortSeriesType.Name,
|
||||||
|
sort_series_ascending: true,
|
||||||
|
};
|
||||||
|
@ -20,8 +20,10 @@ import { hasGenericChartAxes, t } from '@superset-ui/core';
|
|||||||
import { ControlPanelSectionConfig, ControlSetRow } from '../types';
|
import { ControlPanelSectionConfig, ControlSetRow } from '../types';
|
||||||
import {
|
import {
|
||||||
contributionModeControl,
|
contributionModeControl,
|
||||||
xAxisSortControl,
|
|
||||||
xAxisSortAscControl,
|
xAxisSortAscControl,
|
||||||
|
xAxisSortControl,
|
||||||
|
xAxisSortSeriesAscendingControl,
|
||||||
|
xAxisSortSeriesControl,
|
||||||
} from '../shared-controls';
|
} from '../shared-controls';
|
||||||
|
|
||||||
const controlsWithoutXAxis: ControlSetRow[] = [
|
const controlsWithoutXAxis: ControlSetRow[] = [
|
||||||
@ -55,6 +57,8 @@ export const echartsTimeSeriesQueryWithXAxisSort: ControlPanelSectionConfig = {
|
|||||||
[hasGenericChartAxes ? 'time_grain_sqla' : null],
|
[hasGenericChartAxes ? 'time_grain_sqla' : null],
|
||||||
[hasGenericChartAxes ? xAxisSortControl : null],
|
[hasGenericChartAxes ? xAxisSortControl : null],
|
||||||
[hasGenericChartAxes ? xAxisSortAscControl : null],
|
[hasGenericChartAxes ? xAxisSortAscControl : null],
|
||||||
|
[hasGenericChartAxes ? xAxisSortSeriesControl : null],
|
||||||
|
[hasGenericChartAxes ? xAxisSortSeriesAscendingControl : null],
|
||||||
...controlsWithoutXAxis,
|
...controlsWithoutXAxis,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -34,6 +34,10 @@ import {
|
|||||||
isDataset,
|
isDataset,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { isTemporalColumn } from '../utils';
|
import { isTemporalColumn } from '../utils';
|
||||||
|
import {
|
||||||
|
DEFAULT_XAXIS_SORT_SERIES_DATA,
|
||||||
|
SORT_SERIES_CHOICES,
|
||||||
|
} from '../constants';
|
||||||
|
|
||||||
export const contributionModeControl = {
|
export const contributionModeControl = {
|
||||||
name: 'contributionMode',
|
name: 'contributionMode',
|
||||||
@ -59,6 +63,19 @@ const xAxisSortVisibility = ({ controls }: { controls: ControlStateMapping }) =>
|
|||||||
Array.isArray(controls?.groupby?.value) &&
|
Array.isArray(controls?.groupby?.value) &&
|
||||||
controls.groupby.value.length === 0;
|
controls.groupby.value.length === 0;
|
||||||
|
|
||||||
|
const xAxisMultiSortVisibility = ({
|
||||||
|
controls,
|
||||||
|
}: {
|
||||||
|
controls: ControlStateMapping;
|
||||||
|
}) =>
|
||||||
|
isDefined(controls?.x_axis?.value) &&
|
||||||
|
!isTemporalColumn(
|
||||||
|
getColumnLabel(controls?.x_axis?.value as QueryFormColumn),
|
||||||
|
controls?.datasource?.datasource,
|
||||||
|
) &&
|
||||||
|
Array.isArray(controls?.groupby?.value) &&
|
||||||
|
!!controls.groupby.value.length;
|
||||||
|
|
||||||
export const xAxisSortControl = {
|
export const xAxisSortControl = {
|
||||||
name: 'x_axis_sort',
|
name: 'x_axis_sort',
|
||||||
config: {
|
config: {
|
||||||
@ -125,3 +142,35 @@ export const xAxisSortAscControl = {
|
|||||||
visibility: xAxisSortVisibility,
|
visibility: xAxisSortVisibility,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const xAxisSortSeriesControl = {
|
||||||
|
name: 'x_axis_sort_series',
|
||||||
|
config: {
|
||||||
|
type: 'SelectControl',
|
||||||
|
freeForm: false,
|
||||||
|
label: (state: ControlPanelState) =>
|
||||||
|
state.form_data?.orientation === 'horizontal'
|
||||||
|
? t('Y-Axis Sort By')
|
||||||
|
: t('X-Axis Sort By'),
|
||||||
|
choices: SORT_SERIES_CHOICES,
|
||||||
|
default: DEFAULT_XAXIS_SORT_SERIES_DATA.sort_series_type,
|
||||||
|
renderTrigger: true,
|
||||||
|
description: t('Decides which measure to sort the base axis by.'),
|
||||||
|
visibility: xAxisMultiSortVisibility,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const xAxisSortSeriesAscendingControl = {
|
||||||
|
name: 'x_axis_sort_series_ascending',
|
||||||
|
config: {
|
||||||
|
type: 'CheckboxControl',
|
||||||
|
label: (state: ControlPanelState) =>
|
||||||
|
state.form_data?.orientation === 'horizontal'
|
||||||
|
? t('Y-Axis Sort Ascending')
|
||||||
|
: t('X-Axis Sort Ascending'),
|
||||||
|
default: DEFAULT_XAXIS_SORT_SERIES_DATA.sort_series_ascending,
|
||||||
|
description: t('Whether to sort ascending or descending on the base Axis.'),
|
||||||
|
renderTrigger: true,
|
||||||
|
visibility: xAxisMultiSortVisibility,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
@ -481,3 +481,16 @@ export function isQueryResponse(
|
|||||||
): datasource is QueryResponse {
|
): datasource is QueryResponse {
|
||||||
return !!datasource && 'results' in datasource && 'sql' in datasource;
|
return !!datasource && 'results' in datasource && 'sql' in datasource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum SortSeriesType {
|
||||||
|
Name = 'name',
|
||||||
|
Max = 'max',
|
||||||
|
Min = 'min',
|
||||||
|
Sum = 'sum',
|
||||||
|
Avg = 'avg',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SortSeriesData = {
|
||||||
|
sort_series_type: SortSeriesType;
|
||||||
|
sort_series_ascending: boolean;
|
||||||
|
};
|
||||||
|
@ -16,7 +16,10 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { sections } from '@superset-ui/chart-controls';
|
import {
|
||||||
|
DEFAULT_SORT_SERIES_DATA,
|
||||||
|
sections,
|
||||||
|
} from '@superset-ui/chart-controls';
|
||||||
import { t } from '@superset-ui/core';
|
import { t } from '@superset-ui/core';
|
||||||
import {
|
import {
|
||||||
OrientationType,
|
OrientationType,
|
||||||
@ -25,7 +28,6 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
import {
|
import {
|
||||||
DEFAULT_LEGEND_FORM_DATA,
|
DEFAULT_LEGEND_FORM_DATA,
|
||||||
DEFAULT_SORT_SERIES_DATA,
|
|
||||||
DEFAULT_TITLE_FORM_DATA,
|
DEFAULT_TITLE_FORM_DATA,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
|
|
||||||
|
@ -146,6 +146,8 @@ export default function transformProps(
|
|||||||
truncateYAxis,
|
truncateYAxis,
|
||||||
xAxis: xAxisOrig,
|
xAxis: xAxisOrig,
|
||||||
xAxisLabelRotation,
|
xAxisLabelRotation,
|
||||||
|
xAxisSortSeries,
|
||||||
|
xAxisSortSeriesAscending,
|
||||||
xAxisTimeFormat,
|
xAxisTimeFormat,
|
||||||
xAxisTitle,
|
xAxisTitle,
|
||||||
xAxisTitleMargin,
|
xAxisTitleMargin,
|
||||||
@ -200,6 +202,10 @@ export default function transformProps(
|
|||||||
isHorizontal,
|
isHorizontal,
|
||||||
sortSeriesType,
|
sortSeriesType,
|
||||||
sortSeriesAscending,
|
sortSeriesAscending,
|
||||||
|
xAxisSortSeries: groupby.length ? xAxisSortSeries : undefined,
|
||||||
|
xAxisSortSeriesAscending: groupby.length
|
||||||
|
? xAxisSortSeriesAscending
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
const showValueIndexes = extractShowValueIndexes(rawSeries, {
|
const showValueIndexes = extractShowValueIndexes(rawSeries, {
|
||||||
stack,
|
stack,
|
||||||
|
@ -24,8 +24,6 @@ import {
|
|||||||
LegendFormData,
|
LegendFormData,
|
||||||
LegendOrientation,
|
LegendOrientation,
|
||||||
LegendType,
|
LegendType,
|
||||||
SortSeriesData,
|
|
||||||
SortSeriesType,
|
|
||||||
TitleFormData,
|
TitleFormData,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
@ -122,8 +120,3 @@ export const TOOLTIP_POINTER_MARGIN = 10;
|
|||||||
// If no satisfactory position can be found, how far away
|
// If no satisfactory position can be found, how far away
|
||||||
// from the edge of the window should the tooltip be kept
|
// from the edge of the window should the tooltip be kept
|
||||||
export const TOOLTIP_OVERFLOW_MARGIN = 5;
|
export const TOOLTIP_OVERFLOW_MARGIN = 5;
|
||||||
|
|
||||||
export const DEFAULT_SORT_SERIES_DATA: SortSeriesData = {
|
|
||||||
sort_series_type: SortSeriesType.Sum,
|
|
||||||
sort_series_ascending: false,
|
|
||||||
};
|
|
||||||
|
@ -22,15 +22,12 @@ import {
|
|||||||
ControlPanelsContainerProps,
|
ControlPanelsContainerProps,
|
||||||
ControlSetItem,
|
ControlSetItem,
|
||||||
ControlSetRow,
|
ControlSetRow,
|
||||||
|
DEFAULT_SORT_SERIES_DATA,
|
||||||
|
SORT_SERIES_CHOICES,
|
||||||
sharedControls,
|
sharedControls,
|
||||||
} from '@superset-ui/chart-controls';
|
} from '@superset-ui/chart-controls';
|
||||||
import {
|
import { DEFAULT_LEGEND_FORM_DATA, StackControlOptions } from './constants';
|
||||||
DEFAULT_LEGEND_FORM_DATA,
|
|
||||||
DEFAULT_SORT_SERIES_DATA,
|
|
||||||
StackControlOptions,
|
|
||||||
} from './constants';
|
|
||||||
import { DEFAULT_FORM_DATA } from './Timeseries/constants';
|
import { DEFAULT_FORM_DATA } from './Timeseries/constants';
|
||||||
import { SortSeriesType } from './types';
|
|
||||||
|
|
||||||
const { legendMargin, legendOrientation, legendType, showLegend } =
|
const { legendMargin, legendOrientation, legendType, showLegend } =
|
||||||
DEFAULT_LEGEND_FORM_DATA;
|
DEFAULT_LEGEND_FORM_DATA;
|
||||||
@ -225,13 +222,7 @@ const sortSeriesType: ControlSetItem = {
|
|||||||
type: 'SelectControl',
|
type: 'SelectControl',
|
||||||
freeForm: false,
|
freeForm: false,
|
||||||
label: t('Sort Series By'),
|
label: t('Sort Series By'),
|
||||||
choices: [
|
choices: SORT_SERIES_CHOICES,
|
||||||
[SortSeriesType.Name, t('Category name')],
|
|
||||||
[SortSeriesType.Sum, t('Total value')],
|
|
||||||
[SortSeriesType.Min, t('Minimum value')],
|
|
||||||
[SortSeriesType.Max, t('Maximum value')],
|
|
||||||
[SortSeriesType.Avg, t('Average value')],
|
|
||||||
],
|
|
||||||
default: DEFAULT_SORT_SERIES_DATA.sort_series_type,
|
default: DEFAULT_SORT_SERIES_DATA.sort_series_type,
|
||||||
renderTrigger: true,
|
renderTrigger: true,
|
||||||
description: t(
|
description: t(
|
||||||
|
@ -167,17 +167,4 @@ export interface TreePathInfo {
|
|||||||
value: number | number[];
|
value: number | number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum SortSeriesType {
|
|
||||||
Name = 'name',
|
|
||||||
Max = 'max',
|
|
||||||
Min = 'min',
|
|
||||||
Sum = 'sum',
|
|
||||||
Avg = 'avg',
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SortSeriesData = {
|
|
||||||
sort_series_type: SortSeriesType;
|
|
||||||
sort_series_ascending: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export * from './Timeseries/types';
|
export * from './Timeseries/types';
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
|
AxisType,
|
||||||
ChartDataResponseResult,
|
ChartDataResponseResult,
|
||||||
DataRecord,
|
DataRecord,
|
||||||
DataRecordValue,
|
DataRecordValue,
|
||||||
@ -27,22 +28,17 @@ import {
|
|||||||
NumberFormats,
|
NumberFormats,
|
||||||
NumberFormatter,
|
NumberFormatter,
|
||||||
TimeFormatter,
|
TimeFormatter,
|
||||||
AxisType,
|
|
||||||
SupersetTheme,
|
SupersetTheme,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
|
import { SortSeriesType } from '@superset-ui/chart-controls';
|
||||||
import { format, LegendComponentOption, SeriesOption } from 'echarts';
|
import { format, LegendComponentOption, SeriesOption } from 'echarts';
|
||||||
import { sumBy, meanBy, minBy, maxBy, orderBy } from 'lodash';
|
import { maxBy, meanBy, minBy, orderBy, sumBy } from 'lodash';
|
||||||
import {
|
import {
|
||||||
StackControlsValue,
|
|
||||||
NULL_STRING,
|
NULL_STRING,
|
||||||
|
StackControlsValue,
|
||||||
TIMESERIES_CONSTANTS,
|
TIMESERIES_CONSTANTS,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import {
|
import { LegendOrientation, LegendType, StackType } from '../types';
|
||||||
LegendOrientation,
|
|
||||||
LegendType,
|
|
||||||
SortSeriesType,
|
|
||||||
StackType,
|
|
||||||
} from '../types';
|
|
||||||
import { defaultLegendPadding } from '../defaults';
|
import { defaultLegendPadding } from '../defaults';
|
||||||
|
|
||||||
function isDefined<T>(value: T | undefined | null): boolean {
|
function isDefined<T>(value: T | undefined | null): boolean {
|
||||||
@ -155,6 +151,84 @@ export function sortAndFilterSeries(
|
|||||||
).map(({ name }) => name);
|
).map(({ name }) => name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function sortRows(
|
||||||
|
rows: DataRecord[],
|
||||||
|
xAxis: string,
|
||||||
|
xAxisSortSeries: SortSeriesType,
|
||||||
|
xAxisSortSeriesAscending: boolean,
|
||||||
|
) {
|
||||||
|
const sortedRows = rows.map(row => {
|
||||||
|
let sortKey: DataRecordValue = '';
|
||||||
|
let aggregate: number | undefined;
|
||||||
|
let entries = 0;
|
||||||
|
Object.entries(row).forEach(([key, value]) => {
|
||||||
|
const isValueDefined = isDefined(value);
|
||||||
|
if (key === xAxis) {
|
||||||
|
sortKey = value;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
xAxisSortSeries === SortSeriesType.Name ||
|
||||||
|
typeof value !== 'number'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(xAxisSortSeries === SortSeriesType.Avg && !isValueDefined)) {
|
||||||
|
entries += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (xAxisSortSeries) {
|
||||||
|
case SortSeriesType.Avg:
|
||||||
|
case SortSeriesType.Sum:
|
||||||
|
if (aggregate === undefined) {
|
||||||
|
aggregate = value;
|
||||||
|
} else {
|
||||||
|
aggregate += value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SortSeriesType.Min:
|
||||||
|
aggregate =
|
||||||
|
aggregate === undefined || (isValueDefined && value < aggregate)
|
||||||
|
? value
|
||||||
|
: aggregate;
|
||||||
|
break;
|
||||||
|
case SortSeriesType.Max:
|
||||||
|
aggregate =
|
||||||
|
aggregate === undefined || (isValueDefined && value > aggregate)
|
||||||
|
? value
|
||||||
|
: aggregate;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (
|
||||||
|
xAxisSortSeries === SortSeriesType.Avg &&
|
||||||
|
entries > 0 &&
|
||||||
|
aggregate !== undefined
|
||||||
|
) {
|
||||||
|
aggregate /= entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value =
|
||||||
|
xAxisSortSeries === SortSeriesType.Name && typeof sortKey === 'string'
|
||||||
|
? sortKey.toLowerCase()
|
||||||
|
: aggregate;
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: sortKey,
|
||||||
|
value,
|
||||||
|
row,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return orderBy(
|
||||||
|
sortedRows,
|
||||||
|
['value'],
|
||||||
|
[xAxisSortSeriesAscending ? 'asc' : 'desc'],
|
||||||
|
).map(({ row }) => row);
|
||||||
|
}
|
||||||
|
|
||||||
export function extractSeries(
|
export function extractSeries(
|
||||||
data: DataRecord[],
|
data: DataRecord[],
|
||||||
opts: {
|
opts: {
|
||||||
@ -167,6 +241,8 @@ export function extractSeries(
|
|||||||
isHorizontal?: boolean;
|
isHorizontal?: boolean;
|
||||||
sortSeriesType?: SortSeriesType;
|
sortSeriesType?: SortSeriesType;
|
||||||
sortSeriesAscending?: boolean;
|
sortSeriesAscending?: boolean;
|
||||||
|
xAxisSortSeries?: SortSeriesType;
|
||||||
|
xAxisSortSeriesAscending?: boolean;
|
||||||
} = {},
|
} = {},
|
||||||
): SeriesOption[] {
|
): SeriesOption[] {
|
||||||
const {
|
const {
|
||||||
@ -179,24 +255,30 @@ export function extractSeries(
|
|||||||
isHorizontal = false,
|
isHorizontal = false,
|
||||||
sortSeriesType,
|
sortSeriesType,
|
||||||
sortSeriesAscending,
|
sortSeriesAscending,
|
||||||
|
xAxisSortSeries,
|
||||||
|
xAxisSortSeriesAscending,
|
||||||
} = opts;
|
} = opts;
|
||||||
if (data.length === 0) return [];
|
if (data.length === 0) return [];
|
||||||
const rows: DataRecord[] = data.map(datum => ({
|
const rows: DataRecord[] = data.map(datum => ({
|
||||||
...datum,
|
...datum,
|
||||||
[xAxis]: datum[xAxis],
|
[xAxis]: datum[xAxis],
|
||||||
}));
|
}));
|
||||||
const series = sortAndFilterSeries(
|
const sortedSeries = sortAndFilterSeries(
|
||||||
rows,
|
rows,
|
||||||
xAxis,
|
xAxis,
|
||||||
extraMetricLabels,
|
extraMetricLabels,
|
||||||
sortSeriesType,
|
sortSeriesType,
|
||||||
sortSeriesAscending,
|
sortSeriesAscending,
|
||||||
);
|
);
|
||||||
|
const sortedRows =
|
||||||
|
isDefined(xAxisSortSeries) && isDefined(xAxisSortSeriesAscending)
|
||||||
|
? sortRows(rows, xAxis, xAxisSortSeries!, xAxisSortSeriesAscending!)
|
||||||
|
: rows;
|
||||||
|
|
||||||
return series.map(name => ({
|
return sortedSeries.map(name => ({
|
||||||
id: name,
|
id: name,
|
||||||
name,
|
name,
|
||||||
data: rows
|
data: sortedRows
|
||||||
.map((row, idx) => {
|
.map((row, idx) => {
|
||||||
const isNextToDefinedValue =
|
const isNextToDefinedValue =
|
||||||
isDefined(rows[idx - 1]?.[name]) || isDefined(rows[idx + 1]?.[name]);
|
isDefined(rows[idx - 1]?.[name]) || isDefined(rows[idx + 1]?.[name]);
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { SortSeriesType } from '@superset-ui/chart-controls';
|
||||||
import {
|
import {
|
||||||
DataRecord,
|
DataRecord,
|
||||||
getNumberFormatter,
|
getNumberFormatter,
|
||||||
@ -33,8 +34,9 @@ import {
|
|||||||
getOverMaxHiddenFormatter,
|
getOverMaxHiddenFormatter,
|
||||||
sanitizeHtml,
|
sanitizeHtml,
|
||||||
sortAndFilterSeries,
|
sortAndFilterSeries,
|
||||||
|
sortRows,
|
||||||
} from '../../src/utils/series';
|
} from '../../src/utils/series';
|
||||||
import { LegendOrientation, LegendType, SortSeriesType } from '../../src/types';
|
import { LegendOrientation, LegendType } from '../../src/types';
|
||||||
import { defaultLegendPadding } from '../../src/defaults';
|
import { defaultLegendPadding } from '../../src/defaults';
|
||||||
import { NULL_STRING } from '../../src/constants';
|
import { NULL_STRING } from '../../src/constants';
|
||||||
|
|
||||||
@ -48,42 +50,149 @@ const expectedThemeProps = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
test('sortAndFilterSeries', () => {
|
const sortData: DataRecord[] = [
|
||||||
const data: DataRecord[] = [
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
];
|
||||||
|
|
||||||
|
test('sortRows by name ascending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Name, true)).toEqual([
|
||||||
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
];
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by name descending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Name, false)).toEqual([
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by sum ascending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Sum, true)).toEqual([
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by sum descending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Sum, false)).toEqual([
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by avg ascending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Avg, true)).toEqual([
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by avg descending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Avg, false)).toEqual([
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by min ascending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Min, true)).toEqual([
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by min descending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Min, false)).toEqual([
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by max ascending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Min, true)).toEqual([
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortRows by max descending', () => {
|
||||||
|
expect(sortRows(sortData, 'my_x_axis', SortSeriesType.Min, false)).toEqual([
|
||||||
|
{ my_x_axis: 'foo', x: null, y: 10, z: 5 },
|
||||||
|
{ my_x_axis: null, x: 4, y: 3, z: 7 },
|
||||||
|
{ my_x_axis: 'abc', x: 1, y: 0, z: 2 },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by min ascending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Min, true),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Min, true),
|
||||||
).toEqual(['y', 'x', 'z']);
|
).toEqual(['y', 'x', 'z']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by min descending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Min, false),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Min, false),
|
||||||
).toEqual(['z', 'x', 'y']);
|
).toEqual(['z', 'x', 'y']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by max ascending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Max, true),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Max, true),
|
||||||
).toEqual(['x', 'z', 'y']);
|
).toEqual(['x', 'z', 'y']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by max descending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Max, false),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Max, false),
|
||||||
).toEqual(['y', 'z', 'x']);
|
).toEqual(['y', 'z', 'x']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by avg ascending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Avg, true),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Avg, true),
|
||||||
).toEqual(['x', 'y', 'z']);
|
).toEqual(['x', 'y', 'z']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by avg descending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Avg, false),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Avg, false),
|
||||||
).toEqual(['z', 'y', 'x']);
|
).toEqual(['z', 'y', 'x']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by sum ascending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Sum, true),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Sum, true),
|
||||||
).toEqual(['x', 'y', 'z']);
|
).toEqual(['x', 'y', 'z']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by sum descending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Sum, false),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Sum, false),
|
||||||
).toEqual(['z', 'y', 'x']);
|
).toEqual(['z', 'y', 'x']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by name ascending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Name, true),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, true),
|
||||||
).toEqual(['x', 'y', 'z']);
|
).toEqual(['x', 'y', 'z']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortAndFilterSeries by name descending', () => {
|
||||||
expect(
|
expect(
|
||||||
sortAndFilterSeries(data, 'my_x_axis', [], SortSeriesType.Name, false),
|
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, false),
|
||||||
).toEqual(['z', 'y', 'x']);
|
).toEqual(['z', 'y', 'x']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user