Skip to content

Commit

Permalink
Merge branch 'master' into 2021_04_07-add_debug_state_partition
Browse files Browse the repository at this point in the history
  • Loading branch information
markov00 committed Apr 15, 2021
2 parents 211e439 + c1b59f2 commit b29d541
Show file tree
Hide file tree
Showing 22 changed files with 460 additions and 25 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# [28.1.0](https://github.com/elastic/elastic-charts/compare/v28.0.1...v28.1.0) (2021-04-13)


### Bug Fixes

* **legend:** sizing for short labels with scrollbar ([#1115](https://github.com/elastic/elastic-charts/issues/1115)) ([6e1f223](https://github.com/elastic/elastic-charts/commit/6e1f223d5126c2707101d269ebaa5dc117ac61c4))
* **xy:** negative bar highlight and click ([#1109](https://github.com/elastic/elastic-charts/issues/1109)) ([ec17cb2](https://github.com/elastic/elastic-charts/commit/ec17cb2eb2f13e0be4370a2dc89d3872f9b6de5a)), closes [#1100](https://github.com/elastic/elastic-charts/issues/1100)


### Features

* **a11y:** improve chart figure ([#1104](https://github.com/elastic/elastic-charts/issues/1104)) ([815cf39](https://github.com/elastic/elastic-charts/commit/815cf39873e3e1f0a526dd88bb06c2b87f22f9e8))
* **partition:** order slices and sectors ([#1112](https://github.com/elastic/elastic-charts/issues/1112)) ([74df29b](https://github.com/elastic/elastic-charts/commit/74df29b5554eaa5b88c670c71321ce676683da6f))
* **partitions:** small multipies events pass on smAccessorValue ([#1106](https://github.com/elastic/elastic-charts/issues/1106)) ([a3234fe](https://github.com/elastic/elastic-charts/commit/a3234feee9e579cf7bdb21d487f80c8200a0fa73))
* **xy:** optionally rounds the domain to nice values ([#1087](https://github.com/elastic/elastic-charts/issues/1087)) ([f644cc4](https://github.com/elastic/elastic-charts/commit/f644cc4653bf4bea3180057b981f80bdcabee00f))
* **xy:** specify pixel and ratio width for bars ([#1114](https://github.com/elastic/elastic-charts/issues/1114)) ([58de413](https://github.com/elastic/elastic-charts/commit/58de413564a5f0b9a8bef9f5cb2119cdde18794f))
* mosaic ([#1113](https://github.com/elastic/elastic-charts/issues/1113)) ([64bdd88](https://github.com/elastic/elastic-charts/commit/64bdd88836210a4c4c997dc207859c3fbd773d80))

## [28.0.1](https://github.com/elastic/elastic-charts/compare/v28.0.0...v28.0.1) (2021-04-06)


Expand Down
4 changes: 3 additions & 1 deletion api/charts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ export const DEFAULT_TOOLTIP_SNAP = true;
export const DEFAULT_TOOLTIP_TYPE: "vertical";

// @public (undocumented)
export type DefaultSettingsProps = 'id' | 'chartType' | 'specType' | 'rendering' | 'rotation' | 'resizeDebounce' | 'animateData' | 'debug' | 'tooltip' | 'theme' | 'hideDuplicateAxes' | 'brushAxis' | 'minBrushDelta' | 'externalPointerEvents' | 'showLegend' | 'showLegendExtra' | 'legendPosition' | 'legendMaxDepth';
export type DefaultSettingsProps = 'id' | 'chartType' | 'specType' | 'rendering' | 'rotation' | 'resizeDebounce' | 'animateData' | 'debug' | 'tooltip' | 'theme' | 'hideDuplicateAxes' | 'brushAxis' | 'minBrushDelta' | 'externalPointerEvents' | 'showLegend' | 'showLegendExtra' | 'legendPosition' | 'legendMaxDepth' | 'description' | 'useDefaultSummary';

// @public (undocumented)
export const DEPTH_KEY = "depth";
Expand Down Expand Up @@ -1743,6 +1743,7 @@ export interface SettingsSpec extends Spec, LegendSpec {
debug: boolean;
// @alpha
debugState?: boolean;
description?: string;
// @alpha
externalPointerEvents: ExternalPointerEventsSettings;
hideDuplicateAxes: boolean;
Expand Down Expand Up @@ -1773,6 +1774,7 @@ export interface SettingsSpec extends Spec, LegendSpec {
roundHistogramBrushValues?: boolean;
theme?: PartialTheme | PartialTheme[];
tooltip: TooltipSettings;
useDefaultSummary: boolean;
// (undocumented)
xDomain?: CustomXDomain;
}
Expand Down
10 changes: 10 additions & 0 deletions integration/page_objects/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,16 @@ class CommonPage {
});
return accessibilitySnapshot;
}

/**
* Get HTML for element to test aria labels etc
*/
// eslint-disable-next-line class-methods-use-this
async getElementHTML(url: string) {
await this.loadElementFromURL(url);
// https://github.com/puppeteer/puppeteer/issues/406#issuecomment-323555639
return await page.evaluate(() => new XMLSerializer().serializeToString(document));
}
}

export const common = new CommonPage();
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@elastic/charts",
"description": "Elastic-Charts data visualization library",
"version": "28.0.1",
"version": "28.1.0",
"author": "Marco Vettorello <marco.vettorello@elastic.co>",
"license": "Apache-2.0",
"main": "dist/index.js",
Expand Down
34 changes: 28 additions & 6 deletions src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { LegendItem } from '../../../../common/legend';
import { onChartRendered } from '../../../../state/actions/chart';
import { GlobalChartState } from '../../../../state/chart_state';
import { getChartContainerDimensionsSelector } from '../../../../state/selectors/get_chart_container_dimensions';
import { getChartIdSelector } from '../../../../state/selectors/get_chart_id';
import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation';
import { getChartThemeSelector } from '../../../../state/selectors/get_chart_theme';
import { getInternalIsInitializedSelector, InitStatus } from '../../../../state/selectors/get_internal_is_intialized';
Expand Down Expand Up @@ -78,6 +79,9 @@ export interface ReactiveChartStateProps {
annotationSpecs: AnnotationSpec[];
panelGeoms: PanelGeoms;
seriesTypes: Set<SeriesType>;
description?: string;
useDefaultSummary: boolean;
chartId: string;
}

interface ReactiveChartDispatchProps {
Expand Down Expand Up @@ -155,6 +159,9 @@ class XYChartComponent extends React.Component<XYChartProps> {
isChartEmpty,
chartContainerDimensions: { width, height },
seriesTypes,
description,
useDefaultSummary,
chartId,
} = this.props;

if (!initialized || isChartEmpty) {
Expand All @@ -164,7 +171,7 @@ class XYChartComponent extends React.Component<XYChartProps> {

const chartSeriesTypes =
seriesTypes.size > 1 ? `Mixed chart: ${[...seriesTypes].join(' and ')} chart` : `${[...seriesTypes]} chart`;

const chartIdDescription = `${chartId}--description`;
return (
<figure>
<canvas
Expand All @@ -178,11 +185,19 @@ class XYChartComponent extends React.Component<XYChartProps> {
}}
// eslint-disable-next-line jsx-a11y/no-interactive-element-to-noninteractive-role
role="presentation"
{...(description ? { 'aria-describedby': chartIdDescription } : {})}
>
<dl className="echScreen-reader">
<dt>Chart type</dt>
<dd>{chartSeriesTypes}</dd>
</dl>
{(description || useDefaultSummary) && (
<div className="echScreenReaderOnly">
{description && <p id={chartIdDescription}>{description}</p>}
{useDefaultSummary && (
<dl>
<dt>Chart type</dt>
<dd>{chartSeriesTypes}</dd>
</dl>
)}
</div>
)}
</canvas>
</figure>
);
Expand Down Expand Up @@ -237,6 +252,9 @@ const DEFAULT_PROPS: ReactiveChartStateProps = {
annotationSpecs: [],
panelGeoms: [],
seriesTypes: new Set(),
description: undefined,
useDefaultSummary: true,
chartId: '',
};

const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => {
Expand All @@ -245,11 +263,12 @@ const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => {
}

const { geometries, geometriesIndex } = computeSeriesGeometriesSelector(state);
const { debug, description, useDefaultSummary } = getSettingsSpecSelector(state);

return {
initialized: true,
isChartEmpty: isChartEmptySelector(state),
debug: getSettingsSpecSelector(state).debug,
debug,
geometries,
geometriesIndex,
theme: getChartThemeSelector(state),
Expand All @@ -266,6 +285,9 @@ const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => {
annotationSpecs: getAnnotationSpecsSelector(state),
panelGeoms: computePanelsSelectors(state),
seriesTypes: getSeriesTypes(state),
description,
useDefaultSummary,
chartId: getChartIdSelector(state),
};
};

Expand Down
76 changes: 76 additions & 0 deletions src/chart_types/xy_chart/state/chart_state.a11y.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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 { Store } from 'redux';

import { MockGlobalSpec, MockSeriesSpec } from '../../../mocks/specs';
import { MockStore } from '../../../mocks/store/store';
import { GlobalChartState } from '../../../state/chart_state';
import { getSettingsSpecSelector } from '../../../state/selectors/get_settings_specs';

describe('custom description for screen readers', () => {
let store: Store<GlobalChartState>;
beforeEach(() => {
store = MockStore.default();
MockStore.addSpecs(
[
MockSeriesSpec.bar({
data: [
{ x: 1, y: 10 },
{ x: 2, y: 5 },
],
}),
MockGlobalSpec.settings(),
],
store,
);
});
it('should test defaults', () => {
const state = store.getState();
const { description, useDefaultSummary } = getSettingsSpecSelector(state);
expect(description).toBeUndefined();
expect(useDefaultSummary).toBeTrue();
});
it('should allow user to set a custom description for chart', () => {
MockStore.addSpecs(
[
MockGlobalSpec.settings({
description: 'This is sample Kibana data',
}),
],
store,
);
const state = store.getState();
const { description } = getSettingsSpecSelector(state);
expect(description).toBe('This is sample Kibana data');
});
it('should be able to disable generated descriptions', () => {
MockStore.addSpecs(
[
MockGlobalSpec.settings({
useDefaultSummary: false,
}),
],
store,
);
const state = store.getState();
const { useDefaultSummary } = getSettingsSpecSelector(state);
expect(useDefaultSummary).toBe(false);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* 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 { MockGlobalSpec, MockSeriesSpec } from '../../../../mocks/specs/specs';
import { MockStore } from '../../../../mocks/store/store';
import { DEFAULT_GLOBAL_ID } from '../../utils/specs';
import { computeSeriesGeometriesSelector } from './compute_series_geometries';
import { getScaleConfigsFromSpecsSelector } from './get_api_scale_configs';

describe('GroupIds and useDefaultGroupId', () => {
it('use the specified useDefaultGroupId to compute scale configs', () => {
const store = MockStore.default();
MockStore.addSpecs(
[
MockSeriesSpec.bar({
groupId: 'other',
useDefaultGroupDomain: 'a different one',
}),
],
store,
);
const scaleConfigs = getScaleConfigsFromSpecsSelector(store.getState());
expect(scaleConfigs.y['a different one']).toBeDefined();
});

it('have 2 different y domains with 2 groups', () => {
const store = MockStore.default();
MockStore.addSpecs(
[
MockSeriesSpec.bar({ id: 'one' }),
MockSeriesSpec.bar({
id: 'two',
groupId: 'other',
useDefaultGroupDomain: 'a different one',
}),
],
store,
);
const scaleConfigs = getScaleConfigsFromSpecsSelector(store.getState());
expect(Object.keys(scaleConfigs.y)).toHaveLength(2);
expect(scaleConfigs.y['a different one']).toBeDefined();
expect(scaleConfigs.y[DEFAULT_GLOBAL_ID]).toBeDefined();
});

it('have 2 different y domains with 3 groups', () => {
const store = MockStore.default({ width: 120, height: 100, left: 0, top: 0 });
MockStore.addSpecs(
[
MockGlobalSpec.settingsNoMargins(),
MockSeriesSpec.bar({ id: 'one', data: [{ x: 1, y: 10 }] }),
MockSeriesSpec.bar({
id: 'two',
groupId: 'other',
useDefaultGroupDomain: 'a different one',
data: [{ x: 1, y: 10 }],
}),
MockSeriesSpec.bar({
id: 'three',
groupId: 'another again',
useDefaultGroupDomain: 'a different one',
data: [{ x: 1, y: 10 }],
}),
],
store,
);
const scaleConfigs = getScaleConfigsFromSpecsSelector(store.getState());
expect(Object.keys(scaleConfigs.y)).toHaveLength(2);
expect(scaleConfigs.y['a different one']).toBeDefined();
expect(scaleConfigs.y[DEFAULT_GLOBAL_ID]).toBeDefined();

const geoms = computeSeriesGeometriesSelector(store.getState());
const { bars } = geoms.geometries;
expect(bars).toHaveLength(3);
expect(bars[0].value[0].width).toBe(40);
expect(bars[1].value[0].width).toBe(40);
expect(bars[2].value[0].width).toBe(40);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { isHorizontalAxis, isVerticalAxis } from '../../utils/axis_type_utils';
import { groupBy } from '../../utils/group_data_series';
import { AxisSpec, BasicSeriesSpec, CustomXDomain, XScaleType, YDomainRange } from '../../utils/specs';
import { isHorizontalRotation } from '../utils/common';
import { getSpecDomainGroupId } from '../utils/spec';
import { getAxisSpecsSelector, getSeriesSpecsSelector } from './get_specs';
import { mergeYCustomDomainsByGroupId } from './merge_y_custom_domains';

Expand Down Expand Up @@ -83,14 +84,15 @@ export function getScaleConfigsFromSpecs(
};

// y axes
const scaleConfigsByGroupId = groupBy(seriesSpecs, ['groupId'], true).reduce<
const scaleConfigsByGroupId = groupBy(seriesSpecs, getSpecDomainGroupId, true).reduce<
Record<GroupId, { nice: boolean; type: ScaleContinuousType }>
>((acc, series) => {
const yScaleTypes = series.map(({ yScaleType, yNice }) => ({
nice: getYNiceFromSpec(yNice),
type: getYScaleTypeFromSpec(yScaleType),
}));
acc[series[0].groupId] = coerceYScaleTypes(yScaleTypes);
const groupId = getSpecDomainGroupId(series[0]);
acc[groupId] = coerceYScaleTypes(yScaleTypes);
return acc;
}, {});

Expand Down
Loading

0 comments on commit b29d541

Please sign in to comment.