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>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
constructor(element: HTMLElement, { onRenderError }?: Partial<ExpressionRenderHandlerParams>);
|
constructor(element: HTMLElement, { onRenderError, renderMode }?: Partial<ExpressionRenderHandlerParams>);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
@ -17,5 +17,5 @@ constructor(element: HTMLElement, { onRenderError }?: Partial<ExpressionRenderHa
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| element | <code>HTMLElement</code> | |
|
| 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 | 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
|
## Properties
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ export interface IExpressionLoaderParams
|
||||||
| [disableCaching](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md) | <code>boolean</code> | |
|
| [disableCaching](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.disablecaching.md) | <code>boolean</code> | |
|
||||||
| [inspectorAdapters](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.inspectoradapters.md) | <code>Adapters</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> | |
|
| [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> | |
|
| [searchContext](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchcontext.md) | <code>SerializableState</code> | |
|
||||||
| [searchSessionId](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.searchsessionid.md) | <code>string</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> | |
|
| [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 |
|
| [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> | |
|
| [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> | |
|
| [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> | |
|
| [reload](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md) | <code>() => void</code> | |
|
||||||
| [uiState](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md) | <code>PersistedState</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 |
|
| [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> | |
|
| [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> | |
|
| [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> | |
|
| [reload](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md) | <code>() => void</code> | |
|
||||||
| [uiState](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md) | <code>PersistedState</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>;
|
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 {
|
export interface IInterpreterRenderHandlers {
|
||||||
/**
|
/**
|
||||||
* Done increments the number of rendering successes
|
* Done increments the number of rendering successes
|
||||||
|
@ -70,5 +82,6 @@ export interface IInterpreterRenderHandlers {
|
||||||
reload: () => void;
|
reload: () => void;
|
||||||
update: (params: any) => void;
|
update: (params: any) => void;
|
||||||
event: (event: any) => void;
|
event: (event: any) => void;
|
||||||
|
getRenderMode: () => RenderMode;
|
||||||
uiState?: PersistedState;
|
uiState?: PersistedState;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,17 +20,24 @@
|
||||||
import { first, skip, toArray } from 'rxjs/operators';
|
import { first, skip, toArray } from 'rxjs/operators';
|
||||||
import { loader, ExpressionLoader } from './loader';
|
import { loader, ExpressionLoader } from './loader';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { parseExpression, IInterpreterRenderHandlers } from '../common';
|
import {
|
||||||
|
parseExpression,
|
||||||
|
IInterpreterRenderHandlers,
|
||||||
|
RenderMode,
|
||||||
|
AnyExpressionFunctionDefinition,
|
||||||
|
} from '../common';
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const { __getLastExecution } = require('./services');
|
const { __getLastExecution, __getLastRenderMode } = require('./services');
|
||||||
|
|
||||||
const element: HTMLElement = null as any;
|
const element: HTMLElement = null as any;
|
||||||
|
|
||||||
jest.mock('./services', () => {
|
jest.mock('./services', () => {
|
||||||
|
let renderMode: RenderMode | undefined;
|
||||||
const renderers: Record<string, unknown> = {
|
const renderers: Record<string, unknown> = {
|
||||||
test: {
|
test: {
|
||||||
render: (el: HTMLElement, value: unknown, handlers: IInterpreterRenderHandlers) => {
|
render: (el: HTMLElement, value: unknown, handlers: IInterpreterRenderHandlers) => {
|
||||||
|
renderMode = handlers.getRenderMode();
|
||||||
handlers.done();
|
handlers.done();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -39,9 +46,18 @@ jest.mock('./services', () => {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const service = new (require('../common/service/expressions_services').ExpressionsService as any)();
|
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 = {
|
const moduleMock = {
|
||||||
__execution: undefined,
|
__execution: undefined,
|
||||||
__getLastExecution: () => moduleMock.__execution,
|
__getLastExecution: () => moduleMock.__execution,
|
||||||
|
__getLastRenderMode: () => renderMode,
|
||||||
getRenderersRegistry: () => ({
|
getRenderersRegistry: () => ({
|
||||||
get: (id: string) => renderers[id],
|
get: (id: string) => renderers[id],
|
||||||
}),
|
}),
|
||||||
|
@ -130,6 +146,14 @@ describe('ExpressionLoader', () => {
|
||||||
expect(response).toBe(2);
|
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', () => {
|
it('cancels the previous request when the expression is updated', () => {
|
||||||
const expressionLoader = new ExpressionLoader(element, 'var foo', {});
|
const expressionLoader = new ExpressionLoader(element, 'var foo', {});
|
||||||
const execution = __getLastExecution();
|
const execution = __getLastExecution();
|
||||||
|
|
|
@ -63,6 +63,7 @@ export class ExpressionLoader {
|
||||||
|
|
||||||
this.renderHandler = new ExpressionRenderHandler(element, {
|
this.renderHandler = new ExpressionRenderHandler(element, {
|
||||||
onRenderError: params && params.onRenderError,
|
onRenderError: params && params.onRenderError,
|
||||||
|
renderMode: params?.renderMode,
|
||||||
});
|
});
|
||||||
this.render$ = this.renderHandler.render$;
|
this.render$ = this.renderHandler.render$;
|
||||||
this.update$ = this.renderHandler.update$;
|
this.update$ = this.renderHandler.update$;
|
||||||
|
|
|
@ -530,7 +530,7 @@ export interface ExpressionRenderError extends Error {
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export class ExpressionRenderHandler {
|
export class ExpressionRenderHandler {
|
||||||
// Warning: (ae-forgotten-export) The symbol "ExpressionRenderHandlerParams" needs to be exported by the entry point index.d.ts
|
// 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)
|
// (undocumented)
|
||||||
destroy: () => void;
|
destroy: () => void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
@ -891,6 +891,10 @@ export interface IExpressionLoaderParams {
|
||||||
//
|
//
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
onRenderError?: RenderErrorHandlerFnType;
|
onRenderError?: RenderErrorHandlerFnType;
|
||||||
|
// Warning: (ae-forgotten-export) The symbol "RenderMode" needs to be exported by the entry point index.d.ts
|
||||||
|
//
|
||||||
|
// (undocumented)
|
||||||
|
renderMode?: RenderMode;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
searchContext?: SerializableState_2;
|
searchContext?: SerializableState_2;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
@ -909,6 +913,8 @@ export interface IInterpreterRenderHandlers {
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
event: (event: any) => void;
|
event: (event: any) => void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
getRenderMode: () => RenderMode;
|
||||||
|
// (undocumented)
|
||||||
onDestroy: (fn: () => void) => void;
|
onDestroy: (fn: () => void) => void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
reload: () => void;
|
reload: () => void;
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { Observable } from 'rxjs';
|
||||||
import { filter } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
import { ExpressionRenderError, RenderErrorHandlerFnType, IExpressionLoaderParams } from './types';
|
import { ExpressionRenderError, RenderErrorHandlerFnType, IExpressionLoaderParams } from './types';
|
||||||
import { renderErrorHandler as defaultRenderErrorHandler } from './render_error_handler';
|
import { renderErrorHandler as defaultRenderErrorHandler } from './render_error_handler';
|
||||||
import { IInterpreterRenderHandlers, ExpressionAstExpression } from '../common';
|
import { IInterpreterRenderHandlers, ExpressionAstExpression, RenderMode } from '../common';
|
||||||
|
|
||||||
import { getRenderersRegistry } from './services';
|
import { getRenderersRegistry } from './services';
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ export type IExpressionRendererExtraHandlers = Record<string, any>;
|
||||||
|
|
||||||
export interface ExpressionRenderHandlerParams {
|
export interface ExpressionRenderHandlerParams {
|
||||||
onRenderError: RenderErrorHandlerFnType;
|
onRenderError: RenderErrorHandlerFnType;
|
||||||
|
renderMode: RenderMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExpressionRendererEvent {
|
export interface ExpressionRendererEvent {
|
||||||
|
@ -58,7 +59,7 @@ export class ExpressionRenderHandler {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
element: HTMLElement,
|
element: HTMLElement,
|
||||||
{ onRenderError }: Partial<ExpressionRenderHandlerParams> = {}
|
{ onRenderError, renderMode }: Partial<ExpressionRenderHandlerParams> = {}
|
||||||
) {
|
) {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
|
|
||||||
|
@ -92,6 +93,9 @@ export class ExpressionRenderHandler {
|
||||||
event: (data) => {
|
event: (data) => {
|
||||||
this.eventsSubject.next(data);
|
this.eventsSubject.next(data);
|
||||||
},
|
},
|
||||||
|
getRenderMode: () => {
|
||||||
|
return renderMode || 'display';
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
ExpressionValue,
|
ExpressionValue,
|
||||||
ExpressionsService,
|
ExpressionsService,
|
||||||
SerializableState,
|
SerializableState,
|
||||||
|
RenderMode,
|
||||||
} from '../../common';
|
} from '../../common';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,6 +55,7 @@ export interface IExpressionLoaderParams {
|
||||||
inspectorAdapters?: Adapters;
|
inspectorAdapters?: Adapters;
|
||||||
onRenderError?: RenderErrorHandlerFnType;
|
onRenderError?: RenderErrorHandlerFnType;
|
||||||
searchSessionId?: string;
|
searchSessionId?: string;
|
||||||
|
renderMode?: RenderMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExpressionRenderError extends Error {
|
export interface ExpressionRenderError extends Error {
|
||||||
|
|
|
@ -729,6 +729,10 @@ export interface IInterpreterRenderHandlers {
|
||||||
done: () => void;
|
done: () => void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
event: (event: any) => void;
|
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)
|
// (undocumented)
|
||||||
onDestroy: (fn: () => void) => void;
|
onDestroy: (fn: () => void) => void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
|
|
@ -83,6 +83,7 @@ export function savedLens(): ExpressionFunctionDefinition<
|
||||||
title: args.title === null ? undefined : args.title,
|
title: args.title === null ? undefined : args.title,
|
||||||
disableTriggers: true,
|
disableTriggers: true,
|
||||||
palette: args.palette,
|
palette: args.palette,
|
||||||
|
renderMode: 'noInteractivity',
|
||||||
},
|
},
|
||||||
embeddableType: EmbeddableTypes.lens,
|
embeddableType: EmbeddableTypes.lens,
|
||||||
generatedAt: Date.now(),
|
generatedAt: Date.now(),
|
||||||
|
|
|
@ -11,6 +11,7 @@ export const defaultHandlers: RendererHandlers = {
|
||||||
destroy: () => action('destroy'),
|
destroy: () => action('destroy'),
|
||||||
getElementId: () => 'element-id',
|
getElementId: () => 'element-id',
|
||||||
getFilter: () => 'filter',
|
getFilter: () => 'filter',
|
||||||
|
getRenderMode: () => 'display',
|
||||||
onComplete: (fn) => undefined,
|
onComplete: (fn) => undefined,
|
||||||
onEmbeddableDestroyed: action('onEmbeddableDestroyed'),
|
onEmbeddableDestroyed: action('onEmbeddableDestroyed'),
|
||||||
onEmbeddableInputChange: action('onEmbeddableInputChange'),
|
onEmbeddableInputChange: action('onEmbeddableInputChange'),
|
||||||
|
|
|
@ -23,6 +23,9 @@ export const createHandlers = (): RendererHandlers => ({
|
||||||
getFilter() {
|
getFilter() {
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
|
getRenderMode() {
|
||||||
|
return 'display';
|
||||||
|
},
|
||||||
onComplete(fn: () => void) {
|
onComplete(fn: () => void) {
|
||||||
this.done = fn;
|
this.done = fn;
|
||||||
},
|
},
|
||||||
|
|
|
@ -262,6 +262,45 @@ describe('embeddable', () => {
|
||||||
expect(expressionRenderer.mock.calls[0][0].searchSessionId).toBe(input.searchSessionId);
|
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 () => {
|
it('should merge external context with query and filters of the saved object', async () => {
|
||||||
const timeRange: TimeRange = { from: 'now-15d', to: 'now' };
|
const timeRange: TimeRange = { from: 'now-15d', to: 'now' };
|
||||||
const query: Query = { language: 'kquery', query: 'external filter' };
|
const query: Query = { language: 'kquery', query: 'external filter' };
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { PaletteOutput } from 'src/plugins/charts/public';
|
||||||
|
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { toExpression, Ast } from '@kbn/interpreter/common';
|
import { toExpression, Ast } from '@kbn/interpreter/common';
|
||||||
|
import { RenderMode } from 'src/plugins/expressions';
|
||||||
import {
|
import {
|
||||||
ExpressionRendererEvent,
|
ExpressionRendererEvent,
|
||||||
ReactExpressionRendererType,
|
ReactExpressionRendererType,
|
||||||
|
@ -53,6 +54,7 @@ export type LensByValueInput = {
|
||||||
export type LensByReferenceInput = SavedObjectEmbeddableInput & EmbeddableInput;
|
export type LensByReferenceInput = SavedObjectEmbeddableInput & EmbeddableInput;
|
||||||
export type LensEmbeddableInput = (LensByValueInput | LensByReferenceInput) & {
|
export type LensEmbeddableInput = (LensByValueInput | LensByReferenceInput) & {
|
||||||
palette?: PaletteOutput;
|
palette?: PaletteOutput;
|
||||||
|
renderMode?: RenderMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface LensEmbeddableOutput extends EmbeddableOutput {
|
export interface LensEmbeddableOutput extends EmbeddableOutput {
|
||||||
|
@ -192,6 +194,7 @@ export class Embeddable
|
||||||
variables={input.palette ? { theme: { palette: input.palette } } : {}}
|
variables={input.palette ? { theme: { palette: input.palette } } : {}}
|
||||||
searchSessionId={this.input.searchSessionId}
|
searchSessionId={this.input.searchSessionId}
|
||||||
handleEvent={this.handleEvent}
|
handleEvent={this.handleEvent}
|
||||||
|
renderMode={input.renderMode}
|
||||||
/>,
|
/>,
|
||||||
domNode
|
domNode
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
ReactExpressionRendererType,
|
ReactExpressionRendererType,
|
||||||
} from 'src/plugins/expressions/public';
|
} from 'src/plugins/expressions/public';
|
||||||
import { ExecutionContextSearch } from 'src/plugins/data/public';
|
import { ExecutionContextSearch } from 'src/plugins/data/public';
|
||||||
|
import { RenderMode } from 'src/plugins/expressions';
|
||||||
import { getOriginalRequestErrorMessage } from '../error_helper';
|
import { getOriginalRequestErrorMessage } from '../error_helper';
|
||||||
|
|
||||||
export interface ExpressionWrapperProps {
|
export interface ExpressionWrapperProps {
|
||||||
|
@ -22,6 +23,7 @@ export interface ExpressionWrapperProps {
|
||||||
searchContext: ExecutionContextSearch;
|
searchContext: ExecutionContextSearch;
|
||||||
searchSessionId?: string;
|
searchSessionId?: string;
|
||||||
handleEvent: (event: ExpressionRendererEvent) => void;
|
handleEvent: (event: ExpressionRendererEvent) => void;
|
||||||
|
renderMode?: RenderMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExpressionWrapper({
|
export function ExpressionWrapper({
|
||||||
|
@ -31,6 +33,7 @@ export function ExpressionWrapper({
|
||||||
variables,
|
variables,
|
||||||
handleEvent,
|
handleEvent,
|
||||||
searchSessionId,
|
searchSessionId,
|
||||||
|
renderMode,
|
||||||
}: ExpressionWrapperProps) {
|
}: ExpressionWrapperProps) {
|
||||||
return (
|
return (
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
|
@ -57,6 +60,7 @@ export function ExpressionWrapper({
|
||||||
expression={expression}
|
expression={expression}
|
||||||
searchContext={searchContext}
|
searchContext={searchContext}
|
||||||
searchSessionId={searchSessionId}
|
searchSessionId={searchSessionId}
|
||||||
|
renderMode={renderMode}
|
||||||
renderError={(errorMessage, error) => (
|
renderError={(errorMessage, error) => (
|
||||||
<div data-test-subj="expression-renderer-error">
|
<div data-test-subj="expression-renderer-error">
|
||||||
<EuiFlexGroup direction="column" alignItems="center" justifyContent="center">
|
<EuiFlexGroup direction="column" alignItems="center" justifyContent="center">
|
||||||
|
|
|
@ -139,6 +139,7 @@ export const getPieRenderer = (dependencies: {
|
||||||
chartsThemeService={dependencies.chartsThemeService}
|
chartsThemeService={dependencies.chartsThemeService}
|
||||||
paletteService={dependencies.paletteService}
|
paletteService={dependencies.paletteService}
|
||||||
onClickValue={onClickValue}
|
onClickValue={onClickValue}
|
||||||
|
renderMode={handlers.getRenderMode()}
|
||||||
/>
|
/>
|
||||||
</I18nProvider>,
|
</I18nProvider>,
|
||||||
domNode,
|
domNode,
|
||||||
|
|
|
@ -70,6 +70,7 @@ describe('PieVisualization component', () => {
|
||||||
onClickValue: jest.fn(),
|
onClickValue: jest.fn(),
|
||||||
chartsThemeService,
|
chartsThemeService,
|
||||||
paletteService: chartPluginMock.createPaletteRegistry(),
|
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', () => {
|
test('it shows emptyPlaceholder for undefined grouped data', () => {
|
||||||
const defaultData = getDefaultArgs().data;
|
const defaultData = getDefaultArgs().data;
|
||||||
const emptyData: LensMultiTable = {
|
const emptyData: LensMultiTable = {
|
||||||
|
|
|
@ -20,7 +20,9 @@ import {
|
||||||
RecursivePartial,
|
RecursivePartial,
|
||||||
Position,
|
Position,
|
||||||
Settings,
|
Settings,
|
||||||
|
ElementClickListener,
|
||||||
} from '@elastic/charts';
|
} from '@elastic/charts';
|
||||||
|
import { RenderMode } from 'src/plugins/expressions';
|
||||||
import { FormatFactory, LensFilterEvent } from '../types';
|
import { FormatFactory, LensFilterEvent } from '../types';
|
||||||
import { VisualizationContainer } from '../visualization_container';
|
import { VisualizationContainer } from '../visualization_container';
|
||||||
import { CHART_NAMES, DEFAULT_PERCENT_DECIMALS } from './constants';
|
import { CHART_NAMES, DEFAULT_PERCENT_DECIMALS } from './constants';
|
||||||
|
@ -44,6 +46,7 @@ export function PieComponent(
|
||||||
chartsThemeService: ChartsPluginSetup['theme'];
|
chartsThemeService: ChartsPluginSetup['theme'];
|
||||||
paletteService: PaletteRegistry;
|
paletteService: PaletteRegistry;
|
||||||
onClickValue: (data: LensFilterEvent['data']) => void;
|
onClickValue: (data: LensFilterEvent['data']) => void;
|
||||||
|
renderMode: RenderMode;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const [firstTable] = Object.values(props.data.tables);
|
const [firstTable] = Object.values(props.data.tables);
|
||||||
|
@ -228,6 +231,12 @@ export function PieComponent(
|
||||||
</EuiText>
|
</EuiText>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onElementClickHandler: ElementClickListener = (args) => {
|
||||||
|
const context = getFilterContext(args[0][0] as LayerValue[], groups, firstTable);
|
||||||
|
|
||||||
|
onClickValue(desanitizeFilterContext(context));
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<VisualizationContainer
|
<VisualizationContainer
|
||||||
reportTitle={props.args.title}
|
reportTitle={props.args.title}
|
||||||
|
@ -248,11 +257,9 @@ export function PieComponent(
|
||||||
}
|
}
|
||||||
legendPosition={legendPosition || Position.Right}
|
legendPosition={legendPosition || Position.Right}
|
||||||
legendMaxDepth={nestedLegend ? undefined : 1 /* Color is based only on first layer */}
|
legendMaxDepth={nestedLegend ? undefined : 1 /* Color is based only on first layer */}
|
||||||
onElementClick={(args) => {
|
onElementClick={
|
||||||
const context = getFilterContext(args[0][0] as LayerValue[], groups, firstTable);
|
props.renderMode !== 'noInteractivity' ? onElementClickHandler : undefined
|
||||||
|
}
|
||||||
onClickValue(desanitizeFilterContext(context));
|
|
||||||
}}
|
|
||||||
theme={{
|
theme={{
|
||||||
...chartTheme,
|
...chartTheme,
|
||||||
background: {
|
background: {
|
||||||
|
|
|
@ -427,6 +427,7 @@ describe('xy_expression', () => {
|
||||||
args={args}
|
args={args}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -451,6 +452,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'line' }] }}
|
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'line' }] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -504,6 +506,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={undefined}
|
minInterval={undefined}
|
||||||
|
@ -541,6 +544,7 @@ describe('xy_expression', () => {
|
||||||
args={multiLayerArgs}
|
args={multiLayerArgs}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -578,6 +582,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -596,6 +601,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar' }] }}
|
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar' }] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -617,6 +623,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'area' }] }}
|
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'area' }] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -638,6 +645,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar_horizontal' }] }}
|
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar_horizontal' }] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -664,6 +672,7 @@ describe('xy_expression', () => {
|
||||||
args={args}
|
args={args}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -688,6 +697,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -773,6 +783,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
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', () => {
|
test('onElementClick returns correct context data', () => {
|
||||||
const geometry: GeometryValue = { x: 5, y: 1, accessor: 'y1', mark: null, datum: {} };
|
const geometry: GeometryValue = { x: 5, y: 1, accessor: 'y1', mark: null, datum: {} };
|
||||||
const series = {
|
const series = {
|
||||||
|
@ -825,6 +857,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
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', () => {
|
test('it renders stacked bar', () => {
|
||||||
const { data, args } = sampleArgs();
|
const { data, args } = sampleArgs();
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
|
@ -863,6 +917,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar_stacked' }] }}
|
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'bar_stacked' }] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -884,6 +939,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'area_stacked' }] }}
|
args={{ ...args, layers: [{ ...args.layers[0], seriesType: 'area_stacked' }] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -908,6 +964,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -941,6 +998,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -961,6 +1019,7 @@ describe('xy_expression', () => {
|
||||||
args={args}
|
args={args}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="CEST"
|
timeZone="CEST"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -987,6 +1046,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [firstLayer] }}
|
args={{ ...args, layers: [firstLayer] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1007,6 +1067,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [firstLayer] }}
|
args={{ ...args, layers: [firstLayer] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1030,6 +1091,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [firstLayer, secondLayer] }}
|
args={{ ...args, layers: [firstLayer, secondLayer] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1058,6 +1120,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1080,6 +1143,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1481,6 +1545,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [{ ...args.layers[0], xScaleType: 'ordinal' }] }}
|
args={{ ...args, layers: [{ ...args.layers[0], xScaleType: 'ordinal' }] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1501,6 +1566,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, layers: [{ ...args.layers[0], yScaleType: 'sqrt' }] }}
|
args={{ ...args, layers: [{ ...args.layers[0], yScaleType: 'sqrt' }] }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1521,6 +1587,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1544,6 +1611,7 @@ describe('xy_expression', () => {
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
onClickValue={onClickValue}
|
onClickValue={onClickValue}
|
||||||
onSelectRange={onSelectRange}
|
onSelectRange={onSelectRange}
|
||||||
/>
|
/>
|
||||||
|
@ -1563,6 +1631,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1598,6 +1667,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1631,6 +1701,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1664,6 +1735,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1697,6 +1769,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1797,6 +1870,7 @@ describe('xy_expression', () => {
|
||||||
args={args}
|
args={args}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1871,6 +1945,7 @@ describe('xy_expression', () => {
|
||||||
args={args}
|
args={args}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1943,6 +2018,7 @@ describe('xy_expression', () => {
|
||||||
args={args}
|
args={args}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1967,6 +2043,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -1990,6 +2067,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -2013,6 +2091,7 @@ describe('xy_expression', () => {
|
||||||
}}
|
}}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -2048,6 +2127,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args, fittingFunction: 'Carry' }}
|
args={{ ...args, fittingFunction: 'Carry' }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -2075,6 +2155,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -2097,6 +2178,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -2124,6 +2206,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
@ -2157,6 +2240,7 @@ describe('xy_expression', () => {
|
||||||
args={{ ...args }}
|
args={{ ...args }}
|
||||||
formatFactory={getFormatSpy}
|
formatFactory={getFormatSpy}
|
||||||
timeZone="UTC"
|
timeZone="UTC"
|
||||||
|
renderMode="display"
|
||||||
chartsThemeService={chartsThemeService}
|
chartsThemeService={chartsThemeService}
|
||||||
paletteService={paletteService}
|
paletteService={paletteService}
|
||||||
minInterval={50}
|
minInterval={50}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import {
|
||||||
StackMode,
|
StackMode,
|
||||||
VerticalAlignment,
|
VerticalAlignment,
|
||||||
HorizontalAlignment,
|
HorizontalAlignment,
|
||||||
|
ElementClickListener,
|
||||||
|
BrushEndListener,
|
||||||
} from '@elastic/charts';
|
} from '@elastic/charts';
|
||||||
import { I18nProvider } from '@kbn/i18n/react';
|
import { I18nProvider } from '@kbn/i18n/react';
|
||||||
import {
|
import {
|
||||||
|
@ -31,6 +33,7 @@ import {
|
||||||
} from 'src/plugins/expressions/public';
|
} from 'src/plugins/expressions/public';
|
||||||
import { IconType } from '@elastic/eui';
|
import { IconType } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import { RenderMode } from 'src/plugins/expressions';
|
||||||
import {
|
import {
|
||||||
LensMultiTable,
|
LensMultiTable,
|
||||||
FormatFactory,
|
FormatFactory,
|
||||||
|
@ -81,6 +84,7 @@ type XYChartRenderProps = XYChartProps & {
|
||||||
minInterval: number | undefined;
|
minInterval: number | undefined;
|
||||||
onClickValue: (data: LensFilterEvent['data']) => void;
|
onClickValue: (data: LensFilterEvent['data']) => void;
|
||||||
onSelectRange: (data: LensBrushEvent['data']) => void;
|
onSelectRange: (data: LensBrushEvent['data']) => void;
|
||||||
|
renderMode: RenderMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const xyChart: ExpressionFunctionDefinition<
|
export const xyChart: ExpressionFunctionDefinition<
|
||||||
|
@ -235,6 +239,7 @@ export const getXyChartRenderer = (dependencies: {
|
||||||
minInterval={await calculateMinInterval(config, dependencies.getIntervalByColumn)}
|
minInterval={await calculateMinInterval(config, dependencies.getIntervalByColumn)}
|
||||||
onClickValue={onClickValue}
|
onClickValue={onClickValue}
|
||||||
onSelectRange={onSelectRange}
|
onSelectRange={onSelectRange}
|
||||||
|
renderMode={handlers.getRenderMode()}
|
||||||
/>
|
/>
|
||||||
</I18nProvider>,
|
</I18nProvider>,
|
||||||
domNode,
|
domNode,
|
||||||
|
@ -303,6 +308,7 @@ export function XYChart({
|
||||||
minInterval,
|
minInterval,
|
||||||
onClickValue,
|
onClickValue,
|
||||||
onSelectRange,
|
onSelectRange,
|
||||||
|
renderMode,
|
||||||
}: XYChartRenderProps) {
|
}: XYChartRenderProps) {
|
||||||
const { legend, layers, fittingFunction, gridlinesVisibilitySettings, valueLabels } = args;
|
const { legend, layers, fittingFunction, gridlinesVisibilitySettings, valueLabels } = args;
|
||||||
const chartTheme = chartsThemeService.useChartsTheme();
|
const chartTheme = chartsThemeService.useChartsTheme();
|
||||||
|
@ -415,6 +421,87 @@ export function XYChart({
|
||||||
|
|
||||||
const colorAssignments = getColorAssignments(args.layers, data, formatFactory);
|
const colorAssignments = getColorAssignments(args.layers, data, formatFactory);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
const layer = filteredLayers.find((l) =>
|
||||||
|
xySeries.seriesKeys.some((key: string | number) => l.accessors.includes(key.toString()))
|
||||||
|
);
|
||||||
|
if (!layer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const table = data.tables[layer.layerId];
|
||||||
|
|
||||||
|
const points = [
|
||||||
|
{
|
||||||
|
row: table.rows.findIndex((row) => {
|
||||||
|
if (layer.xAccessor) {
|
||||||
|
if (layersAlreadyFormatted[layer.xAccessor]) {
|
||||||
|
// stringify the value to compare with the chart value
|
||||||
|
return xAxisFormatter.convert(row[layer.xAccessor]) === xyGeometry.x;
|
||||||
|
}
|
||||||
|
return row[layer.xAccessor] === xyGeometry.x;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
column: table.columns.findIndex((col) => col.id === layer.xAccessor),
|
||||||
|
value: xyGeometry.x,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (xySeries.seriesKeys.length > 1) {
|
||||||
|
const pointValue = xySeries.seriesKeys[0];
|
||||||
|
|
||||||
|
points.push({
|
||||||
|
row: table.rows.findIndex(
|
||||||
|
(row) => layer.splitAccessor && row[layer.splitAccessor] === pointValue
|
||||||
|
),
|
||||||
|
column: table.columns.findIndex((col) => col.id === layer.splitAccessor),
|
||||||
|
value: pointValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const xAxisFieldName = table.columns.find((el) => el.id === layer.xAccessor)?.meta?.field;
|
||||||
|
const timeFieldName = xDomain && xAxisFieldName;
|
||||||
|
|
||||||
|
const context: LensFilterEvent['data'] = {
|
||||||
|
data: points.map((point) => ({
|
||||||
|
row: point.row,
|
||||||
|
column: point.column,
|
||||||
|
value: point.value,
|
||||||
|
table,
|
||||||
|
})),
|
||||||
|
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 (
|
return (
|
||||||
<Chart>
|
<Chart>
|
||||||
<Settings
|
<Settings
|
||||||
|
@ -441,89 +528,8 @@ export function XYChart({
|
||||||
}}
|
}}
|
||||||
rotation={shouldRotate ? 90 : 0}
|
rotation={shouldRotate ? 90 : 0}
|
||||||
xDomain={xDomain}
|
xDomain={xDomain}
|
||||||
onBrushEnd={({ x }) => {
|
onBrushEnd={renderMode !== 'noInteractivity' ? brushHandler : undefined}
|
||||||
if (!x) {
|
onElementClick={renderMode !== 'noInteractivity' ? clickHandler : undefined}
|
||||||
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]]) => {
|
|
||||||
// for xyChart series is always XYChartSeriesIdentifier and geometry is always type of GeometryValue
|
|
||||||
const xySeries = series as XYChartSeriesIdentifier;
|
|
||||||
const xyGeometry = geometry as GeometryValue;
|
|
||||||
|
|
||||||
const layer = filteredLayers.find((l) =>
|
|
||||||
xySeries.seriesKeys.some((key: string | number) => l.accessors.includes(key.toString()))
|
|
||||||
);
|
|
||||||
if (!layer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const table = data.tables[layer.layerId];
|
|
||||||
|
|
||||||
const points = [
|
|
||||||
{
|
|
||||||
row: table.rows.findIndex((row) => {
|
|
||||||
if (layer.xAccessor) {
|
|
||||||
if (layersAlreadyFormatted[layer.xAccessor]) {
|
|
||||||
// stringify the value to compare with the chart value
|
|
||||||
return xAxisFormatter.convert(row[layer.xAccessor]) === xyGeometry.x;
|
|
||||||
}
|
|
||||||
return row[layer.xAccessor] === xyGeometry.x;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
column: table.columns.findIndex((col) => col.id === layer.xAccessor),
|
|
||||||
value: xyGeometry.x,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
if (xySeries.seriesKeys.length > 1) {
|
|
||||||
const pointValue = xySeries.seriesKeys[0];
|
|
||||||
|
|
||||||
points.push({
|
|
||||||
row: table.rows.findIndex(
|
|
||||||
(row) => layer.splitAccessor && row[layer.splitAccessor] === pointValue
|
|
||||||
),
|
|
||||||
column: table.columns.findIndex((col) => col.id === layer.splitAccessor),
|
|
||||||
value: pointValue,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const xAxisFieldName = table.columns.find((el) => el.id === layer.xAccessor)?.meta?.field;
|
|
||||||
const timeFieldName = xDomain && xAxisFieldName;
|
|
||||||
|
|
||||||
const context: LensFilterEvent['data'] = {
|
|
||||||
data: points.map((point) => ({
|
|
||||||
row: point.row,
|
|
||||||
column: point.column,
|
|
||||||
value: point.value,
|
|
||||||
table,
|
|
||||||
})),
|
|
||||||
timeFieldName,
|
|
||||||
};
|
|
||||||
onClickValue(desanitizeFilterContext(context));
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Axis
|
<Axis
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue