Skip to content

Commit 28a726f

Browse files
Vega visualization renderer (#81606)
* Create vega to_ast function * Create a custom vega renderer * Fix sass error Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
1 parent db92edf commit 28a726f

22 files changed

+354
-106
lines changed

src/plugins/vis_type_vega/public/_vega_vis.scss renamed to src/plugins/vis_type_vega/public/components/vega_vis.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
.vgaVis__wrapper {
2+
@include euiScrollBar;
3+
4+
display: flex;
5+
flex: 1 1 0;
6+
overflow: auto;
7+
}
8+
19
.vgaVis {
210
display: flex;
311
flex: 1 1 100%;
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import React, { useEffect, useMemo, useRef } from 'react';
21+
import { EuiResizeObserver } from '@elastic/eui';
22+
import { throttle } from 'lodash';
23+
24+
import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
25+
import { createVegaVisualization } from '../vega_visualization';
26+
import { VegaVisualizationDependencies } from '../plugin';
27+
import { VegaParser } from '../data_model/vega_parser';
28+
29+
import './vega_vis.scss';
30+
31+
interface VegaVisComponentProps {
32+
deps: VegaVisualizationDependencies;
33+
fireEvent: IInterpreterRenderHandlers['event'];
34+
renderComplete: () => void;
35+
visData: VegaParser;
36+
}
37+
38+
type VegaVisController = InstanceType<ReturnType<typeof createVegaVisualization>>;
39+
40+
const VegaVisComponent = ({ visData, fireEvent, renderComplete, deps }: VegaVisComponentProps) => {
41+
const chartDiv = useRef<HTMLDivElement>(null);
42+
const visController = useRef<VegaVisController | null>(null);
43+
44+
useEffect(() => {
45+
if (chartDiv.current) {
46+
const VegaVis = createVegaVisualization(deps);
47+
visController.current = new VegaVis(chartDiv.current, fireEvent);
48+
}
49+
50+
return () => {
51+
visController.current?.destroy();
52+
visController.current = null;
53+
};
54+
}, [deps, fireEvent]);
55+
56+
useEffect(() => {
57+
if (visController.current) {
58+
visController.current.render(visData).then(renderComplete);
59+
}
60+
}, [visData, renderComplete]);
61+
62+
const updateChartSize = useMemo(
63+
() =>
64+
throttle(() => {
65+
if (visController.current) {
66+
visController.current.render(visData).then(renderComplete);
67+
}
68+
}, 300),
69+
[renderComplete, visData]
70+
);
71+
72+
return (
73+
<EuiResizeObserver onResize={updateChartSize}>
74+
{(resizeRef) => (
75+
<div className="vgaVis__wrapper" ref={resizeRef}>
76+
<div ref={chartDiv} />
77+
</div>
78+
)}
79+
</EuiResizeObserver>
80+
);
81+
};
82+
83+
// default export required for React.Lazy
84+
// eslint-disable-next-line import/no-default-export
85+
export { VegaVisComponent as default };

src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import { VisParams } from '../vega_fn';
3030
import { VegaHelpMenu } from './vega_help_menu';
3131
import { VegaActionsMenu } from './vega_actions_menu';
3232

33+
import './vega_editor.scss';
34+
3335
const aceOptions = {
3436
maxLines: Infinity,
3537
highlightActiveLine: false,
@@ -102,4 +104,6 @@ function VegaVisEditor({ stateParams, setValue }: VisOptionsProps<VisParams>) {
102104
);
103105
}
104106

105-
export { VegaVisEditor };
107+
// default export required for React.Lazy
108+
// eslint-disable-next-line import/no-default-export
109+
export { VegaVisEditor as default };
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import React, { lazy } from 'react';
21+
22+
import { VisOptionsProps } from 'src/plugins/vis_default_editor/public';
23+
import { VisParams } from '../vega_fn';
24+
25+
const VegaVisEditor = lazy(() => import('./vega_vis_editor'));
26+
27+
export const VegaVisEditorComponent = (props: VisOptionsProps<VisParams>) => (
28+
<VegaVisEditor {...props} />
29+
);

src/plugins/vis_type_vega/public/index.scss

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/plugins/vis_type_vega/public/plugin.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ import {
3535
import { createVegaFn } from './vega_fn';
3636
import { createVegaTypeDefinition } from './vega_type';
3737
import { IServiceSettings } from '../../maps_legacy/public';
38-
import './index.scss';
3938
import { ConfigSchema } from '../config';
4039

4140
import { getVegaInspectorView } from './vega_inspector';
41+
import { getVegaVisRenderer } from './vega_vis_renderer';
4242

4343
/** @internal */
4444
export interface VegaVisualizationDependencies {
@@ -93,6 +93,7 @@ export class VegaPlugin implements Plugin<Promise<void>, void> {
9393
inspector.registerView(getVegaInspectorView({ uiSettings: core.uiSettings }));
9494

9595
expressions.registerFunction(() => createVegaFn(visualizationDependencies));
96+
expressions.registerRenderer(getVegaVisRenderer(visualizationDependencies));
9697

9798
visualizations.createBaseVisualization(createVegaTypeDefinition(visualizationDependencies));
9899
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { buildExpression, buildExpressionFunction } from '../../expressions/public';
21+
import { Vis } from '../../visualizations/public';
22+
import { VegaExpressionFunctionDefinition, VisParams } from './vega_fn';
23+
24+
export const toExpressionAst = (vis: Vis<VisParams>) => {
25+
const vega = buildExpressionFunction<VegaExpressionFunctionDefinition>('vega', {
26+
spec: vis.params.spec,
27+
});
28+
29+
const ast = buildExpression([vega]);
30+
31+
return ast.toAst();
32+
};

src/plugins/vis_type_vega/public/vega_fn.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,23 @@ interface Arguments {
4040

4141
export type VisParams = Required<Arguments>;
4242

43-
interface RenderValue {
43+
export interface RenderValue {
4444
visData: VegaParser;
4545
visType: 'vega';
4646
visConfig: VisParams;
4747
}
4848

49-
export const createVegaFn = (
50-
dependencies: VegaVisualizationDependencies
51-
): ExpressionFunctionDefinition<
49+
export type VegaExpressionFunctionDefinition = ExpressionFunctionDefinition<
5250
'vega',
5351
Input,
5452
Arguments,
5553
Output,
5654
ExecutionContext<VegaInspectorAdapters>
57-
> => ({
55+
>;
56+
57+
export const createVegaFn = (
58+
dependencies: VegaVisualizationDependencies
59+
): VegaExpressionFunctionDefinition => ({
5860
name: 'vega',
5961
type: 'render',
6062
inputTypes: ['kibana_context', 'null'],
@@ -80,7 +82,7 @@ export const createVegaFn = (
8082

8183
return {
8284
type: 'render',
83-
as: 'visualization',
85+
as: 'vega_vis',
8486
value: {
8587
visData: response,
8688
visType: 'vega',

src/plugins/vis_type_vega/public/vega_inspector/vega_data_inspector.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const specLabel = i18n.translate('visTypeVega.inspector.specLabel', {
4141
defaultMessage: 'Spec',
4242
});
4343

44-
export const VegaDataInspector = ({ adapters }: VegaDataInspectorProps) => {
44+
const VegaDataInspector = ({ adapters }: VegaDataInspectorProps) => {
4545
const tabs = [
4646
{
4747
id: 'data-viewer--id',
@@ -75,3 +75,7 @@ export const VegaDataInspector = ({ adapters }: VegaDataInspectorProps) => {
7575
/>
7676
);
7777
};
78+
79+
// default export required for React.Lazy
80+
// eslint-disable-next-line import/no-default-export
81+
export { VegaDataInspector as default };

0 commit comments

Comments
 (0)