From 7a41d9475451be7ae3125590645b0b9a73e8dbb3 Mon Sep 17 00:00:00 2001 From: Ashwin P Chandran Date: Tue, 25 Oct 2022 18:31:44 -0700 Subject: [PATCH] [Vis Builder] Bug fixes for datasource picker and auto time interval (#2632) * Fixes auto time interval Signed-off-by: Ashwin P Chandran * Fixes change datasource while editing agg Signed-off-by: Ashwin P Chandran * Misc fixes Signed-off-by: Ashwin P Chandran * Updates Changelog Signed-off-by: Ashwin P Chandran * Correctly sets timerange Signed-off-by: Ashwin P Chandran * Fixes rebase Signed-off-by: Ashwin P Chandran Signed-off-by: Ashwin P Chandran --- CHANGELOG.md | 1 + .../saved_objects/simple_saved_object.ts | 5 +- .../components/data_tab/use/use_dropbox.tsx | 36 ++++++------ .../public/application/components/option.tsx | 1 + .../application/components/workspace.tsx | 7 ++- .../utils/state_management/store.ts | 1 + .../state_management/visualization_slice.ts | 1 + .../public/application/utils/use/index.ts | 1 + .../public/application/utils/use/use_aggs.ts | 57 +++++++++++++++++++ .../utils/validate_schema_state.ts | 15 ++++- .../embeddable/vis_builder_embeddable.tsx | 24 +++++--- .../public/services/type_service/types.ts | 8 ++- .../type_service/visualization_type.tsx | 8 ++- .../visualizations/metric/to_expression.ts | 4 +- .../vislib/area/to_expression.ts | 16 ++++-- .../vislib/common/create_vis.ts | 9 ++- .../visualizations/vislib/common/types.ts | 4 +- .../vislib/histogram/to_expression.ts | 16 ++++-- .../vislib/line/to_expression.ts | 16 ++++-- 19 files changed, 166 insertions(+), 64 deletions(-) create mode 100644 src/plugins/vis_builder/public/application/utils/use/use_aggs.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 0752c16f0de4..b90b52aa24ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * [Vis Builder] Fixes visualization shift when editing agg ([2401](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2401)) * [Vis Builder] Renames "Histogram" to "Bar" in vis type picker ([2401](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2401)) * [Vis Builder] Update vislib params and misc fixes ([2610](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2610)) +* [Vis Builder] Bug fixes for datasource picker and auto time interval ([2632](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2632)) * [MD] Add data source param to low-level search call in Discover ([#2431](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2431)) * [Multi DataSource] Skip data source view in index pattern step when pick default ([#2574](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2574)) * [Multi DataSource] Address UX comments on Edit Data source page ([#2629](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2629)) diff --git a/src/core/public/saved_objects/simple_saved_object.ts b/src/core/public/saved_objects/simple_saved_object.ts index 7cbedf4b9bb9..71b1445e95aa 100644 --- a/src/core/public/saved_objects/simple_saved_object.ts +++ b/src/core/public/saved_objects/simple_saved_object.ts @@ -63,8 +63,7 @@ export class SimpleSavedObject { error, references, migrationVersion, - // eslint-disable-next-line @typescript-eslint/naming-convention - updated_at, + updated_at: updateAt, }: SavedObjectType ) { this.id = id; @@ -73,7 +72,7 @@ export class SimpleSavedObject { this.references = references || []; this._version = version; this.migrationVersion = migrationVersion; - this.updated_at = updated_at; + this.updated_at = updateAt; if (error) { this.error = error; } diff --git a/src/plugins/vis_builder/public/application/components/data_tab/use/use_dropbox.tsx b/src/plugins/vis_builder/public/application/components/data_tab/use/use_dropbox.tsx index 87c004f0ae62..c41e4bc08662 100644 --- a/src/plugins/vis_builder/public/application/components/data_tab/use/use_dropbox.tsx +++ b/src/plugins/vis_builder/public/application/components/data_tab/use/use_dropbox.tsx @@ -8,7 +8,7 @@ import { cloneDeep } from 'lodash'; import { BucketAggType, IndexPatternField, propFilter } from '../../../../../../data/common'; import { Schema } from '../../../../../../vis_default_editor/public'; import { COUNT_FIELD, FieldDragDataType } from '../../../utils/drag_drop/types'; -import { useTypedDispatch, useTypedSelector } from '../../../utils/state_management'; +import { useTypedDispatch } from '../../../utils/state_management'; import { DropboxDisplay, DropboxProps } from '../dropbox'; import { useDrop } from '../../../utils/drag_drop'; import { @@ -16,9 +16,9 @@ import { reorderAgg, updateAggConfigParams, } from '../../../utils/state_management/visualization_slice'; -import { useIndexPatterns } from '../../../utils/use/use_index_pattern'; import { useOpenSearchDashboards } from '../../../../../../opensearch_dashboards_react/public'; import { VisBuilderServices } from '../../../../types'; +import { useAggs } from '../../../utils/use'; const filterByName = propFilter('name'); const filterByType = propFilter('type'); @@ -30,8 +30,8 @@ export interface UseDropboxProps extends Pick { export const useDropbox = (props: UseDropboxProps): DropboxProps => { const { id: dropboxId, label, schema } = props; const [validAggTypes, setValidAggTypes] = useState([]); + const { aggConfigs, indexPattern, aggs, timeRange } = useAggs(); const dispatch = useTypedDispatch(); - const indexPattern = useIndexPatterns().selected; const { services: { data: { @@ -39,27 +39,25 @@ export const useDropbox = (props: UseDropboxProps): DropboxProps => { }, }, } = useOpenSearchDashboards(); - const aggConfigParams = useTypedSelector( - (state) => state.visualization.activeVisualization?.aggConfigParams - ); - - const aggConfigs = useMemo(() => { - return indexPattern && aggService.createAggConfigs(indexPattern, cloneDeep(aggConfigParams)); - }, [aggConfigParams, aggService, indexPattern]); - const aggs = useMemo(() => aggConfigs?.aggs ?? [], [aggConfigs?.aggs]); - - const dropboxAggs = aggs.filter((agg) => agg.schema === schema.name); + const dropboxAggs = useMemo(() => aggs.filter((agg) => agg.schema === schema.name), [ + aggs, + schema.name, + ]); const displayFields: DropboxDisplay[] = useMemo( () => dropboxAggs?.map( - (agg): DropboxDisplay => ({ - id: agg.id, - label: agg.makeLabel(), - }) - ) || [], - [dropboxAggs] + (agg): DropboxDisplay => { + // For timeseries aggregations that have timeinterval set as auto, the current timerange is required to calculate the label accurately + agg.aggConfigs.setTimeRange(timeRange); + return { + id: agg.id, + label: agg.makeLabel(), + }; + } + ) ?? [], + [dropboxAggs, timeRange] ); // Event handlers for each dropbox action type diff --git a/src/plugins/vis_builder/public/application/components/option.tsx b/src/plugins/vis_builder/public/application/components/option.tsx index 0f1f79c7ecbd..2797629ebd04 100644 --- a/src/plugins/vis_builder/public/application/components/option.tsx +++ b/src/plugins/vis_builder/public/application/components/option.tsx @@ -20,6 +20,7 @@ export const Option: FC = ({ title, children, initialIsOpen = false }) => buttonContent={title} className="vbOption" initialIsOpen={initialIsOpen} + data-test-subj={`vbOption-${title.replace(/\s+/g, '-')}`} > diff --git a/src/plugins/vis_builder/public/application/components/workspace.tsx b/src/plugins/vis_builder/public/application/components/workspace.tsx index 6aa5af5132a4..23c9f081fdea 100644 --- a/src/plugins/vis_builder/public/application/components/workspace.tsx +++ b/src/plugins/vis_builder/public/application/components/workspace.tsx @@ -41,7 +41,7 @@ export const Workspace: FC = ({ children }) => { useEffect(() => { async function loadExpression() { const schemas = ui.containerConfig.data.schemas; - const [valid, errorMsg] = validateSchemaState(schemas, rootState); + const [valid, errorMsg] = validateSchemaState(schemas, rootState.visualization); if (!valid) { if (errorMsg) { @@ -50,12 +50,13 @@ export const Workspace: FC = ({ children }) => { setExpression(undefined); return; } - const exp = await toExpression(rootState); + + const exp = await toExpression(rootState, searchContext); setExpression(exp); } loadExpression(); - }, [rootState, toExpression, toasts, ui.containerConfig.data.schemas]); + }, [rootState, toExpression, toasts, ui.containerConfig.data.schemas, searchContext]); useLayoutEffect(() => { const subscription = data.query.state$.subscribe(({ state }) => { diff --git a/src/plugins/vis_builder/public/application/utils/state_management/store.ts b/src/plugins/vis_builder/public/application/utils/state_management/store.ts index 34f777e59508..f02fc5e946dd 100644 --- a/src/plugins/vis_builder/public/application/utils/state_management/store.ts +++ b/src/plugins/vis_builder/public/application/utils/state_management/store.ts @@ -72,6 +72,7 @@ export const getPreloadedStore = async (services: VisBuilderServices) => { // Infer the `RootState` and `AppDispatch` types from the store itself export type RootState = ReturnType; +export type RenderState = Omit; // Remaining state after auxillary states are removed type Store = ReturnType; export type AppDispatch = Store['dispatch']; diff --git a/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts b/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts index 47e7e1fb12e7..2039c93e8ade 100644 --- a/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts +++ b/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts @@ -50,6 +50,7 @@ export const slice = createSlice({ setIndexPattern: (state, action: PayloadAction) => { state.indexPattern = action.payload; state.activeVisualization!.aggConfigParams = []; + state.activeVisualization!.draftAgg = undefined; }, setSearchField: (state, action: PayloadAction) => { state.searchField = action.payload; diff --git a/src/plugins/vis_builder/public/application/utils/use/index.ts b/src/plugins/vis_builder/public/application/utils/use/index.ts index 138285148d43..3ba3ca359072 100644 --- a/src/plugins/vis_builder/public/application/utils/use/index.ts +++ b/src/plugins/vis_builder/public/application/utils/use/index.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +export { useAggs } from './use_aggs'; export { useVisualizationType } from './use_visualization_type'; export { useIndexPatterns } from './use_index_pattern'; export { useSavedVisBuilderVis } from './use_saved_vis_builder_vis'; diff --git a/src/plugins/vis_builder/public/application/utils/use/use_aggs.ts b/src/plugins/vis_builder/public/application/utils/use/use_aggs.ts new file mode 100644 index 000000000000..19a3589a9cb7 --- /dev/null +++ b/src/plugins/vis_builder/public/application/utils/use/use_aggs.ts @@ -0,0 +1,57 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { cloneDeep } from 'lodash'; +import { useLayoutEffect, useMemo, useState } from 'react'; +import { useOpenSearchDashboards } from '../../../../../opensearch_dashboards_react/public'; +import { VisBuilderServices } from '../../../types'; +import { useTypedSelector, useTypedDispatch } from '../state_management'; +import { useIndexPatterns } from './use_index_pattern'; + +/** + * Returns common agg parameters from the store and app context + * @returns { indexPattern, aggConfigs, aggs, timeRange } + */ +export const useAggs = () => { + const { + services: { + data: { + search: { aggs: aggService }, + query: { + timefilter: { timefilter }, + }, + }, + }, + } = useOpenSearchDashboards(); + const indexPattern = useIndexPatterns().selected; + const [timeRange, setTimeRange] = useState(timefilter.getTime()); + const aggConfigParams = useTypedSelector( + (state) => state.visualization.activeVisualization?.aggConfigParams + ); + const dispatch = useTypedDispatch(); + + const aggConfigs = useMemo(() => { + const configs = + indexPattern && aggService.createAggConfigs(indexPattern, cloneDeep(aggConfigParams)); + return configs; + }, [aggConfigParams, aggService, indexPattern]); + + useLayoutEffect(() => { + const subscription = timefilter.getTimeUpdate$().subscribe(() => { + setTimeRange(timefilter.getTime()); + }); + + return () => { + subscription.unsubscribe(); + }; + }, [dispatch, timefilter]); + + return { + indexPattern, + aggConfigs, + aggs: aggConfigs?.aggs ?? [], + timeRange, + }; +}; diff --git a/src/plugins/vis_builder/public/application/utils/validate_schema_state.ts b/src/plugins/vis_builder/public/application/utils/validate_schema_state.ts index 2db3653e2ce3..87dc19a3024e 100644 --- a/src/plugins/vis_builder/public/application/utils/validate_schema_state.ts +++ b/src/plugins/vis_builder/public/application/utils/validate_schema_state.ts @@ -5,10 +5,19 @@ import { countBy } from 'lodash'; import { Schemas } from '../../../../vis_default_editor/public'; -import { RootState } from './state_management'; +import { VisualizationState } from './state_management'; -export const validateSchemaState = (schemas: Schemas, state: RootState): [boolean, string?] => { - const activeViz = state.visualization.activeVisualization; +/** + * Validate if the visualization state fits the vis type schema criteria + * @param schemas Visualization type config Schema objects + * @param state visualization state + * @returns [Validity, 'Message'] + */ +export const validateSchemaState = ( + schemas: Schemas, + state: VisualizationState +): [boolean, string?] => { + const activeViz = state.activeVisualization; const vizName = activeViz?.name; const aggs = activeViz?.aggConfigParams; diff --git a/src/plugins/vis_builder/public/embeddable/vis_builder_embeddable.tsx b/src/plugins/vis_builder/public/embeddable/vis_builder_embeddable.tsx index e6ee03e20827..8ebbd662cc20 100644 --- a/src/plugins/vis_builder/public/embeddable/vis_builder_embeddable.tsx +++ b/src/plugins/vis_builder/public/embeddable/vis_builder_embeddable.tsx @@ -30,6 +30,7 @@ import { import { validateSchemaState } from '../application/utils/validate_schema_state'; import { getExpressionLoader, getTypeService } from '../plugin_services'; import { PersistedState } from '../../../visualizations/public'; +import { RenderState, VisualizationState } from '../application/utils/state_management'; // Apparently this needs to match the saved object type for the clone and replace panel actions to work export const VISBUILDER_EMBEDDABLE = VISBUILDER_SAVED_OBJECT; @@ -121,16 +122,16 @@ export class VisBuilderEmbeddable extends Embeddable { style: StyleTabConfig; }; }; - readonly toExpression: (state: RootState) => Promise; + readonly toExpression: ( + state: RenderState, + searchContext: IExpressionLoaderParams['searchContext'] + ) => Promise; } diff --git a/src/plugins/vis_builder/public/services/type_service/visualization_type.tsx b/src/plugins/vis_builder/public/services/type_service/visualization_type.tsx index 305b7a716cf6..2f863316435e 100644 --- a/src/plugins/vis_builder/public/services/type_service/visualization_type.tsx +++ b/src/plugins/vis_builder/public/services/type_service/visualization_type.tsx @@ -3,7 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ import { IconType } from '@elastic/eui'; -import { RootState } from '../../application/utils/state_management'; +import { IExpressionLoaderParams } from '../../../../expressions/public'; +import { RenderState } from '../../application/utils/state_management'; import { VisualizationTypeOptions } from './types'; type IVisualizationType = VisualizationTypeOptions; @@ -15,7 +16,10 @@ export class VisualizationType implements IVisualizationType { public readonly icon: IconType; public readonly stage: 'experimental' | 'production'; public readonly ui: IVisualizationType['ui']; - public readonly toExpression: (state: RootState) => Promise; + public readonly toExpression: ( + state: RenderState, + searchContext: IExpressionLoaderParams['searchContext'] + ) => Promise; constructor(options: VisualizationTypeOptions) { this.name = options.name; diff --git a/src/plugins/vis_builder/public/visualizations/metric/to_expression.ts b/src/plugins/vis_builder/public/visualizations/metric/to_expression.ts index 181e504ec0e8..f7d8b4aa2a4c 100644 --- a/src/plugins/vis_builder/public/visualizations/metric/to_expression.ts +++ b/src/plugins/vis_builder/public/visualizations/metric/to_expression.ts @@ -7,7 +7,7 @@ import { SchemaConfig } from '../../../../visualizations/public'; import { MetricVisExpressionFunctionDefinition } from '../../../../vis_type_metric/public'; import { AggConfigs, IAggConfig } from '../../../../data/common'; import { buildExpression, buildExpressionFunction } from '../../../../expressions/public'; -import { RootState } from '../../application/utils/state_management'; +import { RenderState } from '../../application/utils/state_management'; import { MetricOptionsDefaults } from './metric_viz_type'; import { getAggExpressionFunctions } from '../common/expression_helpers'; @@ -82,7 +82,7 @@ const getVisSchemas = (aggConfigs: AggConfigs): any => { return schemas; }; -export interface MetricRootState extends RootState { +export interface MetricRootState extends RenderState { style: MetricOptionsDefaults; } diff --git a/src/plugins/vis_builder/public/visualizations/vislib/area/to_expression.ts b/src/plugins/vis_builder/public/visualizations/vislib/area/to_expression.ts index 7512b2f746cc..4481dce24619 100644 --- a/src/plugins/vis_builder/public/visualizations/vislib/area/to_expression.ts +++ b/src/plugins/vis_builder/public/visualizations/vislib/area/to_expression.ts @@ -4,22 +4,26 @@ */ import { buildVislibDimensions } from '../../../../../visualizations/public'; -import { buildExpression, buildExpressionFunction } from '../../../../../expressions/public'; +import { + buildExpression, + buildExpressionFunction, + IExpressionLoaderParams, +} from '../../../../../expressions/public'; import { AreaOptionsDefaults } from './area_vis_type'; import { getAggExpressionFunctions } from '../../common/expression_helpers'; import { VislibRootState, getValueAxes, getPipelineParams } from '../common'; import { createVis } from '../common/create_vis'; -export const toExpression = async ({ - style: styleState, - visualization, -}: VislibRootState) => { +export const toExpression = async ( + { style: styleState, visualization }: VislibRootState, + searchContext: IExpressionLoaderParams['searchContext'] +) => { const { aggConfigs, expressionFns, indexPattern } = await getAggExpressionFunctions( visualization ); const { addLegend, addTooltip, legendPosition, type } = styleState; - const vis = await createVis(type, aggConfigs, indexPattern); + const vis = await createVis(type, aggConfigs, indexPattern, searchContext?.timeRange); const params = getPipelineParams(); const dimensions = await buildVislibDimensions(vis, params); diff --git a/src/plugins/vis_builder/public/visualizations/vislib/common/create_vis.ts b/src/plugins/vis_builder/public/visualizations/vislib/common/create_vis.ts index 8bee18b8d94b..209f4a2a50b8 100644 --- a/src/plugins/vis_builder/public/visualizations/vislib/common/create_vis.ts +++ b/src/plugins/vis_builder/public/visualizations/vislib/common/create_vis.ts @@ -3,19 +3,24 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { AggConfigs, IndexPattern } from '../../../../../data/public'; +import { AggConfigs, IndexPattern, TimeRange } from '../../../../../data/public'; import { Vis } from '../../../../../visualizations/public'; import { getSearchService } from '../../../plugin_services'; export const createVis = async ( type: string, aggConfigs: AggConfigs, - indexPattern: IndexPattern + indexPattern: IndexPattern, + timeRange?: TimeRange ) => { const vis = new Vis(type); vis.data.aggs = aggConfigs; vis.data.searchSource = await getSearchService().searchSource.create(); vis.data.searchSource.setField('index', indexPattern); + const responseAggs = vis.data.aggs.getResponseAggs().filter((agg) => agg.enabled); + responseAggs.forEach((agg) => { + agg.params.timeRange = timeRange; + }); return vis; }; diff --git a/src/plugins/vis_builder/public/visualizations/vislib/common/types.ts b/src/plugins/vis_builder/public/visualizations/vislib/common/types.ts index 4861c1af2e55..fa63b41c826b 100644 --- a/src/plugins/vis_builder/public/visualizations/vislib/common/types.ts +++ b/src/plugins/vis_builder/public/visualizations/vislib/common/types.ts @@ -4,7 +4,7 @@ */ import { Positions } from '../../../../../vis_type_vislib/public'; -import { RootState } from '../../../application/utils/state_management'; +import { RenderState } from '../../../application/utils/state_management'; export interface BasicOptionsDefaults { addTooltip: boolean; @@ -13,6 +13,6 @@ export interface BasicOptionsDefaults { type: string; } -export interface VislibRootState extends RootState { +export interface VislibRootState extends RenderState { style: T; } diff --git a/src/plugins/vis_builder/public/visualizations/vislib/histogram/to_expression.ts b/src/plugins/vis_builder/public/visualizations/vislib/histogram/to_expression.ts index 64308a3a02f4..2f75ed326913 100644 --- a/src/plugins/vis_builder/public/visualizations/vislib/histogram/to_expression.ts +++ b/src/plugins/vis_builder/public/visualizations/vislib/histogram/to_expression.ts @@ -4,22 +4,26 @@ */ import { buildVislibDimensions } from '../../../../../visualizations/public'; -import { buildExpression, buildExpressionFunction } from '../../../../../expressions/public'; +import { + buildExpression, + buildExpressionFunction, + IExpressionLoaderParams, +} from '../../../../../expressions/public'; import { HistogramOptionsDefaults } from './histogram_vis_type'; import { getAggExpressionFunctions } from '../../common/expression_helpers'; import { VislibRootState, getValueAxes, getPipelineParams } from '../common'; import { createVis } from '../common/create_vis'; -export const toExpression = async ({ - style: styleState, - visualization, -}: VislibRootState) => { +export const toExpression = async ( + { style: styleState, visualization }: VislibRootState, + searchContext: IExpressionLoaderParams['searchContext'] +) => { const { aggConfigs, expressionFns, indexPattern } = await getAggExpressionFunctions( visualization ); const { addLegend, addTooltip, legendPosition, type } = styleState; - const vis = await createVis(type, aggConfigs, indexPattern); + const vis = await createVis(type, aggConfigs, indexPattern, searchContext?.timeRange); const params = getPipelineParams(); const dimensions = await buildVislibDimensions(vis, params); diff --git a/src/plugins/vis_builder/public/visualizations/vislib/line/to_expression.ts b/src/plugins/vis_builder/public/visualizations/vislib/line/to_expression.ts index 5cadc0e278e8..41a6d505c724 100644 --- a/src/plugins/vis_builder/public/visualizations/vislib/line/to_expression.ts +++ b/src/plugins/vis_builder/public/visualizations/vislib/line/to_expression.ts @@ -4,22 +4,26 @@ */ import { buildVislibDimensions } from '../../../../../visualizations/public'; -import { buildExpression, buildExpressionFunction } from '../../../../../expressions/public'; +import { + buildExpression, + buildExpressionFunction, + IExpressionLoaderParams, +} from '../../../../../expressions/public'; import { LineOptionsDefaults } from './line_vis_type'; import { getAggExpressionFunctions } from '../../common/expression_helpers'; import { VislibRootState, getValueAxes, getPipelineParams } from '../common'; import { createVis } from '../common/create_vis'; -export const toExpression = async ({ - style: styleState, - visualization, -}: VislibRootState) => { +export const toExpression = async ( + { style: styleState, visualization }: VislibRootState, + searchContext: IExpressionLoaderParams['searchContext'] +) => { const { aggConfigs, expressionFns, indexPattern } = await getAggExpressionFunctions( visualization ); const { addLegend, addTooltip, legendPosition, type } = styleState; - const vis = await createVis(type, aggConfigs, indexPattern); + const vis = await createVis(type, aggConfigs, indexPattern, searchContext?.timeRange); const params = getPipelineParams(); const dimensions = await buildVislibDimensions(vis, params);