Skip to content

Commit

Permalink
[Lens] Synchronize cursor position for X-axis across all Lens visuali…
Browse files Browse the repository at this point in the history
…zations in a dashboard

Closes: elastic#77530
  • Loading branch information
alexwizp committed Jul 29, 2021
1 parent 46def30 commit 3d45332
Show file tree
Hide file tree
Showing 24 changed files with 177 additions and 74 deletions.
2 changes: 2 additions & 0 deletions src/plugins/charts/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export { ChartsPluginSetup, ChartsPluginStart } from './plugin';
export * from './static';
export * from './services/palettes/types';
export { lightenColor } from './services/palettes/lighten_color';
export { useActiveCursor } from './services/active_cursor';

export {
PaletteOutput,
CustomPaletteArguments,
Expand Down
9 changes: 8 additions & 1 deletion src/plugins/charts/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { palette, systemPalette } from '../common';

import { ThemeService, LegacyColorsService } from './services';
import { PaletteService } from './services/palettes/service';
import { ActiveCursor } from './services/active_cursor';

export type Theme = Omit<ThemeService, 'init'>;
export type Color = Omit<LegacyColorsService, 'init'>;
Expand All @@ -28,13 +29,16 @@ export interface ChartsPluginSetup {
}

/** @public */
export type ChartsPluginStart = ChartsPluginSetup;
export type ChartsPluginStart = ChartsPluginSetup & {
activeCursor: ActiveCursor;
};

/** @public */
export class ChartsPlugin implements Plugin<ChartsPluginSetup, ChartsPluginStart> {
private readonly themeService = new ThemeService();
private readonly legacyColorsService = new LegacyColorsService();
private readonly paletteService = new PaletteService();
private readonly activeCursor = new ActiveCursor();

private palettes: undefined | ReturnType<PaletteService['setup']>;

Expand All @@ -45,6 +49,8 @@ export class ChartsPlugin implements Plugin<ChartsPluginSetup, ChartsPluginStart
this.legacyColorsService.init(core.uiSettings);
this.palettes = this.paletteService.setup(this.legacyColorsService);

this.activeCursor.setup();

return {
legacyColors: this.legacyColorsService,
theme: this.themeService,
Expand All @@ -57,6 +63,7 @@ export class ChartsPlugin implements Plugin<ChartsPluginSetup, ChartsPluginStart
legacyColors: this.legacyColorsService,
theme: this.themeService,
palettes: this.palettes!,
activeCursor: this.activeCursor,
};
}
}
18 changes: 18 additions & 0 deletions src/plugins/charts/public/services/active_cursor/active_cursor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { Subject } from 'rxjs';
import type { PointerEvent } from '@elastic/charts';

export class ActiveCursor {
public activeCursor$?: Subject<PointerEvent>;

setup() {
this.activeCursor$ = new Subject<PointerEvent>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,5 @@
* Side Public License, v 1.
*/

import { Subject } from 'rxjs';
import { PointerEvent } from '@elastic/charts';

export const activeCursor$ = new Subject<PointerEvent>();
export { ActiveCursor } from './active_cursor';
export { useActiveCursor } from './use_active_cursor';
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { useCallback, useEffect, RefObject } from 'react';

import type { Chart } from '@elastic/charts';
import type { ActiveCursor } from './active_cursor';

export const useActiveCursor = (activeCursor: ActiveCursor, chartRef: RefObject<Chart>) => {
const handleCursorUpdate = useCallback(
(cursor) => {
activeCursor.activeCursor$?.next(cursor);
},
[activeCursor.activeCursor$]
);

useEffect(() => {
const cursorSubscription = activeCursor.activeCursor$?.subscribe((cursor) => {
chartRef?.current?.dispatchExternalPointerEvent(cursor);
});

return () => {
cursorSubscription?.unsubscribe();
};
}, [activeCursor.activeCursor$, chartRef]);

return handleCursorUpdate;
};
1 change: 1 addition & 0 deletions src/plugins/charts/public/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@

export { LegacyColorsService } from './legacy_colors';
export { ThemeService } from './theme';
export { ActiveCursor, useActiveCursor } from './active_cursor';
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import { SeriesConfigQueryBarWithIgnoreGlobalFilter } from '../../series_config_query_bar_with_ignore_global_filter';
import { PalettePicker } from '../../palette_picker';
import { getChartsSetup } from '../../../../services';
import { getCharts } from '../../../../services';
import { isPercentDisabled } from '../../lib/stacked';
import { STACKED_OPTIONS } from '../../../visualizations/constants/chart';

Expand Down Expand Up @@ -120,7 +120,7 @@ export const TimeseriesConfig = injectI18n(function (props) {
const selectedChartTypeOption = chartTypeOptions.find((option) => {
return model.chart_type === option.value;
});
const { palettes } = getChartsSetup();
const { palettes } = getCharts();
const [palettesRegistry, setPalettesRegistry] = useState(null);

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Side Public License, v 1.
*/

import React, { useEffect, useRef, useCallback } from 'react';
import React, { useRef, useCallback } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { labelDateFormatter } from '../../../components/lib/label_date_formatter';
Expand All @@ -23,8 +23,7 @@ import {
} from '@elastic/charts';
import { EuiIcon } from '@elastic/eui';
import { getTimezone } from '../../../lib/get_timezone';
import { activeCursor$ } from '../../lib/active_cursor';
import { getUISettings, getChartsSetup } from '../../../../services';
import { getUISettings, getCharts } from '../../../../services';
import { GRID_LINE_CONFIG, ICON_TYPES_MAP, STACKED_OPTIONS } from '../../constants';
import { AreaSeriesDecorator } from './decorators/area_decorator';
import { BarSeriesDecorator } from './decorators/bar_decorator';
Expand All @@ -33,7 +32,7 @@ import { getBaseTheme, getChartClasses } from './utils/theme';
import { TOOLTIP_MODES } from '../../../../../common/enums';
import { getValueOrEmpty } from '../../../../../common/empty_label';
import { getSplitByTermsColor } from '../../../lib/get_split_by_terms_color';
import { renderEndzoneTooltip } from '../../../../../../charts/public';
import { renderEndzoneTooltip, useActiveCursor } from '../../../../../../charts/public';
import { getAxisLabelString } from '../../../components/lib/get_axis_label_string';
import { calculateDomainForSeries } from './utils/series_domain_calculation';

Expand All @@ -48,10 +47,6 @@ const generateAnnotationData = (values, formatter) =>

const decorateFormatter = (formatter) => ({ value }) => formatter(value);

const handleCursorUpdate = (cursor) => {
activeCursor$.next(cursor);
};

export const TimeSeries = ({
backgroundColor,
showGrid,
Expand All @@ -69,22 +64,13 @@ export const TimeSeries = ({
interval,
isLastBucketDropped,
}) => {
const chartRef = useRef();
// const [palettesRegistry, setPalettesRegistry] = useState(null);

useEffect(() => {
const updateCursor = (cursor) => {
if (chartRef.current) {
chartRef.current.dispatchExternalPointerEvent(cursor);
}
};

const subscription = activeCursor$.subscribe(updateCursor);
// If the color isn't configured by the user, use the color mapping service
// to assign a color from the Kibana palette. Colors will be shared across the
// session, including dashboards.
const { theme: themeService, activeCursor: activeCursorService } = getCharts();

return () => {
subscription.unsubscribe();
};
}, []);
const chartRef = useRef();
const handleCursorUpdate = useActiveCursor(activeCursorService, chartRef);

let tooltipFormatter = decorateFormatter(xAxisFormatter);
if (!isLastBucketDropped) {
Expand All @@ -104,11 +90,6 @@ export const TimeSeries = ({
// apply legend style change if bgColor is configured
const classes = classNames(getChartClasses(backgroundColor));

// If the color isn't configured by the user, use the color mapping service
// to assign a color from the Kibana palette. Colors will be shared across the
// session, including dashboards.
const { theme: themeService } = getChartsSetup();

const baseTheme = getBaseTheme(themeService.useChartsBaseTheme(), backgroundColor);

const onBrushEndListener = ({ x }) => {
Expand Down
12 changes: 6 additions & 6 deletions src/plugins/vis_type_timeseries/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ import {
setFieldFormats,
setCoreStart,
setDataStart,
setChartsSetup,
setCharts,
} from './services';
import { DataPublicPluginStart } from '../../data/public';
import { ChartsPluginSetup } from '../../charts/public';
import { ChartsPluginStart } from '../../charts/public';
import { getTimeseriesVisRenderer } from './timeseries_vis_renderer';

/** @internal */
export interface MetricsPluginSetupDependencies {
expressions: ReturnType<ExpressionsPublicPlugin['setup']>;
visualizations: VisualizationsSetup;
charts: ChartsPluginSetup;
visualize: VisualizePluginSetup;
}

/** @internal */
export interface MetricsPluginStartDependencies {
data: DataPublicPluginStart;
charts: ChartsPluginStart;
}

/** @internal */
Expand All @@ -49,7 +49,7 @@ export class MetricsPlugin implements Plugin<void, void> {

public setup(
core: CoreSetup,
{ expressions, visualizations, charts, visualize }: MetricsPluginSetupDependencies
{ expressions, visualizations, visualize }: MetricsPluginSetupDependencies
) {
visualize.visEditorsRegistry.register(TSVB_EDITOR_NAME, EditorController);
expressions.registerFunction(createMetricsFn);
Expand All @@ -59,11 +59,11 @@ export class MetricsPlugin implements Plugin<void, void> {
})
);
setUISettings(core.uiSettings);
setChartsSetup(charts);
visualizations.createBaseVisualization(metricsVisDefinition);
}

public start(core: CoreStart, { data }: MetricsPluginStartDependencies) {
public start(core: CoreStart, { data, charts }: MetricsPluginStartDependencies) {
setCharts(charts);
setI18n(core.i18n);
setFieldFormats(data.fieldFormats);
setDataStart(data);
Expand Down
6 changes: 2 additions & 4 deletions src/plugins/vis_type_timeseries/public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import { I18nStart, IUiSettingsClient, CoreStart } from 'src/core/public';
import { createGetterSetter } from '../../kibana_utils/public';
import { ChartsPluginSetup } from '../../charts/public';
import { ChartsPluginStart } from '../../charts/public';
import { DataPublicPluginStart } from '../../data/public';

export const [getUISettings, setUISettings] = createGetterSetter<IUiSettingsClient>('UISettings');
Expand All @@ -23,6 +23,4 @@ export const [getDataStart, setDataStart] = createGetterSetter<DataPublicPluginS

export const [getI18n, setI18n] = createGetterSetter<I18nStart>('I18n');

export const [getChartsSetup, setChartsSetup] = createGetterSetter<ChartsPluginSetup>(
'ChartsPluginSetup'
);
export const [getCharts, setCharts] = createGetterSetter<ChartsPluginStart>('ChartsPluginStart');
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { VisualizationContainer, PersistedState } from '../../visualizations/pub

import type { TimeseriesVisData } from '../common/types';
import { isVisTableData } from '../common/vis_data_utils';
import { getChartsSetup } from './services';
import { getCharts } from './services';

import type { TimeseriesVisParams } from './types';
import type { ExpressionRenderDefinition } from '../../expressions/common';
Expand Down Expand Up @@ -49,7 +49,7 @@ export const getTimeseriesVisRenderer: (deps: {
handlers.onDestroy(() => {
unmountComponentAtNode(domNode);
});
const { palettes } = getChartsSetup();
const { palettes } = getCharts();
const showNoResult = !checkIfDataExists(config.visData, config.visParams);
const palettesService = await palettes.getPalettes();

Expand Down
4 changes: 4 additions & 0 deletions src/plugins/vis_type_xy/public/components/xy_settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import React, { FC } from 'react';
import {
Direction,
Settings,
SettingsSpecProps,
DomainRange,
Position,
PartialTheme,
Expand Down Expand Up @@ -49,6 +50,7 @@ type XYSettingsProps = Pick<
| 'xAxis'
| 'orderBucketsBySum'
> & {
onPointerUpdate: SettingsSpecProps['onPointerUpdate'];
xDomain?: DomainRange;
adjustedXDomain?: DomainRange;
showLegend: boolean;
Expand Down Expand Up @@ -85,6 +87,7 @@ export const XYSettings: FC<XYSettingsProps> = ({
adjustedXDomain,
showLegend,
onElementClick,
onPointerUpdate,
onBrushEnd,
onRenderChange,
legendAction,
Expand Down Expand Up @@ -152,6 +155,7 @@ export const XYSettings: FC<XYSettingsProps> = ({
return (
<Settings
debugState={window._echDebugStateFlag ?? false}
onPointerUpdate={onPointerUpdate}
xDomain={adjustedXDomain}
rotation={rotation}
theme={[themeOverrides, theme]}
Expand Down
8 changes: 5 additions & 3 deletions src/plugins/vis_type_xy/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public';
import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/public';
import { ChartsPluginSetup } from '../../charts/public';
import { ChartsPluginSetup, ChartsPluginStart } from '../../charts/public';
import { DataPublicPluginStart } from '../../data/public';
import { UsageCollectionSetup } from '../../usage_collection/public';
import {
Expand All @@ -20,6 +20,7 @@ import {
setDocLinks,
setPalettesService,
setTrackUiMetric,
setActiveCursor,
} from './services';

import { visTypesDefinitions } from './vis_types';
Expand All @@ -46,6 +47,7 @@ export interface VisTypeXyPluginStartDependencies {
expressions: ReturnType<ExpressionsPublicPlugin['start']>;
visualizations: VisualizationsStart;
data: DataPublicPluginStart;
charts: ChartsPluginStart;
}

type VisTypeXyCoreSetup = CoreSetup<VisTypeXyPluginStartDependencies, VisTypeXyPluginStart>;
Expand Down Expand Up @@ -87,11 +89,11 @@ export class VisTypeXyPlugin
return {};
}

public start(core: CoreStart, { data }: VisTypeXyPluginStartDependencies) {
public start(core: CoreStart, { data, charts }: VisTypeXyPluginStartDependencies) {
setFormatService(data.fieldFormats);
setDataActions(data.actions);
setDocLinks(core.docLinks);

setActiveCursor(charts.activeCursor);
return {};
}
}
6 changes: 5 additions & 1 deletion src/plugins/vis_type_xy/public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { UiCounterMetricType } from '@kbn/analytics';
import { CoreSetup, DocLinksStart } from '../../../core/public';
import { createGetterSetter } from '../../kibana_utils/public';
import { DataPublicPluginStart } from '../../data/public';
import { ChartsPluginSetup } from '../../charts/public';
import { ChartsPluginSetup, ChartsPluginStart } from '../../charts/public';

export const [getUISettings, setUISettings] = createGetterSetter<CoreSetup['uiSettings']>(
'xy core.uiSettings'
Expand All @@ -28,6 +28,10 @@ export const [getThemeService, setThemeService] = createGetterSetter<ChartsPlugi
'xy charts.theme'
);

export const [getActiveCursor, setActiveCursor] = createGetterSetter<
ChartsPluginStart['activeCursor']
>('xy charts.activeCursor');

export const [getPalettesService, setPalettesService] = createGetterSetter<
ChartsPluginSetup['palettes']
>('xy charts.palette');
Expand Down
Loading

0 comments on commit 3d45332

Please sign in to comment.