Browse Source

hotfix: support empty series

pull/1/head
rozetko 2 years ago
parent
commit
246d47c923
  1. 18
      src/index.ts
  2. 14
      src/models/bar_state.ts
  3. 6
      src/models/data_processor.ts
  4. 5
      src/types.ts

18
src/index.ts

@ -10,7 +10,7 @@ import { setBarScaleY, setBarScaleX } from './models/bar_state';
import { import {
BarSerie, BarOptions, DiscreteConfig, NonDiscreteConfig, BarSerie, BarOptions, DiscreteConfig, NonDiscreteConfig,
BarPodType, SizeType, CallbackEvent, Color, Opacity, BarPodType, SizeType, CallbackEvent, Color, Opacity,
ColorFormatter, OpacityFormatter, BarData, ColorFormatter, OpacityFormatter,
Datapoint, ValueX, ValueY, Datapoint, ValueX, ValueY,
} from './types'; } from './types';
@ -108,9 +108,19 @@ export class ChartwerkBarPod extends ChartwerkPod<BarSerie, BarOptions> {
if(!this.series.isSeriesAvailable) { if(!this.series.isSeriesAvailable) {
return undefined; return undefined;
} }
const mousePoisitionKey = Math.ceil(this.state.xScale.invert(eventX)); const mousePositionKey = this.state.xScale.invert(eventX);
const keys = _.map(this.dataProcessor.dataRows, (dataRow: DataRow) => dataRow.key); const keys = _.map(this.dataProcessor.dataRows, (dataRow: DataRow) => dataRow.key);
const idx = findClosest(keys, mousePoisitionKey); let idx: number;
switch(this.options.barType) {
case BarPodType.DISCRETE:
idx = Math.floor(mousePositionKey);
break;
case BarPodType.NON_DISCRETE:
idx = findClosest(keys, mousePositionKey);
break;
default:
break;
}
return this.dataProcessor.dataRows[idx]; return this.dataProcessor.dataRows[idx];
} }
@ -152,6 +162,6 @@ export {
BarSerie, BarOptions, TimeFormat, AxisFormat, BarSerie, BarOptions, TimeFormat, AxisFormat,
DiscreteConfig, NonDiscreteConfig, DiscreteConfig, NonDiscreteConfig,
BarPodType, SizeType, CallbackEvent, Color, Opacity, BarPodType, SizeType, CallbackEvent, Color, Opacity,
ColorFormatter, OpacityFormatter, BarData, ColorFormatter, OpacityFormatter,
Datapoint, ValueX, ValueY, DataItem, DataRow, Datapoint, ValueX, ValueY, DataItem, DataRow,
}; };

14
src/models/bar_state.ts

@ -13,14 +13,24 @@ export function setBarScaleX(state: PodState<BarSerie, BarOptions>, dataRows: Da
switch(options.barType) { switch(options.barType) {
case BarPodType.DISCRETE: case BarPodType.DISCRETE:
const config: DiscreteConfig = options.dicreteConfig; const config: DiscreteConfig = options.dicreteConfig;
const discreteStep = _.isNumber(config.step) ? config.step : (_.last(dataRows).key - _.first(dataRows).key) / dataRows.length; let discreteStep = 0;
if(_.isNumber(config.step)) {
discreteStep = config.step;
} else {
if(!_.isEmpty(dataRows)) {
discreteStep = (_.last(dataRows).key - _.first(dataRows).key) / dataRows.length;
}
}
state.xValueRange = [state.xValueRange[0], state.xValueRange[1] + discreteStep]; state.xValueRange = [state.xValueRange[0], state.xValueRange[1] + discreteStep];
return; return;
case BarPodType.NON_DISCRETE: case BarPodType.NON_DISCRETE:
if(!_.isEmpty(options.axis.x.range)) { if(!_.isEmpty(options.axis.x.range)) {
return; return;
} }
const nonDiscreteStep = (_.last(dataRows).key - _.first(dataRows).key) / dataRows.length; let nonDiscreteStep = 0;
if(!_.isEmpty(dataRows)) {
nonDiscreteStep = (_.last(dataRows).key - _.first(dataRows).key) / dataRows.length;
}
state.xValueRange = [state.xValueRange[0], state.xValueRange[1] + nonDiscreteStep]; state.xValueRange = [state.xValueRange[0], state.xValueRange[1] + nonDiscreteStep];
return; return;
} }

6
src/models/data_processor.ts

@ -113,7 +113,7 @@ export class DataProcessor {
if(_.isFunction(opacity)) { if(_.isFunction(opacity)) {
return _.map(values, (value, i) => (opacity as Function)({ value, barIndex: i, key, target })); return _.map(values, (value, i) => (opacity as Function)({ value, barIndex: i, key, target }));
} }
throw new Error(`Unknown type of serie opacity: ${target} ${opacity}`); throw new Error(`Unknown type of serie opacity: ${target} ${opacity}`);
} }
getMaxSumm(values: number[]): number { getMaxSumm(values: number[]): number {
@ -128,6 +128,10 @@ export class DataProcessor {
if(this.options.barType === BarPodType.NON_DISCRETE) { if(this.options.barType === BarPodType.NON_DISCRETE) {
return; return;
} }
// TODO: move non-empty datapoints validation to core
if(_.isEmpty(this.visibleSeries)) {
return;
}
const xValuesList = _.map(_.first(this.visibleSeries).datapoints, dp => dp[0]); const xValuesList = _.map(_.first(this.visibleSeries).datapoints, dp => dp[0]);
_.forEach(this.visibleSeries, serie => { _.forEach(this.visibleSeries, serie => {
const serieXList = _.map(serie.datapoints, dp => dp[0]); const serieXList = _.map(serie.datapoints, dp => dp[0]);

5
src/types.ts

@ -4,8 +4,9 @@ import { DataRow } from 'models/data_processor';
export type ValueX = (number | string); export type ValueX = (number | string);
export type ValueY = number; export type ValueY = number;
export type Datapoint = [ValueX, ...ValueY[]]; // [x, y, y, y, ..., y], multiple y values as stacked bars export type Datapoint = [ValueX, ...ValueY[]]; // [x, y, y, y, ..., y], multiple y values as stacked bars
export type ColorFormatter = (data: { value: ValueY, key: ValueX, barIndex: number, target: string }) => string; export type BarData = { value: ValueY, key: ValueX, barIndex: number, target: string };
export type OpacityFormatter = (data: { value: ValueY, key: ValueX, barIndex: number, target: string }) => number; export type ColorFormatter = (data: BarData) => string;
export type OpacityFormatter = (data: BarData) => number;
export type Color = string | string[] | ColorFormatter; export type Color = string | string[] | ColorFormatter;
export type Opacity = number | number[] | OpacityFormatter; export type Opacity = number | number[] | OpacityFormatter;

Loading…
Cancel
Save