Skip to content

Commit ffab945

Browse files
Merge branch 'master' into logs-ui-ml-setup-add-dataset-filter
2 parents 0ab8fa4 + 4d19323 commit ffab945

File tree

4 files changed

+56
-5
lines changed

4 files changed

+56
-5
lines changed

src/plugins/expressions/public/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export {
3737
ReactExpressionRendererProps,
3838
ReactExpressionRendererType,
3939
} from './react_expression_renderer';
40-
export { ExpressionRenderHandler } from './render';
40+
export { ExpressionRenderHandler, ExpressionRendererEvent } from './render';
4141
export {
4242
AnyExpressionFunctionDefinition,
4343
AnyExpressionTypeDefinition,

src/plugins/expressions/public/react_expression_renderer.test.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { ExpressionLoader } from './loader';
2626
import { mount } from 'enzyme';
2727
import { EuiProgress } from '@elastic/eui';
2828
import { RenderErrorHandlerFnType } from './types';
29+
import { ExpressionRendererEvent } from './render';
2930

3031
jest.mock('./loader', () => {
3132
return {
@@ -135,4 +136,44 @@ describe('ExpressionRenderer', () => {
135136
expect(instance.find(EuiProgress)).toHaveLength(0);
136137
expect(instance.find('[data-test-subj="custom-error"]')).toHaveLength(0);
137138
});
139+
140+
it('should fire onEvent prop on every events$ observable emission in loader', () => {
141+
const dataSubject = new Subject();
142+
const data$ = dataSubject.asObservable().pipe(share());
143+
const renderSubject = new Subject();
144+
const render$ = renderSubject.asObservable().pipe(share());
145+
const loadingSubject = new Subject();
146+
const loading$ = loadingSubject.asObservable().pipe(share());
147+
const eventsSubject = new Subject<ExpressionRendererEvent>();
148+
const events$ = eventsSubject.asObservable().pipe(share());
149+
150+
const onEvent = jest.fn();
151+
const event: ExpressionRendererEvent = {
152+
name: 'foo',
153+
data: {
154+
bar: 'baz',
155+
},
156+
};
157+
158+
(ExpressionLoader as jest.Mock).mockImplementation(() => {
159+
return {
160+
render$,
161+
data$,
162+
loading$,
163+
events$,
164+
update: jest.fn(),
165+
};
166+
});
167+
168+
mount(<ReactExpressionRenderer expression="" onEvent={onEvent} />);
169+
170+
expect(onEvent).toHaveBeenCalledTimes(0);
171+
172+
act(() => {
173+
eventsSubject.next(event);
174+
});
175+
176+
expect(onEvent).toHaveBeenCalledTimes(1);
177+
expect(onEvent.mock.calls[0][0]).toBe(event);
178+
});
138179
});

src/plugins/expressions/public/react_expression_renderer.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import theme from '@elastic/eui/dist/eui_theme_light.json';
2727
import { IExpressionLoaderParams, RenderError } from './types';
2828
import { ExpressionAstExpression, IInterpreterRenderHandlers } from '../common';
2929
import { ExpressionLoader } from './loader';
30+
import { ExpressionRendererEvent } from './render';
3031

3132
// Accept all options of the runner as props except for the
3233
// dom element which is provided by the component itself
@@ -36,6 +37,7 @@ export interface ReactExpressionRendererProps extends IExpressionLoaderParams {
3637
expression: string | ExpressionAstExpression;
3738
renderError?: (error?: string | null) => React.ReactElement | React.ReactElement[];
3839
padding?: 'xs' | 's' | 'm' | 'l' | 'xl';
40+
onEvent?: (event: ExpressionRendererEvent) => void;
3941
}
4042

4143
export type ReactExpressionRendererType = React.ComponentType<ReactExpressionRendererProps>;
@@ -60,6 +62,7 @@ export const ReactExpressionRenderer = ({
6062
padding,
6163
renderError,
6264
expression,
65+
onEvent,
6366
...expressionLoaderOptions
6467
}: ReactExpressionRendererProps) => {
6568
const mountpoint: React.MutableRefObject<null | HTMLDivElement> = useRef(null);
@@ -99,6 +102,13 @@ export const ReactExpressionRenderer = ({
99102
}
100103
: expressionLoaderOptions.onRenderError,
101104
});
105+
if (onEvent) {
106+
subs.push(
107+
expressionLoaderRef.current.events$.subscribe(event => {
108+
onEvent(event);
109+
})
110+
);
111+
}
102112
subs.push(
103113
expressionLoaderRef.current.loading$.subscribe(() => {
104114
hasHandledErrorRef.current = false;
@@ -123,7 +133,7 @@ export const ReactExpressionRenderer = ({
123133

124134
errorRenderHandlerRef.current = null;
125135
};
126-
}, [hasCustomRenderErrorHandler]);
136+
}, [hasCustomRenderErrorHandler, onEvent]);
127137

128138
// Re-fetch data automatically when the inputs change
129139
useShallowCompareEffect(

src/plugins/expressions/public/render.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export interface ExpressionRenderHandlerParams {
3232
onRenderError: RenderErrorHandlerFnType;
3333
}
3434

35-
interface Event {
35+
export interface ExpressionRendererEvent {
3636
name: string;
3737
data: any;
3838
}
@@ -45,7 +45,7 @@ interface UpdateValue {
4545
export class ExpressionRenderHandler {
4646
render$: Observable<number>;
4747
update$: Observable<UpdateValue | null>;
48-
events$: Observable<Event>;
48+
events$: Observable<ExpressionRendererEvent>;
4949

5050
private element: HTMLElement;
5151
private destroyFn?: any;
@@ -63,7 +63,7 @@ export class ExpressionRenderHandler {
6363
this.element = element;
6464

6565
this.eventsSubject = new Rx.Subject();
66-
this.events$ = this.eventsSubject.asObservable() as Observable<Event>;
66+
this.events$ = this.eventsSubject.asObservable() as Observable<ExpressionRendererEvent>;
6767

6868
this.onRenderError = onRenderError || defaultRenderErrorHandler;
6969

0 commit comments

Comments
 (0)