mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Conflicts: # src/legacy/core_plugins/expressions/public/np_ready/public/loader.test.ts # src/legacy/core_plugins/expressions/public/np_ready/public/loader.ts
This commit is contained in:
parent
1f6fd545de
commit
d5c1c12d78
7 changed files with 61 additions and 14 deletions
|
@ -26,6 +26,7 @@ import { IExpressionLoader, ExpressionLoader } from './loader';
|
|||
// dom element which is provided by the component itself
|
||||
export interface ExpressionRendererProps extends IExpressionLoaderParams {
|
||||
className: string;
|
||||
dataAttrs?: string[];
|
||||
expression: string | ExpressionAST;
|
||||
/**
|
||||
* If an element is specified, but the response of the expression run can't be rendered
|
||||
|
@ -39,6 +40,7 @@ export type ExpressionRenderer = React.FC<ExpressionRendererProps>;
|
|||
|
||||
export const createRenderer = (loader: IExpressionLoader): ExpressionRenderer => ({
|
||||
className,
|
||||
dataAttrs,
|
||||
expression,
|
||||
onRenderFailure,
|
||||
...options
|
||||
|
@ -68,5 +70,5 @@ export const createRenderer = (loader: IExpressionLoader): ExpressionRenderer =>
|
|||
mountpoint.current,
|
||||
]);
|
||||
|
||||
return <div className={className} ref={mountpoint} />;
|
||||
return <div {...dataAttrs} className={className} ref={mountpoint} />;
|
||||
};
|
||||
|
|
|
@ -86,6 +86,22 @@ describe('ExpressionDataHandler', () => {
|
|||
expect(response).toEqual({ type: 'render', as: 'test' });
|
||||
});
|
||||
|
||||
it('emits on loading$ when starting to load', async () => {
|
||||
const expressionLoader = new ExpressionLoader(element, expressionString, {});
|
||||
let loadingPromise = expressionLoader.loading$.pipe(first()).toPromise();
|
||||
expressionLoader.update('test');
|
||||
let response = await loadingPromise;
|
||||
expect(response).toBeUndefined();
|
||||
loadingPromise = expressionLoader.loading$.pipe(first()).toPromise();
|
||||
expressionLoader.update('');
|
||||
response = await loadingPromise;
|
||||
expect(response).toBeUndefined();
|
||||
loadingPromise = expressionLoader.loading$.pipe(first()).toPromise();
|
||||
expressionLoader.update();
|
||||
response = await loadingPromise;
|
||||
expect(response).toBeUndefined();
|
||||
});
|
||||
|
||||
it('emits on render$ when rendering is done', async () => {
|
||||
const expressionLoader = new ExpressionLoader(element, expressionString, {});
|
||||
const response = await expressionLoader.render$.pipe(first()).toPromise();
|
||||
|
|
|
@ -30,11 +30,14 @@ export class ExpressionLoader {
|
|||
update$: ExpressionRenderHandler['update$'];
|
||||
render$: ExpressionRenderHandler['render$'];
|
||||
events$: ExpressionRenderHandler['events$'];
|
||||
loading$: Observable<void>;
|
||||
|
||||
private dataHandler!: ExpressionDataHandler;
|
||||
private renderHandler: ExpressionRenderHandler;
|
||||
private dataSubject: Subject<Data>;
|
||||
private loadingSubject: Subject<void>;
|
||||
private data: Data;
|
||||
private params: IExpressionLoaderParams;
|
||||
|
||||
constructor(
|
||||
element: HTMLElement,
|
||||
|
@ -44,6 +47,9 @@ export class ExpressionLoader {
|
|||
this.dataSubject = new Subject();
|
||||
this.data$ = this.dataSubject.asObservable().pipe(share());
|
||||
|
||||
this.loadingSubject = new Subject();
|
||||
this.loading$ = this.loadingSubject.asObservable().pipe(share());
|
||||
|
||||
this.renderHandler = new ExpressionRenderHandler(element);
|
||||
this.render$ = this.renderHandler.render$;
|
||||
this.update$ = this.renderHandler.update$;
|
||||
|
@ -57,8 +63,14 @@ export class ExpressionLoader {
|
|||
this.render(data);
|
||||
});
|
||||
|
||||
this.params = {
|
||||
searchContext: { type: 'kibana_context' },
|
||||
extraHandlers: params.extraHandlers,
|
||||
};
|
||||
|
||||
this.dataHandler = new ExpressionDataHandler(expression, params);
|
||||
this.dataHandler.getData().then(data => {
|
||||
this.data = data;
|
||||
this.dataSubject.next(data);
|
||||
});
|
||||
}
|
||||
|
@ -91,11 +103,19 @@ export class ExpressionLoader {
|
|||
return this.dataHandler.inspect();
|
||||
}
|
||||
|
||||
update(expression: string | ExpressionAST, params: IExpressionLoaderParams): Promise<RenderId> {
|
||||
update(expression?: string | ExpressionAST, params?: IExpressionLoaderParams): Promise<RenderId> {
|
||||
const promise = this.render$.pipe(first()).toPromise();
|
||||
if (params && params.searchContext && this.params.searchContext) {
|
||||
this.params.searchContext = _.defaults(
|
||||
{},
|
||||
params.searchContext,
|
||||
this.params.searchContext
|
||||
) as any;
|
||||
}
|
||||
|
||||
if (expression !== null) {
|
||||
this.execute(expression, params);
|
||||
this.loadingSubject.next();
|
||||
if (expression) {
|
||||
this.execute(expression, this.params);
|
||||
} else {
|
||||
this.render(this.data);
|
||||
}
|
||||
|
@ -110,13 +130,13 @@ export class ExpressionLoader {
|
|||
this.dataHandler.cancel();
|
||||
}
|
||||
this.dataHandler = new ExpressionDataHandler(expression, params);
|
||||
const data = await this.dataHandler.getData();
|
||||
this.dataSubject.next(data);
|
||||
return data;
|
||||
this.data = await this.dataHandler.getData();
|
||||
this.dataSubject.next(this.data);
|
||||
return this.data;
|
||||
};
|
||||
|
||||
private async render(data: Data): Promise<RenderId> {
|
||||
return this.renderHandler.render(data);
|
||||
return this.renderHandler.render(data, this.params.extraHandlers);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,9 @@ function createExpressionsStartMock(): ExpressionsStart {
|
|||
execute: jest.fn(),
|
||||
loader: jest.fn(),
|
||||
render: jest.fn(),
|
||||
ExpressionRenderHandler: jest.fn(),
|
||||
ExpressionDataHandler: jest.fn(),
|
||||
ExpressionLoader: jest.fn(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,9 @@ import {
|
|||
import { IInterpreter } from './types';
|
||||
import { setInterpreter, setInspector, setRenderersRegistry } from './services';
|
||||
import { createRenderer } from './expression_renderer';
|
||||
import { loader } from './loader';
|
||||
import { execute } from './execute';
|
||||
import { render } from './render';
|
||||
import { ExpressionLoader, loader } from './loader';
|
||||
import { ExpressionDataHandler, execute } from './execute';
|
||||
import { ExpressionRenderHandler, render } from './render';
|
||||
|
||||
export interface ExpressionsSetupDeps {
|
||||
inspector: InspectorSetup;
|
||||
|
@ -84,6 +84,9 @@ export class ExpressionsPublicPlugin
|
|||
execute,
|
||||
render,
|
||||
loader,
|
||||
ExpressionDataHandler,
|
||||
ExpressionRenderHandler,
|
||||
ExpressionLoader,
|
||||
ExpressionRenderer,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import { share, first } from 'rxjs/operators';
|
|||
import { event, RenderId, Data, IInterpreterRenderHandlers } from './types';
|
||||
import { getRenderersRegistry } from './services';
|
||||
|
||||
export type IExpressionRendererExtraHandlers = Record<string, any>;
|
||||
|
||||
export class ExpressionRenderHandler {
|
||||
render$: Observable<RenderId>;
|
||||
update$: Observable<any>;
|
||||
|
@ -65,8 +67,8 @@ export class ExpressionRenderHandler {
|
|||
};
|
||||
}
|
||||
|
||||
render = async (data: Data) => {
|
||||
if (data.type !== 'render' || !data.as) {
|
||||
render = async (data: Data, extraHandlers: IExpressionRendererExtraHandlers = {}) => {
|
||||
if (!data || data.type !== 'render' || !data.as) {
|
||||
throw new Error('invalid data provided to expression renderer');
|
||||
}
|
||||
|
||||
|
@ -78,7 +80,7 @@ export class ExpressionRenderHandler {
|
|||
|
||||
getRenderersRegistry()
|
||||
.get(data.as)
|
||||
.render(this.element, data.value, this.handlers);
|
||||
.render(this.element, data.value, { ...this.handlers, ...extraHandlers });
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
|
|
@ -46,6 +46,7 @@ export interface IExpressionLoaderParams {
|
|||
disableCaching?: boolean;
|
||||
customFunctions?: [];
|
||||
customRenderers?: [];
|
||||
extraHandlers?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface IInterpreterHandlers {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue