From 5e2ed9ac44bf381db738444aa4563ce5342257ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 10 Sep 2024 23:56:05 +0000 Subject: [PATCH] Filter Saved Search Based on AppName Supported by Language (#7999) * Filter Saved Search Based on AppName Supported by Language Signed-off-by: Suchit Sahoo * Fixed test failures Signed-off-by: Suchit Sahoo --------- Signed-off-by: Suchit Sahoo (cherry picked from commit f694be46d46af80a44f3d473bf1af8b43457cdee) Signed-off-by: github-actions[bot] --- .../utils/create_dashboard_container.tsx | 7 ++- .../application/utils/get_nav_actions.tsx | 7 ++- src/plugins/dashboard/public/plugin.tsx | 7 ++- .../language_service/lib/dql_language.ts | 1 + .../language_service/lib/lucene_language.ts | 1 + .../query_string/language_service/types.ts | 1 + .../open_search_panel.test.tsx.snap | 3 + .../components/top_nav/open_search_panel.tsx | 4 ++ .../embeddable/search_embeddable_factory.tsx | 1 + src/plugins/embeddable/public/plugin.tsx | 7 ++- .../query_enhancements/public/plugin.tsx | 2 + .../public/finder/saved_object_finder.tsx | 55 ++++++++++++++++++- src/plugins/visualizations/public/plugin.ts | 2 + src/plugins/visualizations/public/services.ts | 2 + .../public/wizard/new_vis_modal.tsx | 4 ++ .../search_selection/search_selection.tsx | 8 ++- .../public/wizard/show_new_vis.tsx | 2 + 17 files changed, 107 insertions(+), 7 deletions(-) diff --git a/src/plugins/dashboard/public/application/utils/create_dashboard_container.tsx b/src/plugins/dashboard/public/application/utils/create_dashboard_container.tsx index 1c5b06f54e57..acf1147b8c15 100644 --- a/src/plugins/dashboard/public/application/utils/create_dashboard_container.tsx +++ b/src/plugins/dashboard/public/application/utils/create_dashboard_container.tsx @@ -282,7 +282,12 @@ const getEmptyScreenProps = ( getFactory: embeddable.getEmbeddableFactory, notifications, overlays, - SavedObjectFinder: getSavedObjectFinder(savedObjects, uiSettings), + SavedObjectFinder: getSavedObjectFinder( + savedObjects, + uiSettings, + services.data, + services.application + ), }); } } else { diff --git a/src/plugins/dashboard/public/application/utils/get_nav_actions.tsx b/src/plugins/dashboard/public/application/utils/get_nav_actions.tsx index 32bfef083518..5c98bb55099a 100644 --- a/src/plugins/dashboard/public/application/utils/get_nav_actions.tsx +++ b/src/plugins/dashboard/public/application/utils/get_nav_actions.tsx @@ -174,7 +174,12 @@ export const getNavActions = ( getFactory: embeddable.getEmbeddableFactory, notifications, overlays, - SavedObjectFinder: getSavedObjectFinder(savedObjects, uiSettings), + SavedObjectFinder: getSavedObjectFinder( + savedObjects, + uiSettings, + services.data, + services.application + ), }); } }; diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 5d6ad78ca0b7..c7951a955fde 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -567,7 +567,12 @@ export class DashboardPlugin embeddable, } = plugins; - const SavedObjectFinder = getSavedObjectFinder(core.savedObjects, core.uiSettings); + const SavedObjectFinder = getSavedObjectFinder( + core.savedObjects, + core.uiSettings, + plugins.data, + core.application + ); const changeViewAction = new ReplacePanelAction( core, diff --git a/src/plugins/data/public/query/query_string/language_service/lib/dql_language.ts b/src/plugins/data/public/query/query_string/language_service/lib/dql_language.ts index d13125b9d479..39dc49f22fce 100644 --- a/src/plugins/data/public/query/query_string/language_service/lib/dql_language.ts +++ b/src/plugins/data/public/query/query_string/language_service/lib/dql_language.ts @@ -24,5 +24,6 @@ export const getDQLLanguageConfig = ( }, showDocLinks: true, editorSupportedAppNames: ['discover'], + supportedAppNames: ['discover', 'dashboards', 'visualize', 'data-explorer'], }; }; diff --git a/src/plugins/data/public/query/query_string/language_service/lib/lucene_language.ts b/src/plugins/data/public/query/query_string/language_service/lib/lucene_language.ts index f63e0a8b42c6..742747d037e9 100644 --- a/src/plugins/data/public/query/query_string/language_service/lib/lucene_language.ts +++ b/src/plugins/data/public/query/query_string/language_service/lib/lucene_language.ts @@ -24,5 +24,6 @@ export const getLuceneLanguageConfig = ( }, showDocLinks: true, editorSupportedAppNames: ['discover'], + supportedAppNames: ['discover', 'dashboards', 'visualize', 'data-explorer'], }; }; diff --git a/src/plugins/data/public/query/query_string/language_service/types.ts b/src/plugins/data/public/query/query_string/language_service/types.ts index c351cc597917..e82e12f95ec9 100644 --- a/src/plugins/data/public/query/query_string/language_service/types.ts +++ b/src/plugins/data/public/query/query_string/language_service/types.ts @@ -50,4 +50,5 @@ export interface LanguageConfig { }; showDocLinks?: boolean; editorSupportedAppNames?: string[]; + supportedAppNames?: string[]; } diff --git a/src/plugins/discover/public/application/components/top_nav/__snapshots__/open_search_panel.test.tsx.snap b/src/plugins/discover/public/application/components/top_nav/__snapshots__/open_search_panel.test.tsx.snap index 1d35e4e977ba..d4e8ff6ea026 100644 --- a/src/plugins/discover/public/application/components/top_nav/__snapshots__/open_search_panel.test.tsx.snap +++ b/src/plugins/discover/public/application/components/top_nav/__snapshots__/open_search_panel.test.tsx.snap @@ -35,6 +35,9 @@ exports[`render 1`] = ` Array [ Object { "getIconForSavedObject": [Function], + "includeFields": Array [ + "kibanaSavedObjectMeta", + ], "name": "Saved search", "type": "search", }, diff --git a/src/plugins/discover/public/application/components/top_nav/open_search_panel.tsx b/src/plugins/discover/public/application/components/top_nav/open_search_panel.tsx index 1bc4da9a08cf..6bb3a54e71f7 100644 --- a/src/plugins/discover/public/application/components/top_nav/open_search_panel.tsx +++ b/src/plugins/discover/public/application/components/top_nav/open_search_panel.tsx @@ -57,6 +57,7 @@ export function OpenSearchPanel({ onClose, makeUrl }: Props) { services: { core: { uiSettings, savedObjects, application }, addBasePath, + data, }, } = useOpenSearchDashboards(); @@ -87,6 +88,7 @@ export function OpenSearchPanel({ onClose, makeUrl }: Props) { name: i18n.translate('discover.savedSearch.savedObjectName', { defaultMessage: 'Saved search', }), + includeFields: ['kibanaSavedObjectMeta'], }, ]} onChoose={(id) => { @@ -95,6 +97,8 @@ export function OpenSearchPanel({ onClose, makeUrl }: Props) { }} uiSettings={uiSettings} savedObjects={savedObjects} + application={application} + data={data} /> diff --git a/src/plugins/discover/public/embeddable/search_embeddable_factory.tsx b/src/plugins/discover/public/embeddable/search_embeddable_factory.tsx index 8d99b87fbeb2..65db9faaff24 100644 --- a/src/plugins/discover/public/embeddable/search_embeddable_factory.tsx +++ b/src/plugins/discover/public/embeddable/search_embeddable_factory.tsx @@ -55,6 +55,7 @@ export class SearchEmbeddableFactory }), type: 'search', getIconForSavedObject: () => 'search', + includeFields: ['kibanaSavedObjectMeta'], }; constructor(private getStartServices: () => Promise) {} diff --git a/src/plugins/embeddable/public/plugin.tsx b/src/plugins/embeddable/public/plugin.tsx index a0f907043ec4..4ff348a512fc 100644 --- a/src/plugins/embeddable/public/plugin.tsx +++ b/src/plugins/embeddable/public/plugin.tsx @@ -194,7 +194,12 @@ export class EmbeddablePublicPlugin implements Plugin ); diff --git a/src/plugins/query_enhancements/public/plugin.tsx b/src/plugins/query_enhancements/public/plugin.tsx index 5247bb794c96..b6578e1e8fc3 100644 --- a/src/plugins/query_enhancements/public/plugin.tsx +++ b/src/plugins/query_enhancements/public/plugin.tsx @@ -80,6 +80,7 @@ export class QueryEnhancementsPlugin showDocLinks: false, editor: enhancedPPLQueryEditor, editorSupportedAppNames: ['discover'], + supportedAppNames: ['discover', 'data-explorer'], }; queryString.getLanguageService().registerLanguage(pplLanguageConfig); @@ -98,6 +99,7 @@ export class QueryEnhancementsPlugin showDocLinks: false, editor: enhancedSQLQueryEditor, editorSupportedAppNames: ['discover'], + supportedAppNames: ['discover', 'data-explorer'], }; queryString.getLanguageService().registerLanguage(sqlLanguageConfig); diff --git a/src/plugins/saved_objects/public/finder/saved_object_finder.tsx b/src/plugins/saved_objects/public/finder/saved_object_finder.tsx index 5c7f3f1ae031..721b54f68d2a 100644 --- a/src/plugins/saved_objects/public/finder/saved_object_finder.tsx +++ b/src/plugins/saved_objects/public/finder/saved_object_finder.tsx @@ -58,9 +58,12 @@ import { CoreStart, IUiSettingsClient, SavedObjectsStart, + ApplicationStart, } from 'src/core/public'; import { DataSourceAttributes } from 'src/plugins/data_source/common/data_sources'; +import { DataPublicPluginStart, LanguageServiceContract } from 'src/plugins/data/public'; +import { first } from 'rxjs/operators'; import { getIndexPatternTitle } from '../../../data/common/index_patterns/utils'; import { LISTING_LIMIT_SETTING } from '../../common'; @@ -76,6 +79,7 @@ export interface SavedObjectMetaData { interface FinderAttributes { title?: string; type: string; + kibanaSavedObjectMeta?: string; } interface SavedObjectFinderState { @@ -122,6 +126,8 @@ export type SavedObjectFinderProps = SavedObjectFinderFixedPage | SavedObjectFin export type SavedObjectFinderUiProps = { savedObjects: CoreStart['savedObjects']; uiSettings: CoreStart['uiSettings']; + data?: DataPublicPluginStart; + application?: CoreStart['application']; } & SavedObjectFinderProps; class SavedObjectFinderUi extends React.Component< @@ -137,8 +143,29 @@ class SavedObjectFinderUi extends React.Component< showFilter: PropTypes.bool, }; + public async getCurrentAppId() { + return ( + (await this.props?.application?.currentAppId$?.pipe(first()).toPromise()) ?? + Promise.resolve(undefined) + ); + } + + readonly languageService = this.props.data?.query?.queryString?.getLanguageService(); private isComponentMounted: boolean = false; + private isSavedSearchLanguageSupported( + languageId?: string, + currentAppId?: string, + languageService?: LanguageServiceContract + ) { + if (!languageId || !currentAppId || !languageService) { + return true; + } + return ( + languageService?.getLanguage(languageId)?.supportedAppNames?.includes(currentAppId) ?? true + ); + } + private debouncedFetch = _.debounce(async (query: string) => { const metaDataMap = this.getSavedObjectMetaDataMap(); @@ -162,6 +189,8 @@ class SavedObjectFinderUi extends React.Component< return await client.get('data-source', id); }; + const currentAppId = await this.getCurrentAppId(); + const savedObjects = await Promise.all( resp.savedObjects.map(async (obj) => { if (obj.type === 'index-pattern') { @@ -172,6 +201,14 @@ class SavedObjectFinderUi extends React.Component< getDataSource ); return result; + } else if (obj.type === 'search') { + const sourceObject = JSON.parse( + obj.attributes?.kibanaSavedObjectMeta?.searchSourceJSON ?? null + ); + const languageId = sourceObject?.query?.language; + if (this.isSavedSearchLanguageSupported(languageId, currentAppId, this.languageService)) { + return obj; + } } else { return obj; } @@ -179,6 +216,9 @@ class SavedObjectFinderUi extends React.Component< ); resp.savedObjects = savedObjects.filter((savedObject) => { + if (!savedObject) { + return false; + } const metaData = metaDataMap[savedObject.type]; if (metaData.showSavedObject) { return metaData.showSavedObject(savedObject); @@ -571,9 +611,20 @@ class SavedObjectFinderUi extends React.Component< } } -const getSavedObjectFinder = (savedObject: SavedObjectsStart, uiSettings: IUiSettingsClient) => { +const getSavedObjectFinder = ( + savedObject: SavedObjectsStart, + uiSettings: IUiSettingsClient, + data?: DataPublicPluginStart, + application?: ApplicationStart +) => { return (props: SavedObjectFinderProps) => ( - + ); }; diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index bd255b82c6af..911ff931881c 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -64,6 +64,7 @@ import { setEmbeddable, setNotifications, setDocLinks, + setDataStart, } from './services'; import { VISUALIZE_EMBEDDABLE_TYPE, @@ -192,6 +193,7 @@ export class VisualizationsPlugin chrome: core.chrome, overlays: core.overlays, }); + setDataStart(data); setSavedAugmentVisLoader(savedAugmentVisLoader); setI18n(core.i18n); setTypes(types); diff --git a/src/plugins/visualizations/public/services.ts b/src/plugins/visualizations/public/services.ts index 62266ff2ba53..7d517759ea20 100644 --- a/src/plugins/visualizations/public/services.ts +++ b/src/plugins/visualizations/public/services.ts @@ -119,3 +119,5 @@ export const [getSavedAugmentVisLoader, setSavedAugmentVisLoader] = createGetter >('savedAugmentVisLoader'); export const [getDocLinks, setDocLinks] = createGetterSetter('docLinks'); + +export const [getDataStart, setDataStart] = createGetterSetter('DataStart'); diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx index b02ba449dec1..00a2253ea3ee 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx @@ -34,6 +34,7 @@ import { EuiModal } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import { METRIC_TYPE, UiStatsMetricType } from '@osd/analytics'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; import { ApplicationStart, IUiSettingsClient, SavedObjectsStart } from '../../../../core/public'; import { SearchSelection } from './search_selection'; import { TypeSelection } from './type_selection'; @@ -55,6 +56,7 @@ interface TypeSelectionProps { outsideVisualizeApp?: boolean; stateTransfer?: EmbeddableStateTransfer; originatingApp?: string; + data: DataPublicPluginStart; } interface TypeSelectionState { @@ -112,6 +114,8 @@ class NewVisModal extends React.Component ) : ( diff --git a/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx b/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx index 9f98f7520103..2a0ce51a6d8e 100644 --- a/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx +++ b/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx @@ -32,7 +32,8 @@ import { EuiModalBody, EuiModalHeader, EuiModalHeaderTitle } from '@elastic/eui' import { i18n } from '@osd/i18n'; import { FormattedMessage } from '@osd/i18n/react'; import React from 'react'; -import { IUiSettingsClient, SavedObjectsStart } from '../../../../../core/public'; +import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { ApplicationStart, IUiSettingsClient, SavedObjectsStart } from '../../../../../core/public'; import { SavedObjectFinderUi } from '../../../../saved_objects/public'; import { VisType } from '../../vis_types'; @@ -42,6 +43,8 @@ interface SearchSelectionProps { visType: VisType; uiSettings: IUiSettingsClient; savedObjects: SavedObjectsStart; + data: DataPublicPluginStart; + application: ApplicationStart; } export class SearchSelection extends React.Component { @@ -85,6 +88,7 @@ export class SearchSelection extends React.Component { defaultMessage: 'Saved search', } ), + includeFields: ['kibanaSavedObjectMeta'], }, { type: 'index-pattern', @@ -100,6 +104,8 @@ export class SearchSelection extends React.Component { fixedPageSize={this.fixedPageSize} uiSettings={this.props.uiSettings} savedObjects={this.props.savedObjects} + application={this.props.application} + data={this.props.data} /> diff --git a/src/plugins/visualizations/public/wizard/show_new_vis.tsx b/src/plugins/visualizations/public/wizard/show_new_vis.tsx index a9dad7f026b6..5bd83d9bd3c7 100644 --- a/src/plugins/visualizations/public/wizard/show_new_vis.tsx +++ b/src/plugins/visualizations/public/wizard/show_new_vis.tsx @@ -41,6 +41,7 @@ import { getUsageCollector, getApplication, getEmbeddable, + getDataStart, } from '../services'; export interface ShowNewVisModalParams { @@ -90,6 +91,7 @@ export function showNewVisModal({ savedObjects={getSavedObjects()} usageCollection={getUsageCollector()} application={getApplication()} + data={getDataStart()} /> );