From fba380b149e491d62b3e5eec708f53d8dd83fed1 Mon Sep 17 00:00:00 2001 From: Ashwin P Chandran Date: Mon, 9 Jan 2023 15:45:35 -0800 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 --- CHANGELOG.md | 5 +- .../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 + 6 files changed, 112 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83116432ce20..594c92cc4f9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Multi DataSource] Address UX comments on index pattern management stack ([#2611](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2611)) - [Multi DataSource] Apply get indices error handling in step index pattern ([#2652](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2652)) - [Vis Builder] Last Updated Timestamp for visbuilder savedobject is getting Generated ([#2628](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2628)) +- [Vis Builder] fixes filters for table visualisation ([#3210](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3210)) - Removed Leftover X Pack references ([#2638](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2638)) - Removes Add Integration button ([#2723](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2723)) - Change geckodriver version to make consistency ([#2772](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2772)) @@ -83,7 +84,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Build] Fixed "Last Access Time" not being set by `scanCopy` on Windows ([#2964](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2964)) - [Vis Builder] Add global data persistence for vis builder #2896 ([#2896](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2896)) - Update `leaflet-vega` and fix its usage ([#3005](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3005)) -- [Table Visualization][BUG] Fix Url content display issue in table ([#2918](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2918)) +- [Table Visualization][bug] Fix Url content display issue in table ([#2918](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2918)) - Fixes misleading embaddable plugin error message ([#3043](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3043)) - [MD] Update dummy url in tests to follow lychee url allowlist ([#3099](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3099)) - Adds config override to fix obsolete theme:version config value of v8 (beta) rendering issue ([#3045](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3045)) @@ -153,7 +154,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [CVE-2022-37601] Bump loader-utils to 2.0.3 ([#2689](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2689)) - [CVE-2022-37599] Bump loader-utils to 2.0.4 ([#3031](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3031)) - [CVE-2022-37603] Bump loader-utils to 2.0.4 ([#3031](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3031)) -- [WS-2021-0638][Security] bump mocha to 10.1.0 ([#2711](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2711)) +- [WS-2021-0638][security] bump mocha to 10.1.0 ([#2711](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2711)) ### 📈 Features/Enhancements 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';