From ea2c00ab7e3120aaebfe66aa2065cabeecce88cb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 9 Jan 2023 23:47:41 +0000 Subject: [PATCH] [VisBuilder] fixes filters for table visualisation (#3210) * fixes table vis for filter aggregation types Signed-off-by: Ashwin P Chandran * Fixes filter and add error boundry Signed-off-by: Ashwin P Chandran * Adds changelog Signed-off-by: Ashwin P Chandran Signed-off-by: Ashwin P Chandran (cherry picked from commit fba380b149e491d62b3e5eec708f53d8dd83fed1) Signed-off-by: github-actions[bot] # Conflicts: # CHANGELOG.md --- .../components/data_tab/secondary_panel.tsx | 150 ++++++++++++------ .../public/application/components/top_nav.tsx | 4 +- src/plugins/vis_builder/public/plugin.ts | 1 + src/plugins/vis_builder/public/types.ts | 1 + src/plugins/vis_type_table/public/index.ts | 3 + 5 files changed, 109 insertions(+), 50 deletions(-) diff --git a/src/plugins/vis_builder/public/application/components/data_tab/secondary_panel.tsx b/src/plugins/vis_builder/public/application/components/data_tab/secondary_panel.tsx index 385fcda9a805..9576d1edc419 100644 --- a/src/plugins/vis_builder/public/application/components/data_tab/secondary_panel.tsx +++ b/src/plugins/vis_builder/public/application/components/data_tab/secondary_panel.tsx @@ -3,18 +3,24 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React, { useCallback, useMemo, useState } from 'react'; +import React, { Component, useCallback, useMemo, useState } from 'react'; import { cloneDeep, get } from 'lodash'; import { useDebounce } from 'react-use'; +import { i18n } from '@osd/i18n'; +import { EuiCallOut } from '@elastic/eui'; import { useTypedDispatch, useTypedSelector } from '../../utils/state_management'; import { DefaultEditorAggParams } from '../../../../../vis_default_editor/public'; import { Title } from './title'; import { useIndexPatterns, useVisualizationType } from '../../utils/use'; -import { useOpenSearchDashboards } from '../../../../../opensearch_dashboards_react/public'; +import { + OpenSearchDashboardsContextProvider, + useOpenSearchDashboards, +} from '../../../../../opensearch_dashboards_react/public'; import { VisBuilderServices } from '../../../types'; import { AggParam, IAggType, IFieldParamType } from '../../../../../data/public'; import { saveDraftAgg, editDraftAgg } from '../../utils/state_management/visualization_slice'; import { setValidity } from '../../utils/state_management/metadata_slice'; +import { Storage } from '../../../../../opensearch_dashboards_utils/public'; const EDITOR_KEY = 'CONFIG_PANEL'; @@ -27,13 +33,12 @@ export function SecondaryPanel() { const dispatch = useTypedDispatch(); const vizType = useVisualizationType(); const indexPattern = useIndexPatterns().selected; + const { services } = useOpenSearchDashboards(); const { - services: { - data: { - search: { aggs: aggService }, - }, + data: { + search: { aggs: aggService }, }, - } = useOpenSearchDashboards(); + } = services; const schemas = vizType.ui.containerConfig.data.schemas.all; const aggConfigs = useMemo(() => { @@ -98,49 +103,98 @@ export function SecondaryPanel() {
{showAggParamEditor && ( - <DefaultEditorAggParams - className="vbConfig__aggEditor" - agg={aggConfig!} - indexPattern={indexPattern!} - setValidity={handleSetValid} - setTouched={setTouched} - schemas={schemas} - formIsTouched={touched} - groupName={selectedSchema?.group ?? 'none'} - metricAggs={metricAggs} - state={{ - data: {}, - description: '', - title: '', + <OpenSearchDashboardsContextProvider + services={{ + ...services, + storage: new Storage(window.localStorage), // This is necessary for filters }} - setAggParamValue={function <T extends string | number | symbol>( - aggId: string, - paramName: T, - value: any - ): void { - aggConfig.params[paramName] = value; - dispatch(editDraftAgg(aggConfig.serialize())); - }} - onAggTypeChange={function (aggId: string, aggType: IAggType): void { - aggConfig.type = aggType; - - // Persist field if the new agg type supports the existing field - const fieldParam = (aggType.params as AggParam[]).find(({ type }) => type === 'field'); - if (fieldParam) { - const availableFields = (fieldParam as IFieldParamType).getAvailableFields(aggConfig); - const indexField = availableFields.find( - ({ name }) => name === get(draftAgg, 'params.field') - ); - - if (indexField) { - aggConfig.params.field = indexField; - } - } - - dispatch(editDraftAgg(aggConfig.serialize())); - }} - /> + > + <EditorErrorBoundary> + <DefaultEditorAggParams + className="vbConfig__aggEditor" + agg={aggConfig!} + indexPattern={indexPattern!} + setValidity={handleSetValid} + setTouched={setTouched} + schemas={schemas} + formIsTouched={touched} + groupName={selectedSchema?.group ?? 'none'} + metricAggs={metricAggs} + state={{ + data: {}, + description: '', + title: '', + }} + setAggParamValue={function <T extends string | number | symbol>( + aggId: string, + paramName: T, + value: any + ): void { + aggConfig.params[paramName] = value; + dispatch(editDraftAgg(aggConfig.serialize())); + }} + onAggTypeChange={function (aggId: string, aggType: IAggType): void { + aggConfig.type = aggType; + + // Persist field if the new agg type supports the existing field + const fieldParam = (aggType.params as AggParam[]).find( + ({ type }) => type === 'field' + ); + if (fieldParam) { + const availableFields = (fieldParam as IFieldParamType).getAvailableFields( + aggConfig + ); + const indexField = availableFields.find( + ({ name }) => name === get(draftAgg, 'params.field') + ); + + if (indexField) { + aggConfig.params.field = indexField; + } + } + + dispatch(editDraftAgg(aggConfig.serialize())); + }} + /> + </EditorErrorBoundary> + </OpenSearchDashboardsContextProvider> )} </div> ); } + +class EditorErrorBoundary extends Component<{}, { error?: any }> { + state = { + error: undefined, + }; + + static getDerivedStateFromError(error: any) { + return { error }; + } + + componentDidCatch(error) { + // eslint-disable-next-line no-console + console.error(error); + } + + render() { + if (this.state.error) { + return ( + <EuiCallOut + title={i18n.translate('visBuilder.aggParamsEditor.errorTitle', { + defaultMessage: 'Error', + })} + color="danger" + iconType="alert" + > + <p> + {i18n.translate('visBuilder.aggParamsEditor.errorMsg', { + defaultMessage: 'Something went wrong while editing the aggregation', + })} + </p> + </EuiCallOut> + ); + } + return this.props.children; + } +} diff --git a/src/plugins/vis_builder/public/application/components/top_nav.tsx b/src/plugins/vis_builder/public/application/components/top_nav.tsx index d64352fb4d69..768f2db35465 100644 --- a/src/plugins/vis_builder/public/application/components/top_nav.tsx +++ b/src/plugins/vis_builder/public/application/components/top_nav.tsx @@ -6,7 +6,6 @@ import React, { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { useUnmount } from 'react-use'; -import { PLUGIN_ID } from '../../../common'; import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; import { getTopNavConfig } from '../utils/get_top_nav_config'; import { VisBuilderServices } from '../../types'; @@ -29,6 +28,7 @@ export const TopNav = () => { navigation: { ui: { TopNavMenu }, }, + appName, } = services; const rootState = useTypedSelector((state) => state); const dispatch = useTypedDispatch(); @@ -81,7 +81,7 @@ export const TopNav = () => { return ( <div className="vbTopNav"> <TopNavMenu - appName={PLUGIN_ID} + appName={appName} config={config} setMenuMountPoint={setHeaderActionMenu} indexPatterns={indexPattern ? [indexPattern] : []} diff --git a/src/plugins/vis_builder/public/plugin.ts b/src/plugins/vis_builder/public/plugin.ts index a619958653b6..3995c1246de5 100644 --- a/src/plugins/vis_builder/public/plugin.ts +++ b/src/plugins/vis_builder/public/plugin.ts @@ -140,6 +140,7 @@ export class VisBuilderPlugin const services: VisBuilderServices = { ...coreStart, + appName: PLUGIN_ID, scopedHistory: this.currentHistory, history: this.currentHistory, osdUrlStateStorage: createOsdUrlStateStorage({ diff --git a/src/plugins/vis_builder/public/types.ts b/src/plugins/vis_builder/public/types.ts index 2d323a13b213..e79762bedc1f 100644 --- a/src/plugins/vis_builder/public/types.ts +++ b/src/plugins/vis_builder/public/types.ts @@ -37,6 +37,7 @@ export interface VisBuilderPluginStartDependencies { } export interface VisBuilderServices extends CoreStart { + appName: string; setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; savedVisBuilderLoader: VisBuilderStart['savedVisBuilderLoader']; toastNotifications: ToastsStart; diff --git a/src/plugins/vis_type_table/public/index.ts b/src/plugins/vis_type_table/public/index.ts index b5ab796210ff..774af319b920 100644 --- a/src/plugins/vis_type_table/public/index.ts +++ b/src/plugins/vis_type_table/public/index.ts @@ -9,3 +9,6 @@ import { TableVisPlugin as Plugin } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { return new Plugin(initializerContext); } + +/* Public Types */ +export { TableVisExpressionFunctionDefinition } from './table_vis_fn';