Skip to content

Commit

Permalink
feat(xy): optionally rounds the domain to nice values (opensearch-pro…
Browse files Browse the repository at this point in the history
…ject#1087)

Extends the domain so that it starts and ends on nice round values.
  • Loading branch information
markov00 authored Apr 13, 2021
1 parent 15c0d78 commit 9c2eefc
Show file tree
Hide file tree
Showing 36 changed files with 923 additions and 605 deletions.
2 changes: 2 additions & 0 deletions packages/osd-charts/api/charts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1678,7 +1678,9 @@ export type SeriesNameFn = (series: XYChartSeriesIdentifier, isTooltip: boolean)
// @public (undocumented)
export interface SeriesScales {
timeZone?: string;
xNice?: boolean;
xScaleType: XScaleType;
yNice?: boolean;
// @deprecated
yScaleToDataExtent?: boolean;
yScaleType: ScaleContinuousType;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,16 @@ export function shapeViewModel(
let xValues = xDomain.domain as any[];

const timeScale =
xDomain.scaleType === ScaleType.Time
xDomain.type === ScaleType.Time
? new ScaleContinuous(
{
type: ScaleType.Time,
domain: xDomain.domain,
range: [0, chartDimensions.width],
nice: false,
},
{
ticks: getTicks(chartDimensions.width, config.xAxisLabel),
desiredTickCount: getTicks(chartDimensions.width, config.xAxisLabel),
timeZone: config.timeZone,
},
)
Expand Down Expand Up @@ -315,7 +316,7 @@ export function shapeViewModel(
* @param y
*/
const pickHighlightedArea: PickHighlightedArea = (x: Array<string | number>, y: Array<string | number>) => {
if (xDomain.scaleType !== ScaleType.Time) {
if (xDomain.type !== ScaleType.Time) {
return null;
}
const [startValue, endValue] = x;
Expand Down
3 changes: 2 additions & 1 deletion packages/osd-charts/src/chart_types/heatmap/specs/heatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { Accessor, AccessorFn } from '../../../utils/accessor';
import { Color, Datum, RecursivePartial } from '../../../utils/common';
import { config } from '../layout/config/config';
import { Config } from '../layout/types/config_types';
import { X_SCALE_DEFAULT } from './scale_defaults';

const defaultProps = {
chartType: ChartType.Heatmap,
Expand All @@ -38,7 +39,7 @@ const defaultProps = {
colorScale: ScaleType.Linear,
xAccessor: ({ x }: { x: string | number }) => x,
yAccessor: ({ y }: { y: string | number }) => y,
xScaleType: ScaleType.Ordinal,
xScaleType: X_SCALE_DEFAULT.type,
valueAccessor: ({ value }: { value: string | number }) => value,
valueFormatter: (value: number) => `${value}`,
xSortPredicate: Predicate.AlphaAsc,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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 { ScaleType } from '../../../scales/constants';

/** @internal */
export const X_SCALE_DEFAULT = {
type: ScaleType.Ordinal,
nice: false,
desiredTickCount: 10,
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { getChartIdSelector } from '../../../../state/selectors/get_chart_id';
import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs';
import { getAccessorValue } from '../../../../utils/accessor';
import { mergeXDomain } from '../../../xy_chart/domains/x_domain';
import { getXNiceFromSpec, getXScaleTypeFromSpec } from '../../../xy_chart/scales/get_api_scales';
import { X_SCALE_DEFAULT } from '../../specs/scale_defaults';
import { HeatmapTable } from './compute_chart_dimensions';
import { getHeatmapSpecSelector } from './get_heatmap_spec';

Expand Down Expand Up @@ -73,7 +75,16 @@ export const getHeatmapTableSelector = createCachedSelector(
},
);

resultData.xDomain = mergeXDomain([{ xScaleType: spec.xScaleType }], resultData.xValues, xDomain);
resultData.xDomain = mergeXDomain(
{
type: getXScaleTypeFromSpec(spec.xScaleType),
nice: getXNiceFromSpec(),
isBandScale: false,
desiredTickCount: X_SCALE_DEFAULT.desiredTickCount,
customDomain: xDomain,
},
resultData.xValues,
);

// sort values by their predicates
if (spec.xScaleType === ScaleType.Ordinal) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { getHeatmapTableSelector } from './get_heatmap_table';
export const getXAxisRightOverflow = createCachedSelector(
[getHeatmapConfigSelector, getHeatmapTableSelector],
({ xAxisLabel: { fontSize, fontFamily, padding, formatter, width }, timeZone }, { xDomain }): number => {
if (xDomain.scaleType !== ScaleType.Time) {
if (xDomain.type !== ScaleType.Time) {
return 0;
}
if (typeof width === 'number') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
*/

import { ChartType } from '../..';
import { MockGlobalSpec } from '../../../mocks/specs/specs';
import { MockXDomain } from '../../../mocks/xy/domains';
import { ScaleType } from '../../../scales/constants';
import { SpecType } from '../../../specs/constants';
import { Dimensions } from '../../../utils/dimensions';
import { getScaleConfigsFromSpecs } from '../state/selectors/get_api_scale_configs';
import { computeSeriesDomains } from '../state/utils/utils';
import { computeXScale } from '../utils/scales';
import { BasicSeriesSpec, SeriesType } from '../utils/specs';
Expand Down Expand Up @@ -97,22 +100,35 @@ describe('Crosshair utils linear scale', () => {
yScaleType: ScaleType.Linear,
};

const domainGroup = new Map([['group1', { fit: true }]]);

const barSeries = [barSeries1];
const barSeriesDomains = computeSeriesDomains(barSeries, domainGroup);
const barSeriesDomains = computeSeriesDomains(
barSeries,
getScaleConfigsFromSpecs([], barSeries, MockGlobalSpec.settings()),
);

const multiBarSeries = [barSeries1, barSeries2];
const multiBarSeriesDomains = computeSeriesDomains(multiBarSeries, domainGroup);
const multiBarSeriesDomains = computeSeriesDomains(
multiBarSeries,
getScaleConfigsFromSpecs([], multiBarSeries, MockGlobalSpec.settings()),
);

const lineSeries = [lineSeries1];
const lineSeriesDomains = computeSeriesDomains(lineSeries, domainGroup);
const lineSeriesDomains = computeSeriesDomains(
lineSeries,
getScaleConfigsFromSpecs([], lineSeries, MockGlobalSpec.settings()),
);

const multiLineSeries = [lineSeries1, lineSeries2];
const multiLineSeriesDomains = computeSeriesDomains(multiLineSeries, domainGroup);
const multiLineSeriesDomains = computeSeriesDomains(
multiLineSeries,
getScaleConfigsFromSpecs([], multiLineSeries, MockGlobalSpec.settings()),
);

const mixedLinesBars = [lineSeries1, lineSeries2, barSeries1, barSeries2];
const mixedLinesBarsSeriesDomains = computeSeriesDomains(mixedLinesBars, domainGroup);
const mixedLinesBarsSeriesDomains = computeSeriesDomains(
mixedLinesBars,
getScaleConfigsFromSpecs([], mixedLinesBars, MockGlobalSpec.settings()),
);

const barSeriesScale = computeXScale({
xDomain: barSeriesDomains.xDomain,
Expand Down Expand Up @@ -1456,13 +1472,11 @@ describe('Crosshair utils linear scale', () => {
const chartDimensions: Dimensions = { top: 0, left: 0, width: 120, height: 120 };
test('cursor at begin of domain', () => {
const barSeriesScaleLimited = computeXScale({
xDomain: {
xDomain: MockXDomain.fromScaleType(ScaleType.Linear, {
domain: [0.5, 3.5],
isBandScale: true,
minInterval: 1,
scaleType: ScaleType.Linear,
type: 'xDomain',
},
}),
totalBarsInCluster: 1,
range: [0, 120],
});
Expand All @@ -1487,13 +1501,11 @@ describe('Crosshair utils linear scale', () => {
});
test('cursor at end of domain', () => {
const barSeriesScaleLimited = computeXScale({
xDomain: {
xDomain: MockXDomain.fromScaleType(ScaleType.Linear, {
domain: [-0.5, 2.5],
isBandScale: true,
minInterval: 1,
scaleType: ScaleType.Linear,
type: 'xDomain',
},
}),
totalBarsInCluster: barSeries.length,
range: [0, 120],
});
Expand All @@ -1518,13 +1530,11 @@ describe('Crosshair utils linear scale', () => {
});
test('cursor at top begin of domain', () => {
const barSeriesScaleLimited = computeXScale({
xDomain: {
xDomain: MockXDomain.fromScaleType(ScaleType.Linear, {
domain: [0.5, 3.5],
isBandScale: true,
minInterval: 1,
scaleType: ScaleType.Linear,
type: 'xDomain',
},
}),
totalBarsInCluster: 1,
range: [0, 120],
});
Expand All @@ -1549,13 +1559,11 @@ describe('Crosshair utils linear scale', () => {
});
test('cursor at top end of domain', () => {
const barSeriesScaleLimited = computeXScale({
xDomain: {
xDomain: MockXDomain.fromScaleType(ScaleType.Linear, {
domain: [-0.5, 2.5],
isBandScale: true,
minInterval: 1,
scaleType: ScaleType.Linear,
type: 'xDomain',
},
}),
totalBarsInCluster: barSeries.length,
range: [0, 120],
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
*/

import { ChartType } from '../..';
import { MockGlobalSpec } from '../../../mocks/specs/specs';
import { ScaleType } from '../../../scales/constants';
import { SpecType } from '../../../specs/constants';
import { getScaleConfigsFromSpecs } from '../state/selectors/get_api_scale_configs';
import { computeSeriesDomains } from '../state/utils/utils';
import { computeXScale } from '../utils/scales';
import { BasicSeriesSpec, SeriesType } from '../utils/specs';
Expand Down Expand Up @@ -96,22 +98,36 @@ describe('Crosshair utils ordinal scales', () => {
yScaleType: ScaleType.Linear,
};

const domainGroup = new Map([['group1', { fit: true }]]);

const barSeries = [barSeries1];
const barSeriesDomains = computeSeriesDomains(barSeries, domainGroup);

const barSeriesDomains = computeSeriesDomains(
barSeries,
getScaleConfigsFromSpecs([], barSeries, MockGlobalSpec.settings()),
);

const multiBarSeries = [barSeries1, barSeries2];
const multiBarSeriesDomains = computeSeriesDomains(multiBarSeries, domainGroup);
const multiBarSeriesDomains = computeSeriesDomains(
multiBarSeries,
getScaleConfigsFromSpecs([], multiBarSeries, MockGlobalSpec.settings()),
);

const lineSeries = [lineSeries1];
const lineSeriesDomains = computeSeriesDomains(lineSeries, domainGroup);
const lineSeriesDomains = computeSeriesDomains(
lineSeries,
getScaleConfigsFromSpecs([], lineSeries, MockGlobalSpec.settings()),
);

const multiLineSeries = [lineSeries1, lineSeries2];
const multiLineSeriesDomains = computeSeriesDomains(multiLineSeries, domainGroup);
const multiLineSeriesDomains = computeSeriesDomains(
multiLineSeries,
getScaleConfigsFromSpecs([], multiLineSeries, MockGlobalSpec.settings()),
);

const mixedLinesBars = [lineSeries1, lineSeries2, barSeries1, barSeries2];
const mixedLinesBarsSeriesDomains = computeSeriesDomains(mixedLinesBars, domainGroup);
const mixedLinesBarsSeriesDomains = computeSeriesDomains(
mixedLinesBars,
getScaleConfigsFromSpecs([], mixedLinesBars, MockGlobalSpec.settings()),
);

const barSeriesScale = computeXScale({
xDomain: barSeriesDomains.xDomain,
Expand Down
23 changes: 23 additions & 0 deletions packages/osd-charts/src/chart_types/xy_chart/domains/nice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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.
*/

/** @internal */
export function areAllNiceDomain(nice: Array<boolean>) {
return nice.length > 0 && nice.every((d) => d);
}
42 changes: 19 additions & 23 deletions packages/osd-charts/src/chart_types/xy_chart/domains/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,31 @@
*/

import { ScaleContinuousType } from '../../../scales';
import { ScaleType } from '../../../scales/constants';
import { LogScaleOptions } from '../../../scales/scale_continuous';
import { OrdinalDomain, ContinuousDomain } from '../../../utils/domain';
import { GroupId } from '../../../utils/ids';
import { XScaleType } from '../utils/specs';

/** @internal */
export interface BaseDomain {
scaleType: typeof ScaleType.Ordinal | ScaleContinuousType;
export type XDomain = Pick<LogScaleOptions, 'logBase'> & {
type: XScaleType;
nice: boolean;
/* if the scale needs to be a band scale: used when displaying bars */
isBandScale: boolean;
}
/* the minimum interval of the scale if not-ordinal band-scale */
minInterval: number;
/** if x domain is time, we should also specify the timezone */
timeZone?: string;
domain: OrdinalDomain | ContinuousDomain;
desiredTickCount: number;
};

/** @internal */
export type XDomain = BaseDomain &
Pick<LogScaleOptions, 'logBase'> & {
type: 'xDomain';
/* the minimum interval of the scale if not-ordinal band-scale */
minInterval: number;
/** if x domain is time, we should also specify the timezone */
timeZone?: string;
domain: OrdinalDomain | ContinuousDomain;
};

/** @internal */
export type YDomain = BaseDomain &
LogScaleOptions & {
type: 'yDomain';
isBandScale: false;
scaleType: ScaleContinuousType;
groupId: GroupId;
domain: ContinuousDomain;
};
export type YDomain = LogScaleOptions & {
type: ScaleContinuousType;
nice: boolean;
isBandScale: false;
groupId: GroupId;
domain: ContinuousDomain;
desiredTickCount: number;
};
Loading

0 comments on commit 9c2eefc

Please sign in to comment.