mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 11:05:39 -04:00
Expression: Add render mode and use it for canvas interactivity (#83559)
This commit is contained in:
parent
5bc4d75256
commit
38a09b99c4
26 changed files with 344 additions and 96 deletions
|
@ -9,7 +9,7 @@ Constructs a new instance of the `ExpressionRenderHandler` class
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
constructor(element: HTMLElement, { onRenderError }?: Partial<ExpressionRenderHandlerParams>);
|
||||
constructor(element: HTMLElement, { onRenderError, renderMode }?: Partial<ExpressionRenderHandlerParams>);
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
@ -17,5 +17,5 @@ constructor(element: HTMLElement, { onRenderError }?: Partial<ExpressionRenderHa
|
|||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| element | <code>HTMLElement</code> | |
|
||||
| { onRenderError } | <code>Partial<ExpressionRenderHandlerParams></code> | |
|
||||
| { onRenderError, renderMode } | <code>Partial<ExpressionRenderHandlerParams></code> | |
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ export declare class ExpressionRenderHandler
|
|||
|
||||
| Constructor | Modifiers | Description |
|
||||
| --- | --- | --- |
|
||||
| [(constructor)(element, { onRenderError })](./kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md) | | Constructs a new instance of the <code>ExpressionRenderHandler</code> class |
|
||||
| [(constructor)(element, { onRenderError, renderMode })](./kibana-plugin-plugins-expressions-public.expressionrenderhandler._constructor_.md) | | Constructs a new instance of the <code>ExpressionRenderHandler</code> class |
|
||||
|
||||
## Properties
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ export interface IExpressionLoaderParams
|
|||
| [disableCaching](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md) | <code>boolean</code> | |
|
||||
| [inspectorAdapters](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md) | <code>Adapters</code> | |
|
||||
| [onRenderError](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.onrendererror.md) | <code>RenderErrorHandlerFnType</code> | |
|
||||
| [renderMode](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.rendermode.md) | <code>RenderMode</code> | |
|
||||
| [searchContext](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md) | <code>SerializableState</code> | |
|
||||
| [searchSessionId](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md) | <code>string</code> | |
|
||||
| [uiState](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.uistate.md) | <code>unknown</code> | |
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) > [renderMode](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.rendermode.md)
|
||||
|
||||
## IExpressionLoaderParams.renderMode property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
renderMode?: RenderMode;
|
||||
```
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) > [getRenderMode](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.getrendermode.md)
|
||||
|
||||
## IInterpreterRenderHandlers.getRenderMode property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getRenderMode: () => RenderMode;
|
||||
```
|
|
@ -16,6 +16,7 @@ export interface IInterpreterRenderHandlers
|
|||
| --- | --- | --- |
|
||||
| [done](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.done.md) | <code>() => void</code> | Done increments the number of rendering successes |
|
||||
| [event](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.event.md) | <code>(event: any) => void</code> | |
|
||||
| [getRenderMode](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.getrendermode.md) | <code>() => RenderMode</code> | |
|
||||
| [onDestroy](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.ondestroy.md) | <code>(fn: () => void) => void</code> | |
|
||||
| [reload](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md) | <code>() => void</code> | |
|
||||
| [uiState](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md) | <code>PersistedState</code> | |
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) > [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) > [getRenderMode](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.getrendermode.md)
|
||||
|
||||
## IInterpreterRenderHandlers.getRenderMode property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getRenderMode: () => RenderMode;
|
||||
```
|
|
@ -16,6 +16,7 @@ export interface IInterpreterRenderHandlers
|
|||
| --- | --- | --- |
|
||||
| [done](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.done.md) | <code>() => void</code> | Done increments the number of rendering successes |
|
||||
| [event](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.event.md) | <code>(event: any) => void</code> | |
|
||||
| [getRenderMode](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.getrendermode.md) | <code>() => RenderMode</code> | |
|
||||
| [onDestroy](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.ondestroy.md) | <code>(fn: () => void) => void</code> | |
|
||||
| [reload](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md) | <code>() => void</code> | |
|
||||
| [uiState](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md) | <code>PersistedState</code> | |
|
||||
|
|
|
@ -61,6 +61,18 @@ export interface ExpressionRenderDefinition<Config = unknown> {
|
|||
|
||||
export type AnyExpressionRenderDefinition = ExpressionRenderDefinition<any>;
|
||||
|
||||
/**
|
||||
* Mode of the expression render environment.
|
||||
* This value can be set from a consumer embedding an expression renderer and is accessible
|
||||
* from within the active render function as part of the handlers.
|
||||
* The following modes are supported:
|
||||
* * display (default): The chart is rendered in a container with the main purpose of viewing the chart (e.g. in a container like dashboard or canvas)
|
||||
* * preview: The chart is rendered in very restricted space (below 100px width and height) and should only show a rough outline
|
||||
* * edit: The chart is rendered within an editor and configuration elements within the chart should be displayed
|
||||
* * noInteractivity: The chart is rendered in a non-interactive environment and should not provide any affordances for interaction like brushing
|
||||
*/
|
||||
export type RenderMode = 'noInteractivity' | 'edit' | 'preview' | 'display';
|
||||
|
||||
export interface IInterpreterRenderHandlers {
|
||||
/**
|
||||
* Done increments the number of rendering successes
|
||||
|
@ -70,5 +82,6 @@ export interface IInterpreterRenderHandlers {
|
|||
reload: () => void;
|
||||
update: (params: any) => void;
|
||||
event: (event: any) => void;
|
||||
getRenderMode: () => RenderMode;
|
||||
uiState?: PersistedState;
|
||||
}
|
||||
|
|
|
@ -20,17 +20,24 @@
|
|||
import { first, skip, toArray } from 'rxjs/operators';
|
||||
import { loader, ExpressionLoader } from './loader';
|
||||
import { Observable } from 'rxjs';
|
||||
import { parseExpression, IInterpreterRenderHandlers } from '../common';
|
||||
import {
|
||||
parseExpression,
|
||||
IInterpreterRenderHandlers,
|
||||
RenderMode,
|
||||
AnyExpressionFunctionDefinition,
|
||||
} from '../common';
|
||||
|
||||
// eslint-disable-next-line
|
||||
const { __getLastExecution } = require('./services');
|
||||
const { __getLastExecution, __getLastRenderMode } = require('./services');
|
||||
|
||||
const element: HTMLElement = null as any;
|
||||
|
||||
jest.mock('./services', () => {
|
||||
let renderMode: RenderMode | undefined;
|
||||
const renderers: Record<string, unknown> = {
|
||||
test: {
|
||||
render: (el: HTMLElement, value: unknown, handlers: IInterpreterRenderHandlers) => {
|
||||
renderMode = handlers.getRenderMode();
|
||||
handlers.done();
|
||||
},
|
||||
},
|
||||
|
@ -39,9 +46,18 @@ jest.mock('./services', () => {
|
|||
// eslint-disable-next-line
|
||||
const service = new (require('../common/service/expressions_services').ExpressionsService as any)();
|
||||
|
||||
const testFn: AnyExpressionFunctionDefinition = {
|
||||
fn: () => ({ type: 'render', as: 'test' }),
|
||||
name: 'testrender',
|
||||
args: {},
|
||||
help: '',
|
||||
};
|
||||
service.registerFunction(testFn);
|
||||
|
||||
const moduleMock = {
|
||||
__execution: undefined,
|
||||
__getLastExecution: () => moduleMock.__execution,
|
||||
__getLastRenderMode: () => renderMode,
|
||||
getRenderersRegistry: () => ({
|
||||
get: (id: string) => renderers[id],
|
||||
}),
|
||||
|
@ -130,6 +146,14 @@ describe('ExpressionLoader', () => {
|
|||
expect(response).toBe(2);
|
||||
});
|
||||
|
||||
it('passes mode to the renderer', async () => {
|
||||
const expressionLoader = new ExpressionLoader(element, 'testrender', {
|
||||
renderMode: 'edit',
|
||||
});
|
||||
await expressionLoader.render$.pipe(first()).toPromise();
|
||||
expect(__getLastRenderMode()).toEqual('edit');
|
||||
});
|
||||
|
||||
it('cancels the previous request when the expression is updated', () => {
|
||||
const expressionLoader = new ExpressionLoader(element, 'var foo', {});
|
||||
const execution = __getLastExecution();
|
||||
|
|
|
@ -63,6 +63,7 @@ export class ExpressionLoader {
|
|||
|
||||
this.renderHandler = new ExpressionRenderHandler(element, {
|
||||
onRenderError: params && params.onRenderError,
|
||||
renderMode: params?.renderMode,
|
||||
});
|
||||
this.render$ = this.renderHandler.render$;
|
||||
this.update$ = this.renderHandler.update$;
|
||||
|
|
|
@ -530,7 +530,7 @@ export interface ExpressionRenderError extends Error {
|
|||
// @public (undocumented)
|
||||
export class ExpressionRenderHandler {
|
||||
// Warning: (ae-forgotten-export) The symbol "ExpressionRenderHandlerParams" needs to be exported by the entry point index.d.ts
|
||||
constructor(element: HTMLElement, { onRenderError }?: Partial<ExpressionRenderHandlerParams>);
|
||||
constructor(element: HTMLElement, { onRenderError, renderMode }?: Partial<ExpressionRenderHandlerParams>);
|
||||
// (undocumented)
|
||||
destroy: () => void;
|
||||
// (undocumented)
|
||||
|
@ -891,6 +891,10 @@ export interface IExpressionLoaderParams {
|
|||
//
|
||||
// (undocumented)
|
||||
onRenderError?: RenderErrorHandlerFnType;
|
||||
// Warning: (ae-forgotten-export) The symbol "RenderMode" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
renderMode?: RenderMode;
|
||||
// (undocumented)
|
||||
searchContext?: SerializableState_2;
|
||||
// (undocumented)
|
||||
|
@ -909,6 +913,8 @@ export interface IInterpreterRenderHandlers {
|
|||
// (undocumented)
|
||||
event: (event: any) => void;
|
||||
// (undocumented)
|
||||
getRenderMode: () => RenderMode;
|
||||
// (undocumented)
|
||||
onDestroy: (fn: () => void) => void;
|
||||
// (undocumented)
|
||||
reload: () => void;
|
||||
|
|
|
@ -22,7 +22,7 @@ import { Observable } from 'rxjs';
|
|||
import { filter } from 'rxjs/operators';
|
||||
import { ExpressionRenderError, RenderErrorHandlerFnType, IExpressionLoaderParams } from './types';
|
||||
import { renderErrorHandler as defaultRenderErrorHandler } from './render_error_handler';
|
||||
import { IInterpreterRenderHandlers, ExpressionAstExpression } from '../common';
|
||||
import { IInterpreterRenderHandlers, ExpressionAstExpression, RenderMode } from '../common';
|
||||
|
||||
import { getRenderersRegistry } from './services';
|
||||
|
||||
|
@ -30,6 +30,7 @@ export type IExpressionRendererExtraHandlers = Record<string, any>;
|
|||
|
||||
export interface ExpressionRenderHandlerParams {
|
||||
onRenderError: RenderErrorHandlerFnType;
|
||||
renderMode: RenderMode;
|
||||
}
|
||||
|
||||
export interface ExpressionRendererEvent {
|
||||
|
@ -58,7 +59,7 @@ export class ExpressionRenderHandler {
|
|||
|
||||
constructor(
|
||||
element: HTMLElement,
|
||||
{ onRenderError }: Partial<ExpressionRenderHandlerParams> = {}
|
||||
{ onRenderError, renderMode }: Partial<ExpressionRenderHandlerParams> = {}
|
||||
) {
|
||||
this.element = element;
|
||||
|
||||
|
@ -92,6 +93,9 @@ export class ExpressionRenderHandler {
|
|||
event: (data) => {
|
||||
this.eventsSubject.next(data);
|
||||
},
|
||||
getRenderMode: () => {
|
||||
return renderMode || 'display';
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import {
|
|||
ExpressionValue,
|
||||
ExpressionsService,
|
||||
SerializableState,
|
||||
RenderMode,
|
||||
} from '../../common';
|
||||
|
||||
/**
|
||||
|
@ -54,6 +55,7 @@ export interface IExpressionLoaderParams {
|
|||
inspectorAdapters?: Adapters;
|
||||
onRenderError?: RenderErrorHandlerFnType;
|
||||
searchSessionId?: string;
|
||||
renderMode?: RenderMode;
|
||||
}
|
||||
|
||||
export interface ExpressionRenderError extends Error {
|
||||
|
|
|
@ -729,6 +729,10 @@ export interface IInterpreterRenderHandlers {
|
|||
done: () => void;
|
||||
// (undocumented)
|
||||
event: (event: any) => void;
|
||||
// Warning: (ae-forgotten-export) The symbol "RenderMode" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
getRenderMode: () => RenderMode;
|
||||
// (undocumented)
|
||||
onDestroy: (fn: () => void) => void;
|
||||
// (undocumented)
|
||||
|
|
|
@ -83,6 +83,7 @@ export function savedLens(): ExpressionFunctionDefinition<
|
|||
title: args.title === null ? undefined : args.title,
|
||||
disableTriggers: true,
|
||||
palette: args.palette,
|
||||
renderMode: 'noInteractivity',
|
||||
},
|
||||
embeddableType: EmbeddableTypes.lens,
|
||||
generatedAt: Date.now(),
|
||||
|
|
|
@ -11,6 +11,7 @@ export const defaultHandlers: RendererHandlers = {
|
|||
destroy: () => action('destroy'),
|
||||
getElementId: () => 'element-id',
|
||||
getFilter: () => 'filter',
|
||||
getRenderMode: () => 'display',
|
||||
onComplete: (fn) => undefined,
|
||||
onEmbeddableDestroyed: action('onEmbeddableDestroyed'),
|
||||
onEmbeddableInputChange: action('onEmbeddableInputChange'),
|
||||
|
|
|
@ -23,6 +23,9 @@ export const createHandlers = (): RendererHandlers => ({
|
|||
getFilter() {
|
||||
return '';
|
||||
},
|
||||
getRenderMode() {
|
||||
return 'display';
|
||||
},
|
||||
onComplete(fn: () => void) {
|
||||
this.done = fn;
|
||||
},
|
||||
|
|
|
@ -262,6 +262,45 @@ describe('embeddable', () => {
|
|||
expect(expressionRenderer.mock.calls[0][0].searchSessionId).toBe(input.searchSessionId);
|
||||
});
|
||||
|
||||
it('should pass render mode to expression', async () => {
|
||||
const timeRange: TimeRange = { from: 'now-15d', to: 'now' };
|
||||
const query: Query = { language: 'kquery', query: '' };
|
||||
const filters: Filter[] = [{ meta: { alias: 'test', negate: false, disabled: false } }];
|
||||
|
||||
const input = {
|
||||
savedObjectId: '123',
|
||||
timeRange,
|
||||
query,
|
||||
filters,
|
||||
renderMode: 'noInteractivity',
|
||||
} as LensEmbeddableInput;
|
||||
|
||||
const embeddable = new Embeddable(
|
||||
{
|
||||
timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter,
|
||||
attributeService,
|
||||
expressionRenderer,
|
||||
basePath,
|
||||
indexPatternService: {} as IndexPatternsContract,
|
||||
editable: true,
|
||||
getTrigger,
|
||||
documentToExpression: () =>
|
||||
Promise.resolve({
|
||||
type: 'expression',
|
||||
chain: [
|
||||
{ type: 'function', function: 'my', arguments: {} },
|
||||
{ type: 'function', function: 'expression', arguments: {} },
|
||||
],
|
||||
}),
|
||||
},
|
||||
input
|
||||
);
|
||||
await embeddable.initializeSavedVis(input);
|
||||
embeddable.render(mountpoint);
|
||||
|
||||
expect(expressionRenderer.mock.calls[0][0].renderMode).toEqual('noInteractivity');
|
||||
});
|
||||
|
||||
it('should merge external context with query and filters of the saved object', async () => {
|
||||
const timeRange: TimeRange = { from: 'now-15d', to: 'now' };
|
||||
const query: Query = { language: 'kquery', query: 'external filter' };
|
||||
|
|
|
@ -20,6 +20,7 @@ import { PaletteOutput } from 'src/plugins/charts/public';
|
|||
|
||||
import { Subscription } from 'rxjs';
|
||||
import { toExpression, Ast } from '@kbn/interpreter/common';
|
||||
import { RenderMode } from 'src/plugins/expressions';
|
||||
import {
|
||||
ExpressionRendererEvent,
|
||||
ReactExpressionRendererType,
|
||||
|
@ -53,6 +54,7 @@ export type LensByValueInput = {
|
|||
export type LensByReferenceInput = SavedObjectEmbeddableInput & EmbeddableInput;
|
||||
export type LensEmbeddableInput = (LensByValueInput | LensByReferenceInput) & {
|
||||
palette?: PaletteOutput;
|
||||
renderMode?: RenderMode;
|
||||
};
|
||||
|
||||
export interface LensEmbeddableOutput extends EmbeddableOutput {
|
||||
|
@ -192,6 +194,7 @@ export class Embeddable
|
|||
variables={input.palette ? { theme: { palette: input.palette } } : {}}
|
||||
searchSessionId={this.input.searchSessionId}
|
||||
handleEvent={this.handleEvent}
|
||||
renderMode={input.renderMode}
|
||||
/>,
|
||||
domNode
|
||||
);
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
ReactExpressionRendererType,
|
||||
} from 'src/plugins/expressions/public';
|
||||
import { ExecutionContextSearch } from 'src/plugins/data/public';
|
||||
import { RenderMode } from 'src/plugins/expressions';
|
||||
import { getOriginalRequestErrorMessage } from '../error_helper';
|
||||
|
||||
export interface ExpressionWrapperProps {
|
||||
|
@ -22,6 +23,7 @@ export interface ExpressionWrapperProps {
|
|||
searchContext: ExecutionContextSearch;
|
||||
searchSessionId?: string;
|
||||
handleEvent: (event: ExpressionRendererEvent) => void;
|
||||
renderMode?: RenderMode;
|
||||
}
|
||||
|
||||
export function ExpressionWrapper({
|
||||
|
@ -31,6 +33,7 @@ export function ExpressionWrapper({
|
|||
variables,
|
||||
handleEvent,
|
||||
searchSessionId,
|
||||
renderMode,
|
||||
}: ExpressionWrapperProps) {
|
||||
return (
|
||||
<I18nProvider>
|
||||
|
@ -57,6 +60,7 @@ export function ExpressionWrapper({
|
|||
expression={expression}
|
||||
searchContext={searchContext}
|
||||
searchSessionId={searchSessionId}
|
||||
renderMode={renderMode}
|
||||
renderError={(errorMessage, error) => (
|
||||
<div data-test-subj="expression-renderer-error">
|
||||
<EuiFlexGroup direction="column" alignItems="center" justifyContent="center">
|
||||
|
|
|
@ -139,6 +139,7 @@ export const getPieRenderer = (dependencies: {
|
|||
chartsThemeService={dependencies.chartsThemeService}
|
||||
paletteService={dependencies.paletteService}
|
||||
onClickValue={onClickValue}
|
||||
renderMode={handlers.getRenderMode()}
|
||||
/>
|
||||
</I18nProvider>,
|
||||
domNode,
|
||||
|
|
|
@ -70,6 +70,7 @@ describe('PieVisualization component', () => {
|
|||
onClickValue: jest.fn(),
|
||||
chartsThemeService,
|
||||
paletteService: chartPluginMock.createPaletteRegistry(),
|
||||
renderMode: 'display' as const,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -266,6 +267,14 @@ describe('PieVisualization component', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('does not set click listener on noInteractivity render mode', () => {
|
||||
const defaultArgs = getDefaultArgs();
|
||||
const component = shallow(
|
||||
<PieComponent args={{ ...args }} {...defaultArgs} renderMode="noInteractivity" />
|
||||
);
|
||||
expect(component.find(Settings).first().prop('onElementClick')).toBeUndefined();
|
||||
});
|
||||
|
||||
test('it shows emptyPlaceholder for undefined grouped data', () => {
|
||||
const defaultData = getDefaultArgs().data;
|
||||
const emptyData: LensMultiTable = {
|
||||
|
|
|
@ -20,7 +20,9 @@ import {
|
|||
RecursivePartial,
|
||||
Position,
|
||||
Settings,
|
||||
ElementClickListener,
|
||||
} from '@elastic/charts';
|
||||
import { RenderMode } from 'src/plugins/expressions';
|
||||
import { FormatFactory, LensFilterEvent } from '../types';
|
||||
import { VisualizationContainer } from '../visualization_container';
|
||||
import { CHART_NAMES, DEFAULT_PERCENT_DECIMALS } from './constants';
|
||||
|
@ -44,6 +46,7 @@ export function PieComponent(
|
|||
chartsThemeService: ChartsPluginSetup['theme'];
|
||||
paletteService: PaletteRegistry;
|
||||
onClickValue: (data: LensFilterEvent['data']) => void;
|
||||
renderMode: RenderMode;
|
||||
}
|
||||
) {
|
||||
const [firstTable] = Object.values(props.data.tables);
|
||||
|
@ -228,6 +231,12 @@ export function PieComponent(
|
|||
</EuiText>
|
||||
);
|
||||
}
|
||||
|
||||
const onElementClickHandler: ElementClickListener = (args) => {
|
||||
const context = getFilterContext(args[0][0] as LayerValue[], groups, firstTable);
|
||||
|
||||
onClickValue(desanitizeFilterContext(context));
|
||||
};
|
||||
return (
|
||||
<VisualizationContainer
|
||||
reportTitle={props.args.title}
|
||||
|
@ -248,11 +257,9 @@ export function PieComponent(
|
|||
}
|
||||
legendPosition={legendPosition || Position.Right}
|
||||
legendMaxDepth={nestedLegend ? undefined : 1 /* Color is based only on first layer */}
|
||||
onElementClick={(args) => {
|
||||
const context = getFilterContext(args[0][0] as LayerValue[], groups, firstTable);
|
||||
|
||||
onClickValue(desanitizeFilterContext(context));
|
||||
}}
|
||||
onElementClick={
|
||||
props.renderMode !== 'noInteractivity' ? onElementClickHandler : undefined
|
||||
}
|
||||
theme={{
|
||||
...chartTheme,
|
||||
background: {
|
||||
|
|
|
@ -427,6 +427,7 @@ describe('xy_expression', () => {
|
|||
args={args}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -451,6 +452,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'line' }] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -504,6 +506,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={undefined}
|
||||
|
@ -541,6 +544,7 @@ describe('xy_expression', () => {
|
|||
args={multiLayerArgs}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -578,6 +582,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -596,6 +601,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar' }] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -617,6 +623,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'area' }] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -638,6 +645,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar_horizontal' }] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -664,6 +672,7 @@ describe('xy_expression', () => {
|
|||
args={args}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -688,6 +697,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -773,6 +783,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -791,6 +802,27 @@ describe('xy_expression', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('onBrushEnd is not set on noInteractivity mode', () => {
|
||||
const { args, data } = sampleArgs();
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
<XYChart
|
||||
data={data}
|
||||
args={args}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="noInteractivity"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
onClickValue={onClickValue}
|
||||
onSelectRange={onSelectRange}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(Settings).first().prop('onBrushEnd')).toBeUndefined();
|
||||
});
|
||||
|
||||
test('onElementClick returns correct context data', () => {
|
||||
const geometry: GeometryValue = { x: 5, y: 1, accessor: 'y1', mark: null, datum: {} };
|
||||
const series = {
|
||||
|
@ -825,6 +857,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -855,6 +888,27 @@ describe('xy_expression', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('onElementClick is not triggering event on noInteractivity mode', () => {
|
||||
const { args, data } = sampleArgs();
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
<XYChart
|
||||
data={data}
|
||||
args={args}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="noInteractivity"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
onClickValue={onClickValue}
|
||||
onSelectRange={onSelectRange}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(Settings).first().prop('onElementClick')).toBeUndefined();
|
||||
});
|
||||
|
||||
test('it renders stacked bar', () => {
|
||||
const { data, args } = sampleArgs();
|
||||
const component = shallow(
|
||||
|
@ -863,6 +917,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar_stacked' }] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -884,6 +939,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'area_stacked' }] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -908,6 +964,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -941,6 +998,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -961,6 +1019,7 @@ describe('xy_expression', () => {
|
|||
args={args}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="CEST"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -987,6 +1046,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [firstLayer] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1007,6 +1067,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [firstLayer] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1030,6 +1091,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [firstLayer, secondLayer] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1058,6 +1120,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1080,6 +1143,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1481,6 +1545,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [{ ...args.layers[0], xScaleType: 'ordinal' }] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1501,6 +1566,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, layers: [{ ...args.layers[0], yScaleType: 'sqrt' }] }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1521,6 +1587,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1544,6 +1611,7 @@ describe('xy_expression', () => {
|
|||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
onClickValue={onClickValue}
|
||||
onSelectRange={onSelectRange}
|
||||
/>
|
||||
|
@ -1563,6 +1631,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1598,6 +1667,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1631,6 +1701,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1664,6 +1735,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1697,6 +1769,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1797,6 +1870,7 @@ describe('xy_expression', () => {
|
|||
args={args}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1871,6 +1945,7 @@ describe('xy_expression', () => {
|
|||
args={args}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1943,6 +2018,7 @@ describe('xy_expression', () => {
|
|||
args={args}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1967,6 +2043,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -1990,6 +2067,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -2013,6 +2091,7 @@ describe('xy_expression', () => {
|
|||
}}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -2048,6 +2127,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args, fittingFunction: 'Carry' }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -2075,6 +2155,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -2097,6 +2178,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -2124,6 +2206,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
@ -2157,6 +2240,7 @@ describe('xy_expression', () => {
|
|||
args={{ ...args }}
|
||||
formatFactory={getFormatSpy}
|
||||
timeZone="UTC"
|
||||
renderMode="display"
|
||||
chartsThemeService={chartsThemeService}
|
||||
paletteService={paletteService}
|
||||
minInterval={50}
|
||||
|
|
|
@ -21,6 +21,8 @@ import {
|
|||
StackMode,
|
||||
VerticalAlignment,
|
||||
HorizontalAlignment,
|
||||
ElementClickListener,
|
||||
BrushEndListener,
|
||||
} from '@elastic/charts';
|
||||
import { I18nProvider } from '@kbn/i18n/react';
|
||||
import {
|
||||
|
@ -31,6 +33,7 @@ import {
|
|||
} from 'src/plugins/expressions/public';
|
||||
import { IconType } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { RenderMode } from 'src/plugins/expressions';
|
||||
import {
|
||||
LensMultiTable,
|
||||
FormatFactory,
|
||||
|
@ -81,6 +84,7 @@ type XYChartRenderProps = XYChartProps & {
|
|||
minInterval: number | undefined;
|
||||
onClickValue: (data: LensFilterEvent['data']) => void;
|
||||
onSelectRange: (data: LensBrushEvent['data']) => void;
|
||||
renderMode: RenderMode;
|
||||
};
|
||||
|
||||
export const xyChart: ExpressionFunctionDefinition<
|
||||
|
@ -235,6 +239,7 @@ export const getXyChartRenderer = (dependencies: {
|
|||
minInterval={await calculateMinInterval(config, dependencies.getIntervalByColumn)}
|
||||
onClickValue={onClickValue}
|
||||
onSelectRange={onSelectRange}
|
||||
renderMode={handlers.getRenderMode()}
|
||||
/>
|
||||
</I18nProvider>,
|
||||
domNode,
|
||||
|
@ -303,6 +308,7 @@ export function XYChart({
|
|||
minInterval,
|
||||
onClickValue,
|
||||
onSelectRange,
|
||||
renderMode,
|
||||
}: XYChartRenderProps) {
|
||||
const { legend, layers, fittingFunction, gridlinesVisibilitySettings, valueLabels } = args;
|
||||
const chartTheme = chartsThemeService.useChartsTheme();
|
||||
|
@ -415,60 +421,7 @@ export function XYChart({
|
|||
|
||||
const colorAssignments = getColorAssignments(args.layers, data, formatFactory);
|
||||
|
||||
return (
|
||||
<Chart>
|
||||
<Settings
|
||||
showLegend={
|
||||
legend.isVisible && !legend.showSingleSeries
|
||||
? chartHasMoreThanOneSeries
|
||||
: legend.isVisible
|
||||
}
|
||||
legendPosition={legend.position}
|
||||
showLegendExtra={false}
|
||||
theme={{
|
||||
...chartTheme,
|
||||
barSeriesStyle: {
|
||||
...chartTheme.barSeriesStyle,
|
||||
...valueLabelsStyling,
|
||||
},
|
||||
background: {
|
||||
color: undefined, // removes background for embeddables
|
||||
},
|
||||
}}
|
||||
baseTheme={chartBaseTheme}
|
||||
tooltip={{
|
||||
headerFormatter: (d) => safeXAccessorLabelRenderer(d.value),
|
||||
}}
|
||||
rotation={shouldRotate ? 90 : 0}
|
||||
xDomain={xDomain}
|
||||
onBrushEnd={({ x }) => {
|
||||
if (!x) {
|
||||
return;
|
||||
}
|
||||
const [min, max] = x;
|
||||
if (!xAxisColumn || !isHistogramViz) {
|
||||
return;
|
||||
}
|
||||
|
||||
const table = data.tables[filteredLayers[0].layerId];
|
||||
|
||||
const xAxisColumnIndex = table.columns.findIndex(
|
||||
(el) => el.id === filteredLayers[0].xAccessor
|
||||
);
|
||||
|
||||
const timeFieldName = isTimeViz
|
||||
? table.columns[xAxisColumnIndex]?.meta?.field
|
||||
: undefined;
|
||||
|
||||
const context: LensBrushEvent['data'] = {
|
||||
range: [min, max],
|
||||
table,
|
||||
column: xAxisColumnIndex,
|
||||
timeFieldName,
|
||||
};
|
||||
onSelectRange(context);
|
||||
}}
|
||||
onElementClick={([[geometry, series]]) => {
|
||||
const clickHandler: ElementClickListener = ([[geometry, series]]) => {
|
||||
// for xyChart series is always XYChartSeriesIdentifier and geometry is always type of GeometryValue
|
||||
const xySeries = series as XYChartSeriesIdentifier;
|
||||
const xyGeometry = geometry as GeometryValue;
|
||||
|
@ -523,7 +476,60 @@ export function XYChart({
|
|||
timeFieldName,
|
||||
};
|
||||
onClickValue(desanitizeFilterContext(context));
|
||||
};
|
||||
|
||||
const brushHandler: BrushEndListener = ({ x }) => {
|
||||
if (!x) {
|
||||
return;
|
||||
}
|
||||
const [min, max] = x;
|
||||
if (!xAxisColumn || !isHistogramViz) {
|
||||
return;
|
||||
}
|
||||
|
||||
const table = data.tables[filteredLayers[0].layerId];
|
||||
|
||||
const xAxisColumnIndex = table.columns.findIndex((el) => el.id === filteredLayers[0].xAccessor);
|
||||
|
||||
const timeFieldName = isTimeViz ? table.columns[xAxisColumnIndex]?.meta?.field : undefined;
|
||||
|
||||
const context: LensBrushEvent['data'] = {
|
||||
range: [min, max],
|
||||
table,
|
||||
column: xAxisColumnIndex,
|
||||
timeFieldName,
|
||||
};
|
||||
onSelectRange(context);
|
||||
};
|
||||
|
||||
return (
|
||||
<Chart>
|
||||
<Settings
|
||||
showLegend={
|
||||
legend.isVisible && !legend.showSingleSeries
|
||||
? chartHasMoreThanOneSeries
|
||||
: legend.isVisible
|
||||
}
|
||||
legendPosition={legend.position}
|
||||
showLegendExtra={false}
|
||||
theme={{
|
||||
...chartTheme,
|
||||
barSeriesStyle: {
|
||||
...chartTheme.barSeriesStyle,
|
||||
...valueLabelsStyling,
|
||||
},
|
||||
background: {
|
||||
color: undefined, // removes background for embeddables
|
||||
},
|
||||
}}
|
||||
baseTheme={chartBaseTheme}
|
||||
tooltip={{
|
||||
headerFormatter: (d) => safeXAccessorLabelRenderer(d.value),
|
||||
}}
|
||||
rotation={shouldRotate ? 90 : 0}
|
||||
xDomain={xDomain}
|
||||
onBrushEnd={renderMode !== 'noInteractivity' ? brushHandler : undefined}
|
||||
onElementClick={renderMode !== 'noInteractivity' ? clickHandler : undefined}
|
||||
/>
|
||||
|
||||
<Axis
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue