Skip to content

Commit

Permalink
Expression: Add render mode and use it for canvas interactivity (#83559
Browse files Browse the repository at this point in the history
…) (#84259)
  • Loading branch information
flash1293 authored Nov 25, 2020
1 parent 096238c commit 79fa876
Show file tree
Hide file tree
Showing 26 changed files with 344 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ 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

| Parameter | Type | Description |
| --- | --- | --- |
| element | <code>HTMLElement</code> | |
| { onRenderError } | <code>Partial&lt;ExpressionRenderHandlerParams&gt;</code> | |
| { onRenderError, renderMode } | <code>Partial&lt;ExpressionRenderHandlerParams&gt;</code> | |

Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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> | |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [IExpressionLoaderParams](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.md) &gt; [renderMode](./kibana-plugin-plugins-expressions-public.iexpressionloaderparams.rendermode.md)

## IExpressionLoaderParams.renderMode property

<b>Signature:</b>

```typescript
renderMode?: RenderMode;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) &gt; [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.md) &gt; [getRenderMode](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.getrendermode.md)

## IInterpreterRenderHandlers.getRenderMode property

<b>Signature:</b>

```typescript
getRenderMode: () => RenderMode;
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface IInterpreterRenderHandlers
| --- | --- | --- |
| [done](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.done.md) | <code>() =&gt; void</code> | Done increments the number of rendering successes |
| [event](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.event.md) | <code>(event: any) =&gt; void</code> | |
| [getRenderMode](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.getrendermode.md) | <code>() =&gt; RenderMode</code> | |
| [onDestroy](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.ondestroy.md) | <code>(fn: () =&gt; void) =&gt; void</code> | |
| [reload](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.reload.md) | <code>() =&gt; void</code> | |
| [uiState](./kibana-plugin-plugins-expressions-public.iinterpreterrenderhandlers.uistate.md) | <code>PersistedState</code> | |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-expressions-server](./kibana-plugin-plugins-expressions-server.md) &gt; [IInterpreterRenderHandlers](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.md) &gt; [getRenderMode](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.getrendermode.md)

## IInterpreterRenderHandlers.getRenderMode property

<b>Signature:</b>

```typescript
getRenderMode: () => RenderMode;
```
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface IInterpreterRenderHandlers
| --- | --- | --- |
| [done](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.done.md) | <code>() =&gt; void</code> | Done increments the number of rendering successes |
| [event](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.event.md) | <code>(event: any) =&gt; void</code> | |
| [getRenderMode](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.getrendermode.md) | <code>() =&gt; RenderMode</code> | |
| [onDestroy](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.ondestroy.md) | <code>(fn: () =&gt; void) =&gt; void</code> | |
| [reload](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.reload.md) | <code>() =&gt; void</code> | |
| [uiState](./kibana-plugin-plugins-expressions-server.iinterpreterrenderhandlers.uistate.md) | <code>PersistedState</code> | |
Expand Down
13 changes: 13 additions & 0 deletions src/plugins/expressions/common/expression_renderers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -70,5 +82,6 @@ export interface IInterpreterRenderHandlers {
reload: () => void;
update: (params: any) => void;
event: (event: any) => void;
getRenderMode: () => RenderMode;
uiState?: PersistedState;
}
28 changes: 26 additions & 2 deletions src/plugins/expressions/public/loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
},
},
Expand All @@ -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],
}),
Expand Down Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions src/plugins/expressions/public/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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$;
Expand Down
8 changes: 7 additions & 1 deletion src/plugins/expressions/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -909,6 +913,8 @@ export interface IInterpreterRenderHandlers {
// (undocumented)
event: (event: any) => void;
// (undocumented)
getRenderMode: () => RenderMode;
// (undocumented)
onDestroy: (fn: () => void) => void;
// (undocumented)
reload: () => void;
Expand Down
8 changes: 6 additions & 2 deletions src/plugins/expressions/public/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ 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';

export type IExpressionRendererExtraHandlers = Record<string, any>;

export interface ExpressionRenderHandlerParams {
onRenderError: RenderErrorHandlerFnType;
renderMode: RenderMode;
}

export interface ExpressionRendererEvent {
Expand Down Expand Up @@ -58,7 +59,7 @@ export class ExpressionRenderHandler {

constructor(
element: HTMLElement,
{ onRenderError }: Partial<ExpressionRenderHandlerParams> = {}
{ onRenderError, renderMode }: Partial<ExpressionRenderHandlerParams> = {}
) {
this.element = element;

Expand Down Expand Up @@ -92,6 +93,9 @@ export class ExpressionRenderHandler {
event: (data) => {
this.eventsSubject.next(data);
},
getRenderMode: () => {
return renderMode || 'display';
},
};
}

Expand Down
2 changes: 2 additions & 0 deletions src/plugins/expressions/public/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
ExpressionValue,
ExpressionsService,
SerializableState,
RenderMode,
} from '../../common';

/**
Expand Down Expand Up @@ -54,6 +55,7 @@ export interface IExpressionLoaderParams {
inspectorAdapters?: Adapters;
onRenderError?: RenderErrorHandlerFnType;
searchSessionId?: string;
renderMode?: RenderMode;
}

export interface ExpressionRenderError extends Error {
Expand Down
4 changes: 4 additions & 0 deletions src/plugins/expressions/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/canvas/public/lib/create_handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export const createHandlers = (): RendererHandlers => ({
getFilter() {
return '';
},
getRenderMode() {
return 'display';
},
onComplete(fn: () => void) {
this.done = fn;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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' };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -22,6 +23,7 @@ export interface ExpressionWrapperProps {
searchContext: ExecutionContextSearch;
searchSessionId?: string;
handleEvent: (event: ExpressionRendererEvent) => void;
renderMode?: RenderMode;
}

export function ExpressionWrapper({
Expand All @@ -31,6 +33,7 @@ export function ExpressionWrapper({
variables,
handleEvent,
searchSessionId,
renderMode,
}: ExpressionWrapperProps) {
return (
<I18nProvider>
Expand All @@ -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">
Expand Down
Loading

0 comments on commit 79fa876

Please sign in to comment.