Skip to content

Commit

Permalink
fix: render charts without series (#657)
Browse files Browse the repository at this point in the history
This commit fixes the thrown errors when a chart is initialized without a series configuration.
It adds a custom `isInitialized` function for every chart type
  • Loading branch information
markov00 authored Apr 30, 2020
1 parent b7f0cb4 commit 0c0af01
Show file tree
Hide file tree
Showing 19 changed files with 83 additions and 32 deletions.
36 changes: 34 additions & 2 deletions .playground/playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,45 @@
* under the License. */

import React from 'react';
import { example } from '../stories/treemap/6_custom_style';
import { Chart, Axis, Position, Settings, AreaSeries, ScaleType, DataGenerator } from '../src';
import { getRandomNumberGenerator } from '../src/mocks/utils';

const dg = new DataGenerator(500, getRandomNumberGenerator());
const basicData = dg.generateBasicSeries();
export class Playground extends React.Component {
state = {
data: basicData,
};
onBrushEnd = () => {
this.setState({ data: [] });
setTimeout(() => {
this.setState({
data: dg.generateBasicSeries(),
});
}, 100);
};
render() {
return (
<div className="testing">
<div className="chart">{example()}</div>
<div className="chart">
<Chart className="story-chart">
<Settings onBrushEnd={this.onBrushEnd} />
<Axis id="bottom" position={Position.Bottom} title="bottom" showOverlappingTicks={true} />
<Axis id="left" title="left" position={Position.Left} tickFormat={(d) => Number(d).toFixed(2)} />
<Axis id="top" position={Position.Top} title="top" showOverlappingTicks={true} />
<Axis id="right" title="right" position={Position.Right} tickFormat={(d) => Number(d).toFixed(2)} />
{this.state.data.length > 0 && (
<AreaSeries
id="lines"
xScaleType={ScaleType.Linear}
yScaleType={ScaleType.Linear}
xAccessor="x"
yAccessors={['y']}
data={this.state.data}
/>
)}
</Chart>
</div>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import React, { MouseEvent } from 'react';
import { bindActionCreators, Dispatch } from 'redux';
import { connect } from 'react-redux';
import { onChartRendered } from '../../../../state/actions/chart';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { GlobalChartState } from '../../../../state/chart_state';
import { Dimensions } from '../../../../utils/dimensions';
import { geometries } from '../../state/selectors/geometries';
import { BulletViewModel, nullShapeViewModel, ShapeViewModel } from '../../layout/types/viewmodel_types';
import { renderCanvas2d } from './canvas_renderers';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

interface ReactiveChartStateProps {
initialized: boolean;
Expand Down Expand Up @@ -149,7 +149,7 @@ const DEFAULT_PROPS: ReactiveChartStateProps = {
};

const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return DEFAULT_PROPS;
}
return {
Expand Down
4 changes: 4 additions & 0 deletions src/chart_types/goal_chart/state/chart_state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { createOnElementOverCaller } from './selectors/on_element_over_caller';
import { createOnElementOutCaller } from './selectors/on_element_out_caller';
import { LegendItem } from '../../../commons/legend';
import { LegendItemLabel } from '../../../state/selectors/get_legend_items_labels';
import { getSpecOrNull } from './selectors/goal_spec';

const EMPTY_MAP = new Map();
const EMPTY_LEGEND_LIST: LegendItem[] = [];
Expand All @@ -45,6 +46,9 @@ export class GoalState implements InternalChartState {
this.onElementOutCaller = createOnElementOutCaller();
}
chartType = ChartTypes.Goal;
isInitialized(globalState: GlobalChartState) {
return globalState.specsInitialized && getSpecOrNull(globalState) !== null;
}
isBrushAvailable() {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions src/chart_types/partition_chart/renderer/canvas/partition.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ import React, { MouseEvent } from 'react';
import { bindActionCreators, Dispatch } from 'redux';
import { connect } from 'react-redux';
import { onChartRendered } from '../../../../state/actions/chart';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { GlobalChartState } from '../../../../state/chart_state';
import { Dimensions } from '../../../../utils/dimensions';
import { partitionGeometries } from '../../state/selectors/geometries';
import { nullShapeViewModel, QuadViewModel, ShapeViewModel } from '../../layout/types/viewmodel_types';
import { renderPartitionCanvas2d } from './canvas_renderers';
import { INPUT_KEY } from '../../layout/utils/group_by_rollup';
import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

interface ReactiveChartStateProps {
initialized: boolean;
Expand Down Expand Up @@ -166,7 +166,7 @@ const DEFAULT_PROPS: ReactiveChartStateProps = {
};

const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return DEFAULT_PROPS;
}
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@

import { connect } from 'react-redux';
import { GlobalChartState } from '../../../../state/chart_state';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { partitionGeometries } from '../../state/selectors/geometries';
import { getPickedShapes } from '../../state/selectors/picked_shapes';
import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions';
import { HighlighterComponent, HighlighterProps, DEFAULT_PROPS } from './highlighter';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

const hoverMapStateToProps = (state: GlobalChartState): HighlighterProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return DEFAULT_PROPS;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@

import { connect } from 'react-redux';
import { GlobalChartState } from '../../../../state/chart_state';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { partitionGeometries } from '../../state/selectors/geometries';
import { getHighlightedSectorsSelector } from '../../state/selectors/get_highlighted_shapes';
import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions';
import { HighlighterComponent, HighlighterProps, DEFAULT_PROPS } from './highlighter';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

const legendMapStateToProps = (state: GlobalChartState): HighlighterProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return DEFAULT_PROPS;
}

Expand Down
4 changes: 4 additions & 0 deletions src/chart_types/partition_chart/state/chart_state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { computeLegendSelector } from './selectors/compute_legend';
import { getLegendItemsLabels } from './selectors/get_legend_items_labels';
import { HighlighterFromHover } from '../renderer/dom/highlighter_hover';
import { HighlighterFromLegend } from '../renderer/dom/highlighter_legend';
import { getPieSpecOrNull } from './selectors/pie_spec';

const EMPTY_MAP = new Map();

Expand All @@ -45,6 +46,9 @@ export class PartitionState implements InternalChartState {
this.onElementOutCaller = createOnElementOutCaller();
}
chartType = ChartTypes.Partition;
isInitialized(globalState: GlobalChartState) {
return globalState.specsInitialized && getPieSpecOrNull(globalState) !== null;
}
isBrushAvailable() {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { getChartContainerDimensionsSelector } from '../../../../state/selectors
import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation';
import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme';
import { getSettingsSpecSelector } from '../../../../state/selectors/get_settings_specs';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { Dimensions } from '../../../../utils/dimensions';
import { AnnotationId, AxisId } from '../../../../utils/ids';
import { LIGHT_THEME } from '../../../../utils/themes/light_theme';
Expand All @@ -48,6 +47,7 @@ import { isChartEmptySelector } from '../../state/selectors/is_chart_empty';
import { deepEqual } from '../../../../utils/fast_deep_equal';
import { Rotation } from '../../../../utils/commons';
import { IndexedGeometryMap } from '../../utils/indexed_geometry_map';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

/** @internal */
export interface ReactiveChartStateProps {
Expand Down Expand Up @@ -219,7 +219,7 @@ const DEFAULT_PROPS: ReactiveChartStateProps = {
};

const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return DEFAULT_PROPS;
}

Expand Down
4 changes: 2 additions & 2 deletions src/chart_types/xy_chart/renderer/dom/annotation_tooltips.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import { AnnotationDimensions, AnnotationTooltipState, AnnotationTooltipFormatte
import { connect } from 'react-redux';
import { Dimensions } from '../../../../utils/dimensions';
import { GlobalChartState, BackwardRef } from '../../../../state/chart_state';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { computeAnnotationDimensionsSelector } from '../../state/selectors/compute_annotations';
import { getAnnotationSpecsSelector } from '../../state/selectors/get_specs';
import { getAnnotationTooltipStateSelector } from '../../state/selectors/get_annotation_tooltip_state';
Expand All @@ -34,6 +33,7 @@ import { createPortal } from 'react-dom';
import { getFinalAnnotationTooltipPosition } from '../../annotations/tooltip';
import { getSpecsById } from '../../state/utils';
import { Position } from '../../../../utils/commons';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

interface AnnotationTooltipStateProps {
isChartEmpty: boolean;
Expand Down Expand Up @@ -266,7 +266,7 @@ function LineAnnotationTooltipRender(props: LineAnnotationTooltipProps, ref: Rea
const LineAnnotationTooltip = React.forwardRef(LineAnnotationTooltipRender);

const mapStateToProps = (state: GlobalChartState): AnnotationTooltipStateProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return {
isChartEmpty: true,
chartDimensions: { top: 0, left: 0, width: 0, height: 0 },
Expand Down
4 changes: 2 additions & 2 deletions src/chart_types/xy_chart/renderer/dom/brush.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import React, { RefObject } from 'react';
import { connect } from 'react-redux';
import { Dimensions } from '../../../../utils/dimensions';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { GlobalChartState } from '../../../../state/chart_state';
import { getBrushAreaSelector } from '../../state/selectors/get_brush_area';
import { isBrushAvailableSelector } from '../../state/selectors/is_brush_available';
Expand All @@ -28,6 +27,7 @@ import { isBrushingSelector } from '../../state/selectors/is_brushing';
import { renderRect } from '../canvas/primitives/rect';
import { clearCanvas, withContext, withClip } from '../../../../renderers/canvas';
import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

interface Props {
initialized: boolean;
Expand Down Expand Up @@ -133,7 +133,7 @@ class BrushToolComponent extends React.Component<Props> {
}

const mapStateToProps = (state: GlobalChartState): Props => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return {
initialized: false,
isBrushing: false,
Expand Down
4 changes: 2 additions & 2 deletions src/chart_types/xy_chart/renderer/dom/crosshair.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import { Dimensions } from '../../../../utils/dimensions';
import { Theme } from '../../../../utils/themes/theme';
import { Rotation } from '../../../../utils/commons';
import { GlobalChartState } from '../../../../state/chart_state';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation';
import { getCursorBandPositionSelector } from '../../state/selectors/get_cursor_band';
import { getCursorLinePositionSelector } from '../../state/selectors/get_cursor_line';
import { getTooltipTypeSelector } from '../../state/selectors/get_tooltip_type';
import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme';
import { LIGHT_THEME } from '../../../../utils/themes/light_theme';
import { TooltipType } from '../../../../specs';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

interface CrosshairProps {
theme: Theme;
Expand Down Expand Up @@ -114,7 +114,7 @@ class CrosshairComponent extends React.Component<CrosshairProps> {
}

const mapStateToProps = (state: GlobalChartState): CrosshairProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return {
theme: LIGHT_THEME,
chartRotation: 0,
Expand Down
4 changes: 2 additions & 2 deletions src/chart_types/xy_chart/renderer/dom/highlighter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import React from 'react';
import { connect } from 'react-redux';
import { isPointGeometry, IndexedGeometry } from '../../../../utils/geometry';
import { GlobalChartState } from '../../../../state/chart_state';
import { isInitialized } from '../../../../state/selectors/is_initialized';
import { computeChartTransformSelector } from '../../state/selectors/compute_chart_transform';
import { getHighlightedGeomsSelector } from '../../state/selectors/get_tooltip_values_highlighted_geoms';
import { Dimensions } from '../../../../utils/dimensions';
Expand All @@ -29,6 +28,7 @@ import { Transform } from '../../state/utils';
import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation';
import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions';
import { DEFAULT_HIGHLIGHT_PADDING } from '../../rendering/rendering';
import { getInternalIsInitializedSelector } from '../../../../state/selectors/get_internal_is_intialized';

interface HighlighterProps {
initialized: boolean;
Expand Down Expand Up @@ -92,7 +92,7 @@ class HighlighterComponent extends React.Component<HighlighterProps> {
}

const mapStateToProps = (state: GlobalChartState): HighlighterProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return {
initialized: false,
chartId: state.chartId,
Expand Down
4 changes: 4 additions & 0 deletions src/chart_types/xy_chart/state/chart_state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { createOnBrushEndCaller } from './selectors/on_brush_end_caller';
import { createOnPointerMoveCaller } from './selectors/on_pointer_move_caller';
import { getLegendItemsLabelsSelector } from './selectors/get_legend_items_labels';
import { LegendItemExtraValues } from '../../../commons/legend';
import { getSeriesSpecsSelector } from './selectors/get_specs';

/** @internal */
export class XYAxisChartState implements InternalChartState {
Expand All @@ -63,6 +64,9 @@ export class XYAxisChartState implements InternalChartState {
this.chartType = ChartTypes.XYAxis;
this.legendId = htmlIdGenerator()('legend');
}
isInitialized(globalState: GlobalChartState) {
return globalState.specsInitialized && getSeriesSpecsSelector(globalState).length > 0;
}

isBrushAvailable(globalState: GlobalChartState) {
return isBrushAvailableSelector(globalState);
Expand Down
4 changes: 2 additions & 2 deletions src/components/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ import { Position } from '../utils/commons';
import { ChartSize, getChartSize } from '../utils/chart_size';
import { ChartStatus } from './chart_status';
import { chartStoreReducer, GlobalChartState } from '../state/chart_state';
import { isInitialized } from '../state/selectors/is_initialized';
import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs';
import { onExternalPointerEvent } from '../state/actions/events';
import { PointerEvent } from '../specs';
import { getInternalIsInitializedSelector } from '../state/selectors/get_internal_is_intialized';

interface ChartProps {
/** The type of rendered
Expand Down Expand Up @@ -87,7 +87,7 @@ export class Chart extends React.Component<ChartProps, ChartState> {

this.unsubscribeToStore = this.chartStore.subscribe(() => {
const state = this.chartStore.getState();
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/chart_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ import { getInternalChartRendererSelector } from '../state/selectors/get_chart_t
import { getInternalPointerCursor } from '../state/selectors/get_internal_cursor_pointer';
import { getInternalIsBrushingAvailableSelector } from '../state/selectors/get_internal_is_brushing_available';
import { isInternalChartEmptySelector } from '../state/selectors/is_chart_empty';
import { isInitialized } from '../state/selectors/is_initialized';
import { getSettingsSpecSelector } from '../state/selectors/get_settings_specs';
import { SettingsSpec } from '../specs';
import { getInternalIsBrushingSelector } from '../state/selectors/get_internal_is_brushing';
import { getInternalIsInitializedSelector } from '../state/selectors/get_internal_is_intialized';

interface ChartContainerComponentStateProps {
initialized: boolean;
Expand Down Expand Up @@ -173,7 +173,7 @@ const mapDispatchToProps = (dispatch: Dispatch): ChartContainerComponentDispatch
dispatch,
);
const mapStateToProps = (state: GlobalChartState): ChartContainerComponentStateProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return {
initialized: false,
isChartEmpty: true,
Expand Down
3 changes: 2 additions & 1 deletion src/components/legend/legend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { clearTemporaryColors, setTemporaryColor, setPersistedColor } from '../.
import { LegendItemListener, BasicListener, LegendColorPicker } from '../../specs';
import { getLegendStyle, getLegendListStyle } from './style_utils';
import { renderLegendItem } from './legend_item';
import { getInternalIsInitializedSelector } from '../../state/selectors/get_internal_is_intialized';

interface LegendStateProps {
debug: boolean;
Expand Down Expand Up @@ -146,7 +147,7 @@ const EMPTY_DEFAULT_STATE = {
showExtra: false,
};
const mapStateToProps = (state: GlobalChartState): LegendStateProps => {
if (!state.specsInitialized) {
if (!getInternalIsInitializedSelector(state)) {
return EMPTY_DEFAULT_STATE;
}
const {
Expand Down
4 changes: 2 additions & 2 deletions src/components/tooltip/tooltip_portal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ import { getFinalTooltipPosition, TooltipAnchorPosition } from './utils';
import { TooltipInfo } from './types';
import { TooltipValueFormatter } from '../../specs';
import { GlobalChartState, BackwardRef } from '../../state/chart_state';
import { isInitialized } from '../../state/selectors/is_initialized';
import { getInternalIsTooltipVisibleSelector } from '../../state/selectors/get_internal_is_tooltip_visible';
import { getTooltipHeaderFormatterSelector } from '../../state/selectors/get_tooltip_header_formatter';
import { getInternalTooltipInfoSelector } from '../../state/selectors/get_internal_tooltip_info';
import { getInternalTooltipAnchorPositionSelector } from '../../state/selectors/get_internal_tooltip_anchor_position';
import { Tooltip } from './tooltip';
import { getInternalIsInitializedSelector } from '../../state/selectors/get_internal_is_intialized';

interface TooltipPortalStateProps {
isVisible: boolean;
Expand Down Expand Up @@ -128,7 +128,7 @@ const HIDDEN_TOOLTIP_PROPS = {
};

const mapStateToProps = (state: GlobalChartState): TooltipPortalStateProps => {
if (!isInitialized(state)) {
if (!getInternalIsInitializedSelector(state)) {
return HIDDEN_TOOLTIP_PROPS;
}
return {
Expand Down
Loading

0 comments on commit 0c0af01

Please sign in to comment.