From cf72e84aa263ecd757b256edbc9a5477b625c0ca Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Wed, 16 Feb 2022 14:06:32 +0300 Subject: [PATCH] [Reporting] Missing vega vis is when generating report from sample data Closes: #124886 --- .../vega/public/components/vega_vis.scss | 5 +++ .../public/components/vega_vis_component.tsx | 45 +++++++++++++------ .../vega/public/vega_view/vega_base_view.d.ts | 1 + .../vega/public/vega_view/vega_base_view.js | 15 ++++--- .../public/vega_view/vega_map_view/view.ts | 7 +++ .../vega/public/vega_vis_renderer.tsx | 1 - .../vega/public/vega_visualization.ts | 5 +++ 7 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/plugins/vis_types/vega/public/components/vega_vis.scss b/src/plugins/vis_types/vega/public/components/vega_vis.scss index f0062869e0046..e37cae11d6810 100644 --- a/src/plugins/vis_types/vega/public/components/vega_vis.scss +++ b/src/plugins/vis_types/vega/public/components/vega_vis.scss @@ -12,6 +12,11 @@ flex: 1 1 100%; position: relative; // flex-direction determined by js + + // Fix Firefox incorrectly showing vertical/horizontal scrollbars for canvas element + canvas { + display: block; + } } .vgaVis__view { diff --git a/src/plugins/vis_types/vega/public/components/vega_vis_component.tsx b/src/plugins/vis_types/vega/public/components/vega_vis_component.tsx index 66cb87d0d6138..f9b6f3c0e36df 100644 --- a/src/plugins/vis_types/vega/public/components/vega_vis_component.tsx +++ b/src/plugins/vis_types/vega/public/components/vega_vis_component.tsx @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import React, { useEffect, useCallback, useRef } from 'react'; -import { EuiResizeObserver } from '@elastic/eui'; +import React, { useEffect, useRef, useMemo, useCallback } from 'react'; +import { EuiResizeObserver, EuiResizeObserverProps } from '@elastic/eui'; import { throttle } from 'lodash'; import type { IInterpreterRenderHandlers, RenderMode } from 'src/plugins/expressions'; @@ -27,6 +27,8 @@ interface VegaVisComponentProps { type VegaVisController = InstanceType>; +const THROTTLE_INTERVAL = 300; + export const VegaVisComponent = ({ visData, fireEvent, @@ -35,6 +37,7 @@ export const VegaVisComponent = ({ renderMode, }: VegaVisComponentProps) => { const chartDiv = useRef(null); + const renderCompleted = useRef(false); const visController = useRef(null); useEffect(() => { @@ -42,7 +45,6 @@ export const VegaVisComponent = ({ const VegaVis = createVegaVisualization(deps, renderMode); visController.current = new VegaVis(chartDiv.current, fireEvent); } - return () => { visController.current?.destroy(); visController.current = null; @@ -50,23 +52,40 @@ export const VegaVisComponent = ({ }, [deps, fireEvent, renderMode]); useEffect(() => { + const asyncRender = async (visCtrl: VegaVisController) => { + await visCtrl.render(visData); + renderCompleted.current = true; + renderComplete(); + }; + if (visController.current) { - visController.current.render(visData).then(renderComplete); + asyncRender(visController.current); } - }, [visData, renderComplete]); + }, [renderComplete, visData]); + + const resizeChart = useMemo( + () => + throttle( + (dimensions) => { + visController.current?.resize(dimensions); + }, + THROTTLE_INTERVAL, + { leading: false, trailing: true } + ), + [] + ); - /* eslint-disable-next-line react-hooks/exhaustive-deps */ - const updateChartSize = useCallback( - throttle(() => { - if (visController.current) { - visController.current.render(visData).then(renderComplete); + const onContainerResize: EuiResizeObserverProps['onResize'] = useCallback( + (dimensions) => { + if (renderCompleted.current) { + resizeChart(dimensions); } - }, 300), - [renderComplete, visData] + }, + [resizeChart] ); return ( - + {(resizeRef) => (
diff --git a/src/plugins/vis_types/vega/public/vega_view/vega_base_view.d.ts b/src/plugins/vis_types/vega/public/vega_view/vega_base_view.d.ts index a1d79394de4eb..1ddd2849e3f39 100644 --- a/src/plugins/vis_types/vega/public/vega_view/vega_base_view.d.ts +++ b/src/plugins/vis_types/vega/public/vega_view/vega_base_view.d.ts @@ -34,6 +34,7 @@ export class VegaBaseView { _addDestroyHandler(handler: Function): void; destroy(): Promise; + resize(dimensions?: { height: number; width: number }): Promise; _$container: any; _$controls: any; diff --git a/src/plugins/vis_types/vega/public/vega_view/vega_base_view.js b/src/plugins/vis_types/vega/public/vega_view/vega_base_view.js index 25cfcdb4dde04..c6ec924f07d9d 100644 --- a/src/plugins/vis_types/vega/public/vega_view/vega_base_view.js +++ b/src/plugins/vis_types/vega/public/vega_view/vega_base_view.js @@ -262,16 +262,19 @@ export class VegaBaseView { } } - resize() { + async resize(dimensions) { if (this._parser.useResize && this._view) { - this.updateVegaSize(this._view); - return this._view.runAsync(); + this.updateVegaSize(this._view, dimensions); + await this._view.runAsync(); + + // The derived class should create this method + this.onViewContainerResize?.(); } } - updateVegaSize(view) { - const width = Math.floor(Math.max(0, this._$container.width())); - const height = Math.floor(Math.max(0, this._$container.height())); + updateVegaSize(view, dimensions) { + const width = Math.floor(Math.max(0, dimensions?.width ?? this._$container.width())); + const height = Math.floor(Math.max(0, dimensions?.height ?? this._$container.height())); if (view.width() !== width || view.height() !== height) { view.width(width).height(height); diff --git a/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.ts b/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.ts index be68abaebc638..fe8d85a011442 100644 --- a/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.ts +++ b/src/plugins/vis_types/vega/public/vega_view/vega_map_view/view.ts @@ -46,6 +46,8 @@ async function updateVegaView(mapBoxInstance: Map, vegaView: View) { } export class VegaMapView extends VegaBaseView { + private mapBoxInstance?: Map; + private get shouldShowZoomControl() { return Boolean(this._parser.mapConfig.zoomControl); } @@ -139,6 +141,7 @@ export class VegaMapView extends VegaBaseView { }; mapBoxInstance.once('load', initMapComponents); + this.mapBoxInstance = mapBoxInstance; }); } @@ -193,4 +196,8 @@ export class VegaMapView extends VegaBaseView { await this.initMapContainer(vegaView); } + + protected async onViewContainerResize() { + this.mapBoxInstance?.resize(); + } } diff --git a/src/plugins/vis_types/vega/public/vega_vis_renderer.tsx b/src/plugins/vis_types/vega/public/vega_vis_renderer.tsx index a7bab7f0f0860..ac36c9f2d20e1 100644 --- a/src/plugins/vis_types/vega/public/vega_vis_renderer.tsx +++ b/src/plugins/vis_types/vega/public/vega_vis_renderer.tsx @@ -27,7 +27,6 @@ export const getVegaVisRenderer: ( handlers.onDestroy(() => { unmountComponentAtNode(domNode); }); - render( diff --git a/src/plugins/vis_types/vega/public/vega_visualization.ts b/src/plugins/vis_types/vega/public/vega_visualization.ts index f9a18067e6886..49e6355a7109d 100644 --- a/src/plugins/vis_types/vega/public/vega_visualization.ts +++ b/src/plugins/vis_types/vega/public/vega_visualization.ts @@ -16,6 +16,7 @@ import { createVegaStateRestorer } from './lib/vega_state_restorer'; type VegaVisType = new (el: HTMLDivElement, fireEvent: IInterpreterRenderHandlers['event']) => { render(visData: VegaParser): Promise; + resize(dimensions?: { height: number; width: number }): Promise; destroy(): void; }; @@ -97,6 +98,10 @@ export const createVegaVisualization = ( } } + async resize(dimensions?: { height: number; width: number }) { + return this.vegaView?.resize(dimensions); + } + destroy() { this.vegaStateRestorer.clear(); this.vegaView?.destroy();