From 2e379a589d5c710dbbc58381b7b98a22f94d18ef Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Thu, 5 Dec 2024 15:09:51 -0600 Subject: [PATCH] [Search] Search Playground - shared rendering (#201302) --- config/serverless.es.yml | 3 - config/serverless.oblt.yml | 1 + config/serverless.security.yml | 1 + packages/deeplinks/search/constants.ts | 2 +- packages/deeplinks/search/deep_links.ts | 6 +- packages/deeplinks/search/index.ts | 1 + .../collectors/application_usage/schema.ts | 1 + src/plugins/telemetry/schema/oss_plugins.json | 131 ++++++++++++++++++ .../common/locators/index.ts | 2 - .../common/locators/playground_locator.tsx | 28 ---- .../__mocks__/kea_logic/kibana_logic.mock.ts | 2 - .../components/layout/page_template.tsx | 9 +- .../playground/header_docs_action.tsx | 27 ---- .../components/playground/page_template.tsx | 71 ---------- .../components/playground/playground.tsx | 46 ------ .../components/playground/types.ts | 19 --- .../components/playground_redirect.tsx | 22 +++ .../applications/applications/index.tsx | 24 +--- .../applications/applications/routes.ts | 3 - .../components/whats_next_box.tsx | 23 ++- .../create_connector/finish_up_step.tsx | 23 ++- .../search_playground_popover.tsx | 21 +-- .../public/applications/index.tsx | 1 - .../shared/kibana/kibana_logic.ts | 4 - .../applications/shared/layout/base_nav.tsx | 2 +- .../shared/layout/classic_nav_helpers.test.ts | 2 +- .../applications/shared/layout/nav.test.tsx | 6 +- .../test_helpers/test_utils.test_helper.tsx | 2 - .../public/navigation_tree.ts | 2 +- .../enterprise_search/public/plugin.ts | 12 +- .../__mocks__/search_playground_mock.ts | 24 ---- .../plugins/search_playground/common/index.ts | 5 +- x-pack/plugins/search_playground/kibana.jsonc | 3 + .../search_playground/public/embeddable.tsx | 34 ----- .../hooks/use_playground_breadcrumbs.ts | 25 ++++ .../public/playground_overview.tsx | 11 +- .../search_playground/public/plugin.ts | 55 ++++++-- .../plugins/search_playground/public/types.ts | 47 +++---- .../search_playground/server/config.ts | 2 +- .../search_playground/server/plugin.ts | 46 +++++- .../search_playground/server/routes.ts | 41 ++++++ .../plugins/search_playground/server/types.ts | 10 +- .../plugins/search_playground/tsconfig.json | 7 +- .../search_navigation/public/plugin.ts | 56 +++++++- .../search_navigation/public/types.ts | 16 ++- .../search_navigation/tsconfig.json | 3 - x-pack/plugins/serverless_search/kibana.jsonc | 1 + .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../apis/features/features/features.ts | 2 + .../apis/security/privileges.ts | 1 + .../apis/security/privileges_basic.ts | 2 + .../tests/solution_navigation.ts | 8 +- .../spaces_only/telemetry/telemetry.ts | 1 + .../security_and_spaces/tests/catalogue.ts | 1 + .../security_and_spaces/tests/nav_links.ts | 1 + 57 files changed, 485 insertions(+), 420 deletions(-) delete mode 100644 x-pack/plugins/enterprise_search/common/locators/playground_locator.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/applications/components/playground/header_docs_action.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/applications/components/playground/page_template.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/applications/components/playground/playground.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/applications/components/playground/types.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/applications/components/playground_redirect.tsx delete mode 100644 x-pack/plugins/search_playground/__mocks__/search_playground_mock.ts delete mode 100644 x-pack/plugins/search_playground/public/embeddable.tsx create mode 100644 x-pack/plugins/search_playground/public/hooks/use_playground_breadcrumbs.ts diff --git a/config/serverless.es.yml b/config/serverless.es.yml index 3132125bfecde..127a0c8362d7f 100644 --- a/config/serverless.es.yml +++ b/config/serverless.es.yml @@ -116,9 +116,6 @@ xpack.ml.compatibleModuleType: 'search' data_visualizer.resultLinks.fileBeat.enabled: false -# Search Playground -xpack.searchPlayground.ui.enabled: true - # Search InferenceEndpoints xpack.searchInferenceEndpoints.ui.enabled: true diff --git a/config/serverless.oblt.yml b/config/serverless.oblt.yml index 4f2e5a0883b52..ef3c9fd23121e 100644 --- a/config/serverless.oblt.yml +++ b/config/serverless.oblt.yml @@ -7,6 +7,7 @@ xpack.infra.enabled: true xpack.uptime.enabled: true xpack.securitySolution.enabled: false xpack.search.notebooks.enabled: false +xpack.searchPlayground.enabled: false ## Fine-tune the observability solution feature privileges. Also, refer to `serverless.yml` for the project-agnostic overrides. xpack.features.overrides: diff --git a/config/serverless.security.yml b/config/serverless.security.yml index d92075fbb3fdc..1b75b4b06cb25 100644 --- a/config/serverless.security.yml +++ b/config/serverless.security.yml @@ -8,6 +8,7 @@ xpack.observabilityLogsExplorer.enabled: false xpack.observability.enabled: false xpack.observabilityAIAssistant.enabled: false xpack.search.notebooks.enabled: false +xpack.searchPlayground.enabled: false ## Fine-tune the security solution feature privileges. Also, refer to `serverless.yml` for the project-agnostic overrides. xpack.features.overrides: diff --git a/packages/deeplinks/search/constants.ts b/packages/deeplinks/search/constants.ts index 6d9f6492abda7..a458b38aff3cc 100644 --- a/packages/deeplinks/search/constants.ts +++ b/packages/deeplinks/search/constants.ts @@ -17,7 +17,7 @@ export const ENTERPRISE_SEARCH_WORKPLACESEARCH_APP_ID = 'workplaceSearch'; export const SERVERLESS_ES_APP_ID = 'serverlessElasticsearch'; export const SERVERLESS_ES_CONNECTORS_ID = 'serverlessConnectors'; export const SERVERLESS_ES_WEB_CRAWLERS_ID = 'serverlessWebCrawlers'; -export const SERVERLESS_ES_SEARCH_PLAYGROUND_ID = 'searchPlayground'; +export const ES_SEARCH_PLAYGROUND_ID = 'searchPlayground'; export const SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID = 'searchInferenceEndpoints'; export const SEARCH_HOMEPAGE = 'searchHomepage'; export const SEARCH_INDICES_START = 'elasticsearchStart'; diff --git a/packages/deeplinks/search/deep_links.ts b/packages/deeplinks/search/deep_links.ts index 9dc9a8ed18203..ede9bc303dbe5 100644 --- a/packages/deeplinks/search/deep_links.ts +++ b/packages/deeplinks/search/deep_links.ts @@ -18,7 +18,7 @@ import { ENTERPRISE_SEARCH_ANALYTICS_APP_ID, ENTERPRISE_SEARCH_APPSEARCH_APP_ID, ENTERPRISE_SEARCH_WORKPLACESEARCH_APP_ID, - SERVERLESS_ES_SEARCH_PLAYGROUND_ID, + ES_SEARCH_PLAYGROUND_ID, SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID, SEARCH_HOMEPAGE, SEARCH_INDICES_START, @@ -40,7 +40,7 @@ export type EnterpriseSearchWorkplaceSearchApp = typeof ENTERPRISE_SEARCH_WORKPL export type ServerlessSearchApp = typeof SERVERLESS_ES_APP_ID; export type ConnectorsId = typeof SERVERLESS_ES_CONNECTORS_ID; export type ServerlessWebCrawlers = typeof SERVERLESS_ES_WEB_CRAWLERS_ID; -export type SearchPlaygroundId = typeof SERVERLESS_ES_SEARCH_PLAYGROUND_ID; +export type SearchPlaygroundId = typeof ES_SEARCH_PLAYGROUND_ID; export type SearchInferenceEndpointsId = typeof SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID; export type SearchHomepage = typeof SEARCH_HOMEPAGE; export type SearchStart = typeof SEARCH_INDICES_START; @@ -52,7 +52,7 @@ export type SearchAISearch = typeof SEARCH_AI_SEARCH; export type ContentLinkId = 'searchIndices' | 'connectors' | 'webCrawlers'; -export type ApplicationsLinkId = 'searchApplications' | 'playground'; +export type ApplicationsLinkId = 'searchApplications'; export type AppsearchLinkId = 'engines'; diff --git a/packages/deeplinks/search/index.ts b/packages/deeplinks/search/index.ts index 7c78d64081133..69110f36deb45 100644 --- a/packages/deeplinks/search/index.ts +++ b/packages/deeplinks/search/index.ts @@ -21,6 +21,7 @@ export { SEARCH_VECTOR_SEARCH, SEARCH_SEMANTIC_SEARCH, SEARCH_AI_SEARCH, + ES_SEARCH_PLAYGROUND_ID, } from './constants'; export type { diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts index ad2dce80fb650..dd327dd4706d5 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts @@ -137,6 +137,7 @@ export const applicationUsageSchema = { enterpriseSearch: commonSchema, enterpriseSearchContent: commonSchema, searchInferenceEndpoints: commonSchema, + searchPlayground: commonSchema, enterpriseSearchAnalytics: commonSchema, enterpriseSearchApplications: commonSchema, enterpriseSearchAISearch: commonSchema, diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 35e0242b57624..e4423a9b30743 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -2229,6 +2229,137 @@ } } }, + "searchPlayground": { + "properties": { + "appId": { + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } + }, + "viewId": { + "type": "keyword", + "_meta": { + "description": "Always `main`" + } + }, + "clicks_total": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application since we started counting them" + } + }, + "clicks_7_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 7 days" + } + }, + "clicks_30_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 30 days" + } + }, + "clicks_90_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application over the last 90 days" + } + }, + "minutes_on_screen_total": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen since we started counting them." + } + }, + "minutes_on_screen_7_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 7 days" + } + }, + "minutes_on_screen_30_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 30 days" + } + }, + "minutes_on_screen_90_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen over the last 90 days" + } + }, + "views": { + "type": "array", + "items": { + "properties": { + "appId": { + "type": "keyword", + "_meta": { + "description": "The application being tracked" + } + }, + "viewId": { + "type": "keyword", + "_meta": { + "description": "The application view being tracked" + } + }, + "clicks_total": { + "type": "long", + "_meta": { + "description": "General number of clicks in the application sub view since we started counting them" + } + }, + "clicks_7_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 7 days" + } + }, + "clicks_30_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 30 days" + } + }, + "clicks_90_days": { + "type": "long", + "_meta": { + "description": "General number of clicks in the active application sub view over the last 90 days" + } + }, + "minutes_on_screen_total": { + "type": "float", + "_meta": { + "description": "Minutes the application sub view is active and on-screen since we started counting them." + } + }, + "minutes_on_screen_7_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 7 days" + } + }, + "minutes_on_screen_30_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 30 days" + } + }, + "minutes_on_screen_90_days": { + "type": "float", + "_meta": { + "description": "Minutes the application is active and on-screen active application sub view over the last 90 days" + } + } + } + } + } + } + }, "enterpriseSearchAnalytics": { "properties": { "appId": { diff --git a/x-pack/plugins/enterprise_search/common/locators/index.ts b/x-pack/plugins/enterprise_search/common/locators/index.ts index 35c1d43b3b30a..3c3597fe4f161 100644 --- a/x-pack/plugins/enterprise_search/common/locators/index.ts +++ b/x-pack/plugins/enterprise_search/common/locators/index.ts @@ -13,10 +13,8 @@ import { type CreateIndexLocatorParams, } from './create_index_locator'; import { SearchInferenceEndpointLocatorDefinition } from './inference_locator'; -import { PlaygroundLocatorDefinition, type PlaygroundLocatorParams } from './playground_locator'; export function registerLocators(share: SharePluginSetup) { share.url.locators.create(new CreateIndexLocatorDefinition()); - share.url.locators.create(new PlaygroundLocatorDefinition()); share.url.locators.create(new SearchInferenceEndpointLocatorDefinition()); } diff --git a/x-pack/plugins/enterprise_search/common/locators/playground_locator.tsx b/x-pack/plugins/enterprise_search/common/locators/playground_locator.tsx deleted file mode 100644 index eca283c8c2b06..0000000000000 --- a/x-pack/plugins/enterprise_search/common/locators/playground_locator.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { LocatorDefinition } from '@kbn/share-plugin/common'; -import type { SerializableRecord } from '@kbn/utility-types'; - -import { APPLICATIONS_PLUGIN, PLAYGROUND_URL } from '../constants'; - -export type PlaygroundLocatorParams = { 'default-index': string } & SerializableRecord; - -export class PlaygroundLocatorDefinition implements LocatorDefinition { - public readonly getLocation = async (params: PlaygroundLocatorParams) => { - const defaultIndex = params['default-index']; - const path = `${PLAYGROUND_URL}${defaultIndex ? `?default-index=${defaultIndex}` : ''}`; - - return { - app: APPLICATIONS_PLUGIN.ID, - path, - state: {}, - }; - }; - - public readonly id = 'PLAYGROUND_LOCATOR_ID'; -} diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts index 5548228b9b64c..7af3dbc94343d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/kibana_logic.mock.ts @@ -16,7 +16,6 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { LensPublicStart } from '@kbn/lens-plugin/public'; import { mlPluginMock } from '@kbn/ml-plugin/public/mocks'; -import { searchPlaygroundMock } from '@kbn/search-playground/__mocks__/search_playground_mock'; import { securityMock } from '@kbn/security-plugin/public/mocks'; import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; @@ -67,7 +66,6 @@ export const mockKibanaValues = { }, renderHeaderActions: jest.fn(), searchInferenceEndpoints: null, - searchPlayground: searchPlaygroundMock.createStart(), security: securityMock.createStart(), setBreadcrumbs: jest.fn(), setChromeIsVisible: jest.fn(), diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/layout/page_template.tsx index ec745ce77be2f..cc01ab52239e3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/applications/components/layout/page_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/applications/components/layout/page_template.tsx @@ -19,14 +19,12 @@ import { SetEnterpriseSearchApplicationsChrome } from '../../../shared/kibana_ch import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; import { useEnterpriseSearchApplicationNav } from '../../../shared/layout'; import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry'; -import { PlaygroundHeaderDocsAction } from '../playground/header_docs_action'; import { SearchApplicationHeaderDocsAction } from '../search_application/header_docs_action'; export type EnterpriseSearchApplicationsPageTemplateProps = Omit< PageTemplateProps, 'useEndpointHeaderActions' > & { - docLink?: 'search_application' | 'playground'; hasSchemaConflicts?: boolean; restrictWidth?: boolean; searchApplicationName?: string; @@ -41,7 +39,6 @@ export const EnterpriseSearchApplicationsPageTemplate: React.FC< searchApplicationName, hasSchemaConflicts, restrictWidth = true, - docLink = 'search_application', ...pageTemplateProps }) => { const alwaysReturnNavItems = true; @@ -72,11 +69,7 @@ export const EnterpriseSearchApplicationsPageTemplate: React.FC< ); useLayoutEffect(() => { - const docAction = { - playground: PlaygroundHeaderDocsAction, - search_application: SearchApplicationHeaderDocsAction, - }[docLink]; - renderHeaderActions(docAction); + renderHeaderActions(SearchApplicationHeaderDocsAction); return () => { renderHeaderActions(); diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/header_docs_action.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/header_docs_action.tsx deleted file mode 100644 index 9f834666a6894..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/header_docs_action.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { useValues } from 'kea'; - -import { KibanaLogic } from '../../../shared/kibana'; - -import { EndpointsHeaderAction } from '../../../shared/layout/endpoints_header_action'; - -export const PlaygroundHeaderDocsAction: React.FC = () => { - const { searchPlayground } = useValues(KibanaLogic); - - if (!searchPlayground) { - return null; - } - return ( - - - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/page_template.tsx deleted file mode 100644 index 40698b273730b..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/page_template.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useLayoutEffect } from 'react'; - -import { useValues } from 'kea'; - -import useObservable from 'react-use/lib/useObservable'; - -import { SEARCH_PRODUCT_NAME } from '../../../../../common/constants'; -import { KibanaLogic } from '../../../shared/kibana'; -import { SetSearchPlaygroundChrome } from '../../../shared/kibana_chrome/set_chrome'; -import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; -import { useEnterpriseSearchNav } from '../../../shared/layout'; -import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry'; - -import { PlaygroundHeaderDocsAction } from './header_docs_action'; - -export type SearchPlaygroundPageTemplateProps = Omit< - PageTemplateProps, - 'useEndpointHeaderActions' -> & { - hasSchemaConflicts?: boolean; - restrictWidth?: boolean; - searchApplicationName?: string; -}; - -export const SearchPlaygroundPageTemplate: React.FC = ({ - children, - pageChrome, - pageViewTelemetry, - searchApplicationName, - hasSchemaConflicts, - restrictWidth = true, - ...pageTemplateProps -}) => { - const navItems = useEnterpriseSearchNav(); - - const { renderHeaderActions, getChromeStyle$ } = useValues(KibanaLogic); - const chromeStyle = useObservable(getChromeStyle$(), 'classic'); - - useLayoutEffect(() => { - renderHeaderActions(PlaygroundHeaderDocsAction); - - return () => { - renderHeaderActions(); - }; - }, []); - - return ( - } - useEndpointHeaderActions={false} - > - {pageViewTelemetry && ( - - )} - {children} - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/playground.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/playground.tsx deleted file mode 100644 index c198062cb759b..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/playground.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { useValues } from 'kea'; - -import { i18n } from '@kbn/i18n'; - -import { KibanaLogic } from '../../../shared/kibana'; - -import { SearchPlaygroundPageTemplate } from './page_template'; - -interface PlaygroundProps { - pageMode?: 'chat' | 'search'; -} - -export const Playground: React.FC = ({ pageMode = 'chat' }) => { - const { searchPlayground } = useValues(KibanaLogic); - - if (!searchPlayground) { - return null; - } - return ( - - - - - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/types.ts b/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/types.ts deleted file mode 100644 index 71a46c5c9a1bc..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground/types.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export enum MessageRole { - 'user' = 'user', - 'assistant' = 'assistant', - 'system' = 'system', -} - -export interface Message { - id: string; - content: string | React.ReactNode; - createdAt?: Date; - role: MessageRole; -} diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/components/playground_redirect.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/components/playground_redirect.tsx new file mode 100644 index 0000000000000..ba9efbd45be57 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/applications/components/playground_redirect.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect } from 'react'; + +import { ES_SEARCH_PLAYGROUND_ID } from '@kbn/deeplinks-search'; + +import { useKibana } from '@kbn/kibana-react-plugin/public'; + +export const PlaygroundRedirect: React.FC = () => { + const { application } = useKibana().services; + + useEffect(() => { + application?.navigateToApp(ES_SEARCH_PLAYGROUND_ID); + }, [application]); + + return null; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/applications/index.tsx index a04ebf2e3edbb..2a10eac6af7bd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/applications/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/applications/index.tsx @@ -6,35 +6,19 @@ */ import React from 'react'; -import { Redirect } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; import { NotFound } from './components/not_found'; -import { Playground } from './components/playground/playground'; +import { PlaygroundRedirect } from './components/playground_redirect'; import { SearchApplicationsRouter } from './components/search_applications/search_applications_router'; -import { - PLAYGROUND_CHAT_PATH, - PLAYGROUND_PATH, - PLAYGROUND_SEARCH_PATH, - ROOT_PATH, - SEARCH_APPLICATIONS_PATH, -} from './routes'; +import { ROOT_PATH, SEARCH_APPLICATIONS_PATH } from './routes'; export const Applications = () => { return ( - - - - - - - - - - - + + diff --git a/x-pack/plugins/enterprise_search/public/applications/applications/routes.ts b/x-pack/plugins/enterprise_search/public/applications/applications/routes.ts index 2df42a129938c..dd79fbc9ea5ae 100644 --- a/x-pack/plugins/enterprise_search/public/applications/applications/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/applications/routes.ts @@ -17,9 +17,6 @@ export enum SearchApplicationViewTabs { export const SEARCH_APPLICATION_CREATION_PATH = `${SEARCH_APPLICATIONS_PATH}/new`; export const SEARCH_APPLICATION_PATH = `${SEARCH_APPLICATIONS_PATH}/:searchApplicationName`; export const SEARCH_APPLICATION_TAB_PATH = `${SEARCH_APPLICATION_PATH}/:tabId`; -export const PLAYGROUND_PATH = `${ROOT_PATH}playground/`; -export const PLAYGROUND_CHAT_PATH = `${PLAYGROUND_PATH}chat`; -export const PLAYGROUND_SEARCH_PATH = `${PLAYGROUND_PATH}search`; export const SEARCH_APPLICATION_CONNECT_PATH = `${SEARCH_APPLICATION_PATH}/${SearchApplicationViewTabs.CONNECT}/:connectTabId`; export enum SearchApplicationConnectTabs { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/components/whats_next_box.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/components/whats_next_box.tsx index 2e04c094e7d7e..7e65b4d3367b8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/components/whats_next_box.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/connector_detail/components/whats_next_box.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; import { useValues } from 'kea'; @@ -25,9 +25,6 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { ConnectorStatus } from '@kbn/search-connectors'; -import { APPLICATIONS_PLUGIN } from '../../../../../../common/constants'; - -import { PLAYGROUND_PATH } from '../../../../applications/routes'; import { generateEncodedPath } from '../../../../shared/encode_path_params'; import { KibanaLogic } from '../../../../shared/kibana'; import { EuiButtonTo } from '../../../../shared/react_router_helpers'; @@ -53,7 +50,14 @@ export const WhatsNextBox: React.FC = ({ isSyncing = false, isWaitingForConnector = false, }) => { - const { navigateToUrl } = useValues(KibanaLogic); + const { share } = useValues(KibanaLogic); + const onStartPlaygroundClick = useCallback(() => { + if (!share) return; + const playgroundLocator = share.url.locators.get('PLAYGROUND_LOCATOR_ID'); + if (playgroundLocator) { + playgroundLocator.navigate({ 'default-index': connectorIndex }); + } + }, [connectorIndex, share]); const isConfigured = !( connectorStatus === ConnectorStatus.NEEDS_CONFIGURATION || connectorStatus === ConnectorStatus.CREATED @@ -84,14 +88,7 @@ export const WhatsNextBox: React.FC = ({ data-test-subj="enterpriseSearchWhatsNextBoxSearchPlaygroundButton" iconType="sparkles" disabled={!connectorIndex || disabled} - onClick={() => { - navigateToUrl( - `${APPLICATIONS_PLUGIN.URL}${PLAYGROUND_PATH}?default-index=${connectorIndex}`, - { - shouldNotCreateHref: true, - } - ); - }} + onClick={onStartPlaygroundClick} > = ({ title }) => { const isSyncing = isWaitingForSync || isSyncingProp; const { http } = useValues(HttpLogic); - const { application } = useValues(KibanaLogic); + const { application, share } = useValues(KibanaLogic); + const onStartPlaygroundClick = useCallback(() => { + if (!share) return; + const playgroundLocator = share.url.locators.get('PLAYGROUND_LOCATOR_ID'); + if (playgroundLocator) { + playgroundLocator.navigate({ 'default-index': connector?.index_name }); + } + }, [connector, share]); useEffect(() => { setTimeout(() => { window.scrollTo({ @@ -134,14 +140,7 @@ export const FinishUpStep: React.FC = ({ title }) => { 'xpack.enterpriseSearch.createConnector.finishUpStep.euiButton.startSearchPlaygroundLabel', { defaultMessage: 'Start Search Playground' } )} - onClick={() => { - if (connector) { - KibanaLogic.values.navigateToUrl( - `${APPLICATIONS_PLUGIN.URL}${PLAYGROUND_PATH}?default-index=${connector.index_name}`, - { shouldNotCreateHref: true } - ); - } - }} + onClick={onStartPlaygroundClick} > {i18n.translate( 'xpack.enterpriseSearch.createConnector.finishUpStep.startSearchPlaygroundButtonLabel', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/search_playground_popover.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/search_playground_popover.tsx index 283d594e2891b..8b85ab9b97168 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/search_playground_popover.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/search_playground_popover.tsx @@ -5,14 +5,14 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback } from 'react'; + +import { useValues } from 'kea'; import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { APPLICATIONS_PLUGIN } from '../../../../../../../common/constants'; -import { PLAYGROUND_PATH } from '../../../../../applications/routes'; import { KibanaLogic } from '../../../../../shared/kibana'; export interface SearchPlaygroundPopoverProps { @@ -24,18 +24,21 @@ export const SearchPlaygroundPopover: React.FC = ( indexName, ingestionMethod, }) => { - const playgroundUrl = `${APPLICATIONS_PLUGIN.URL}${PLAYGROUND_PATH}?default-index=${indexName}`; + const { share } = useValues(KibanaLogic); + const onStartPlaygroundClick = useCallback(() => { + if (!share) return; + const playgroundLocator = share.url.locators.get('PLAYGROUND_LOCATOR_ID'); + if (playgroundLocator) { + playgroundLocator.navigate({ 'default-index': indexName }); + } + }, [indexName, share]); return ( { - KibanaLogic.values.navigateToUrl(playgroundUrl, { - shouldNotCreateHref: true, - }); - }} + onClick={onStartPlaygroundClick} > {i18n.translate('xpack.enterpriseSearch.content.index.viewPlayground', { defaultMessage: 'View in Playground', diff --git a/x-pack/plugins/enterprise_search/public/applications/index.tsx b/x-pack/plugins/enterprise_search/public/applications/index.tsx index fe3e7a84147ba..8cefb4cb733e5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/index.tsx @@ -129,7 +129,6 @@ export const renderApp = ( params.setHeaderActionMenu( HeaderActions ? renderHeaderActions.bind(null, HeaderActions, store, params) : undefined ), - searchPlayground: plugins.searchPlayground, searchInferenceEndpoints: plugins.searchInferenceEndpoints, security, setBreadcrumbs: chrome.setBreadcrumbs, diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts index b404d0e8fb65d..02a00a3198ee2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts @@ -30,7 +30,6 @@ import { MlPluginStart } from '@kbn/ml-plugin/public'; import { ELASTICSEARCH_URL_PLACEHOLDER } from '@kbn/search-api-panels/constants'; import { ConnectorDefinition } from '@kbn/search-connectors'; import { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public'; -import { SearchPlaygroundPluginStart } from '@kbn/search-playground/public'; import { AuthenticatedUser, SecurityPluginStart } from '@kbn/security-plugin/public'; import { SharePluginStart } from '@kbn/share-plugin/public'; @@ -68,7 +67,6 @@ export interface KibanaLogicProps { productFeatures: ProductFeatures; renderHeaderActions(HeaderActions?: FC): void; searchInferenceEndpoints?: SearchInferenceEndpointsPluginStart; - searchPlayground?: SearchPlaygroundPluginStart; security?: SecurityPluginStart; setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void; setChromeIsVisible(isVisible: boolean): void; @@ -103,7 +101,6 @@ export interface KibanaValues { productFeatures: ProductFeatures; renderHeaderActions(HeaderActions?: FC): void; searchInferenceEndpoints: SearchInferenceEndpointsPluginStart | null; - searchPlayground: SearchPlaygroundPluginStart | null; security: SecurityPluginStart | null; setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void; setChromeIsVisible(isVisible: boolean): void; @@ -150,7 +147,6 @@ export const KibanaLogic = kea>({ productFeatures: [props.productFeatures, {}], renderHeaderActions: [props.renderHeaderActions, {}], searchInferenceEndpoints: [props.searchInferenceEndpoints || null, {}], - searchPlayground: [props.searchPlayground || null, {}], security: [props.security || null, {}], setBreadcrumbs: [props.setBreadcrumbs, {}], setChromeIsVisible: [props.setChromeIsVisible, {}], diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/base_nav.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/base_nav.tsx index a8fff53d8a9b2..0c1e959f7b507 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/base_nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/base_nav.tsx @@ -88,7 +88,7 @@ export const buildBaseClassicNavItems = ({ { 'data-test-subj': 'searchSideNav-Playground', deepLink: { - link: 'enterpriseSearchApplications:playground', + link: 'searchPlayground', shouldShowActiveForSubroutes: true, }, id: 'playground', diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/classic_nav_helpers.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/layout/classic_nav_helpers.test.ts index 80e846716e59b..50c5841092a6d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/classic_nav_helpers.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/classic_nav_helpers.test.ts @@ -133,7 +133,7 @@ describe('generateSideNavItems', () => { }, { deepLink: { - link: 'enterpriseSearchApplications:playground', + link: 'searchPlayground', }, id: 'unit-test-missing', }, diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx index fed85bad23353..08976a4dc68c1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx @@ -73,7 +73,7 @@ const baseNavItems = [ items: [ { 'data-test-subj': 'searchSideNav-Playground', - href: '/app/enterprise_search/applications/playground', + href: '/app/search_playground', id: 'playground', items: undefined, name: 'Playground', @@ -188,9 +188,9 @@ const mockNavLinks = [ url: '/app/enterprise_search/content/crawlers', }, { - id: 'enterpriseSearchApplications:playground', + id: 'searchPlayground', title: 'Playground', - url: '/app/enterprise_search/applications/playground', + url: '/app/search_playground', }, { id: 'enterpriseSearchApplications:searchApplications', diff --git a/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx b/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx index da30e6e93fadb..e046bfa904e55 100644 --- a/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx @@ -24,7 +24,6 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { I18nProvider } from '@kbn/i18n-react'; import { LensPublicStart } from '@kbn/lens-plugin/public'; import { mlPluginMock } from '@kbn/ml-plugin/public/mocks'; -import { searchPlaygroundMock } from '@kbn/search-playground/__mocks__/search_playground_mock'; import { securityMock } from '@kbn/security-plugin/public/mocks'; import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; @@ -86,7 +85,6 @@ export const mockKibanaProps: KibanaLogicProps = { hasWebCrawler: true, }, renderHeaderActions: jest.fn(), - searchPlayground: searchPlaygroundMock.createStart(), security: securityMock.createStart(), setBreadcrumbs: jest.fn(), setChromeIsVisible: jest.fn(), diff --git a/x-pack/plugins/enterprise_search/public/navigation_tree.ts b/x-pack/plugins/enterprise_search/public/navigation_tree.ts index 25ad8ec37743f..dfd639a075520 100644 --- a/x-pack/plugins/enterprise_search/public/navigation_tree.ts +++ b/x-pack/plugins/enterprise_search/public/navigation_tree.ts @@ -151,7 +151,7 @@ export const getNavigationTreeDefinition = ({ { children: [ { - link: 'enterpriseSearchApplications:playground', + link: 'searchPlayground', }, { getIsActive: ({ pathNameSerialized, prepend }) => { diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts index a413ae5f2067d..aa0a2e37c599c 100644 --- a/x-pack/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/plugins/enterprise_search/public/plugin.ts @@ -60,7 +60,7 @@ import { ClientConfigType, InitialAppData, ProductAccess } from '../common/types import { hasEnterpriseLicense } from '../common/utils/licensing'; import { ENGINES_PATH } from './applications/app_search/routes'; -import { SEARCH_APPLICATIONS_PATH, PLAYGROUND_PATH } from './applications/applications/routes'; +import { SEARCH_APPLICATIONS_PATH } from './applications/applications/routes'; import { CONNECTORS_PATH, SEARCH_INDICES_PATH, @@ -151,14 +151,6 @@ const relevanceLinks: AppDeepLink[] = [ ]; const applicationsLinks: AppDeepLink[] = [ - { - id: 'playground', - path: `/${PLAYGROUND_PATH}`, - title: i18n.translate('xpack.enterpriseSearch.navigation.contentPlaygroundLinkLabel', { - defaultMessage: 'Playground', - }), - visibleIn: ['sideNav', 'globalSearch'], - }, { id: 'searchApplications', path: `/${SEARCH_APPLICATIONS_PATH}`, @@ -281,6 +273,7 @@ export class EnterpriseSearchPlugin implements Plugin { return renderApp(EnterpriseSearchOverview, kibanaDeps, pluginData); }, + order: 0, title: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAV_TITLE, visibleIn: ['home', 'kibanaOverview', 'globalSearch', 'sideNav'], }); @@ -306,6 +299,7 @@ export class EnterpriseSearchPlugin implements Plugin { return renderApp(EnterpriseSearchContent, kibanaDeps, pluginData); }, + order: 1, title: ENTERPRISE_SEARCH_CONTENT_PLUGIN.NAV_TITLE, }); diff --git a/x-pack/plugins/search_playground/__mocks__/search_playground_mock.ts b/x-pack/plugins/search_playground/__mocks__/search_playground_mock.ts deleted file mode 100644 index 1a73128730324..0000000000000 --- a/x-pack/plugins/search_playground/__mocks__/search_playground_mock.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { SearchPlaygroundPluginStart } from '../public'; - -export type Start = jest.Mocked; - -const createStartMock = (): Start => { - const startContract: Start = { - PlaygroundProvider: jest.fn(), - Playground: jest.fn(), - PlaygroundHeaderDocs: jest.fn(), - }; - - return startContract; -}; - -export const searchPlaygroundMock = { - createStart: createStartMock, -}; diff --git a/x-pack/plugins/search_playground/common/index.ts b/x-pack/plugins/search_playground/common/index.ts index 95624681b6193..5d972f6a17e0c 100644 --- a/x-pack/plugins/search_playground/common/index.ts +++ b/x-pack/plugins/search_playground/common/index.ts @@ -5,10 +5,13 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; import { Pagination } from './types'; export const PLUGIN_ID = 'searchPlayground'; -export const PLUGIN_NAME = 'Playground'; +export const PLUGIN_NAME = i18n.translate('xpack.searchPlayground.plugin.name', { + defaultMessage: 'Playground', +}); export const PLUGIN_PATH = '/app/search_playground'; export const SEARCH_MODE_FEATURE_FLAG_ID = 'searchPlayground:searchModeEnabled'; diff --git a/x-pack/plugins/search_playground/kibana.jsonc b/x-pack/plugins/search_playground/kibana.jsonc index 3c4eaaddc81a2..794e1760efbd2 100644 --- a/x-pack/plugins/search_playground/kibana.jsonc +++ b/x-pack/plugins/search_playground/kibana.jsonc @@ -18,7 +18,9 @@ "actions", "data", "encryptedSavedObjects", + "licensing", "ml", + "features", "navigation", "share", "security", @@ -29,6 +31,7 @@ "cloud", "console", "usageCollection", + "searchNavigation", ], "requiredBundles": [ "kibanaReact", diff --git a/x-pack/plugins/search_playground/public/embeddable.tsx b/x-pack/plugins/search_playground/public/embeddable.tsx deleted file mode 100644 index 21688f5e47387..0000000000000 --- a/x-pack/plugins/search_playground/public/embeddable.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { dynamic } from '@kbn/shared-ux-utility'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { CoreStart } from '@kbn/core-lifecycle-browser'; -import { AppPluginStartDependencies } from './types'; -import { AppProps } from './components/app'; - -export const Playground = dynamic>(async () => ({ - default: (await import('./components/app')).App, -})); - -export const PlaygroundProvider = dynamic(async () => ({ - default: (await import('./providers/playground_provider')).PlaygroundProvider, -})); - -export const PlaygroundHeaderDocs = dynamic(async () => ({ - default: (await import('./components/playground_header_docs')).PlaygroundHeaderDocs, -})); - -export const getPlaygroundProvider = - (core: CoreStart, services: AppPluginStartDependencies) => - (props: React.ComponentProps) => - ( - - - - ); diff --git a/x-pack/plugins/search_playground/public/hooks/use_playground_breadcrumbs.ts b/x-pack/plugins/search_playground/public/hooks/use_playground_breadcrumbs.ts new file mode 100644 index 0000000000000..8e3467a968b36 --- /dev/null +++ b/x-pack/plugins/search_playground/public/hooks/use_playground_breadcrumbs.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEffect } from 'react'; +import { useKibana } from './use_kibana'; + +export const usePlaygroundBreadcrumbs = () => { + const { searchNavigation } = useKibana().services; + + useEffect(() => { + searchNavigation?.breadcrumbs.setSearchBreadCrumbs( + [{ text: 'Build' }, { text: 'Playground' }], + { forClassicChromeStyle: true } + ); + + return () => { + // Clear breadcrumbs on unmount; + searchNavigation?.breadcrumbs.clearBreadcrumbs(); + }; + }, [searchNavigation]); +}; diff --git a/x-pack/plugins/search_playground/public/playground_overview.tsx b/x-pack/plugins/search_playground/public/playground_overview.tsx index 9fec0fa566ac6..faf5181f4ae7b 100644 --- a/x-pack/plugins/search_playground/public/playground_overview.tsx +++ b/x-pack/plugins/search_playground/public/playground_overview.tsx @@ -6,12 +6,13 @@ */ import React, { useMemo } from 'react'; -import { EuiPageTemplate } from '@elastic/eui'; +import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; import { PlaygroundProvider } from './providers/playground_provider'; import { useKibana } from './hooks/use_kibana'; import { PlaygroundPageMode } from './types'; import { App } from './components/app'; +import { usePlaygroundBreadcrumbs } from './hooks/use_playground_breadcrumbs'; interface PlaygroundOverviewProps { pageMode?: PlaygroundPageMode; @@ -20,8 +21,9 @@ export const PlaygroundOverview: React.FC = ({ pageMode = PlaygroundPageMode.chat, }) => { const { - services: { console: consolePlugin }, + services: { history, console: consolePlugin, searchNavigation }, } = useKibana(); + usePlaygroundBreadcrumbs(); const embeddableConsole = useMemo( () => (consolePlugin?.EmbeddableConsole ? : null), @@ -30,16 +32,17 @@ export const PlaygroundOverview: React.FC = ({ return ( - {embeddableConsole} - + ); }; diff --git a/x-pack/plugins/search_playground/public/plugin.ts b/x-pack/plugins/search_playground/public/plugin.ts index 47bc8352b763e..b1042f6e82444 100644 --- a/x-pack/plugins/search_playground/public/plugin.ts +++ b/x-pack/plugins/search_playground/public/plugin.ts @@ -5,17 +5,20 @@ * 2.0. */ -import type { - CoreSetup, +import { BehaviorSubject, type Subscription } from 'rxjs'; + +import { + type CoreSetup, Plugin, - CoreStart, - AppMountParameters, - PluginInitializerContext, + type CoreStart, + type AppMountParameters, + type PluginInitializerContext, + DEFAULT_APP_CATEGORIES, + AppUpdater, + AppStatus, } from '@kbn/core/public'; import { PLUGIN_ID, PLUGIN_NAME, PLUGIN_PATH } from '../common'; import { docLinks } from '../common/doc_links'; -import { PlaygroundHeaderDocs } from './components/playground_header_docs'; -import { Playground, getPlaygroundProvider } from './embeddable'; import type { AppPluginSetupDependencies, AppPluginStartDependencies, @@ -29,6 +32,8 @@ export class SearchPlaygroundPlugin implements Plugin { private config: SearchPlaygroundConfigType; + private appUpdater$ = new BehaviorSubject(() => ({})); + private licenseSubscription: Subscription | undefined; constructor(initializerContext: PluginInitializerContext) { this.config = initializerContext.config.get(); @@ -43,12 +48,17 @@ export class SearchPlaygroundPlugin core.application.register({ id: PLUGIN_ID, appRoute: PLUGIN_PATH, + category: DEFAULT_APP_CATEGORIES.enterpriseSearch, + euiIconType: 'logoEnterpriseSearch', + status: AppStatus.inaccessible, title: PLUGIN_NAME, + updater$: this.appUpdater$, async mount({ element, history }: AppMountParameters) { const { renderApp } = await import('./application'); const [coreStart, depsStart] = await core.getStartServices(); coreStart.chrome.docTitle.change(PLUGIN_NAME); + depsStart.searchNavigation?.handleOnAppMount(); const startDeps: AppPluginStartDependencies = { ...depsStart, @@ -57,6 +67,8 @@ export class SearchPlaygroundPlugin return renderApp(coreStart, startDeps, element); }, + visibleIn: ['sideNav', 'globalSearch'], + order: 2, }); registerLocators(deps.share); @@ -64,14 +76,29 @@ export class SearchPlaygroundPlugin return {}; } - public start(core: CoreStart, deps: AppPluginStartDependencies): SearchPlaygroundPluginStart { + public start( + core: CoreStart, + { licensing }: AppPluginStartDependencies + ): SearchPlaygroundPluginStart { docLinks.setDocLinks(core.docLinks.links); - return { - PlaygroundProvider: getPlaygroundProvider(core, deps), - Playground, - PlaygroundHeaderDocs, - }; + + this.licenseSubscription = licensing.license$.subscribe((license) => { + const status: AppStatus = + license && license.isAvailable && license.isActive && license.hasAtLeast('enterprise') + ? AppStatus.accessible + : AppStatus.inaccessible; + + this.appUpdater$.next(() => ({ + status, + })); + }); + return {}; } - public stop() {} + public stop() { + if (this.licenseSubscription) { + this.licenseSubscription.unsubscribe(); + this.licenseSubscription = undefined; + } + } } diff --git a/x-pack/plugins/search_playground/public/types.ts b/x-pack/plugins/search_playground/public/types.ts index ff9c56ffb553e..dfd415d5b9781 100644 --- a/x-pack/plugins/search_playground/public/types.ts +++ b/x-pack/plugins/search_playground/public/types.ts @@ -11,21 +11,19 @@ import { IndicesStatsIndexMetadataState, Uuid, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public'; -import { SecurityPluginStart } from '@kbn/security-plugin/public'; -import { HttpStart } from '@kbn/core-http-browser'; +import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public'; import React, { ComponentType } from 'react'; -import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public'; -import { CloudSetup } from '@kbn/cloud-plugin/public'; -import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; -import { AppMountParameters } from '@kbn/core/public'; -import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; +import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public'; +import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public'; +import type { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; +import type { AppMountParameters, CoreStart } from '@kbn/core/public'; +import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import type { ConsolePluginStart } from '@kbn/console-plugin/public'; -import { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { ChatRequestData, MessageRole } from '../common/types'; -import type { App } from './components/app'; -import type { PlaygroundProvider as PlaygroundProviderComponent } from './providers/playground_provider'; -import { PlaygroundHeaderDocs } from './components/playground_header_docs'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { SearchNavigationPluginStart } from '@kbn/search-navigation/public'; +import type { SecurityPluginStart } from '@kbn/security-plugin/public'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; +import type { ChatRequestData, MessageRole } from '../common/types'; export * from '../common/types'; @@ -36,13 +34,11 @@ export enum PlaygroundPageMode { // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SearchPlaygroundPluginSetup {} -export interface SearchPlaygroundPluginStart { - PlaygroundProvider: React.FC>; - Playground: React.FC>; - PlaygroundHeaderDocs: React.FC>; -} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface SearchPlaygroundPluginStart {} export interface AppPluginSetupDependencies { + cloud?: CloudSetup; share: SharePluginSetup; } @@ -52,21 +48,16 @@ export interface AppPluginStartDependencies { navigation: NavigationPublicPluginStart; triggersActionsUi: TriggersAndActionsUIPublicPluginStart; share: SharePluginStart; + cloud?: CloudStart; console?: ConsolePluginStart; data: DataPublicPluginStart; -} - -export interface AppServicesContext { - http: HttpStart; + searchNavigation?: SearchNavigationPluginStart; security: SecurityPluginStart; - share: SharePluginStart; - cloud?: CloudSetup; - triggersActionsUi: TriggersAndActionsUIPublicPluginStart; - usageCollection?: UsageCollectionStart; - console?: ConsolePluginStart; - data: DataPublicPluginStart; + licensing: LicensingPluginStart; } +export type AppServicesContext = CoreStart & AppPluginStartDependencies; + export enum ChatFormFields { question = 'question', citations = 'citations', diff --git a/x-pack/plugins/search_playground/server/config.ts b/x-pack/plugins/search_playground/server/config.ts index 083c7ff14f5ea..3465b3126a1c7 100644 --- a/x-pack/plugins/search_playground/server/config.ts +++ b/x-pack/plugins/search_playground/server/config.ts @@ -13,7 +13,7 @@ export * from './types'; const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), ui: schema.object({ - enabled: schema.boolean({ defaultValue: false }), + enabled: schema.boolean({ defaultValue: true }), }), }); diff --git a/x-pack/plugins/search_playground/server/plugin.ts b/x-pack/plugins/search_playground/server/plugin.ts index 962645aba8403..f2291de820a22 100644 --- a/x-pack/plugins/search_playground/server/plugin.ts +++ b/x-pack/plugins/search_playground/server/plugin.ts @@ -5,15 +5,25 @@ * 2.0. */ -import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server'; +import { + PluginInitializerContext, + CoreSetup, + CoreStart, + Plugin, + Logger, + DEFAULT_APP_CATEGORIES, +} from '@kbn/core/server'; +import { KibanaFeatureScope } from '@kbn/features-plugin/common'; import { sendMessageEvent } from './analytics/events'; import { SearchPlaygroundPluginSetup, + SearchPlaygroundPluginSetupDependencies, SearchPlaygroundPluginStart, SearchPlaygroundPluginStartDependencies, } from './types'; import { defineRoutes } from './routes'; +import { PLUGIN_ID, PLUGIN_NAME } from '../common'; export class SearchPlaygroundPlugin implements @@ -31,7 +41,8 @@ export class SearchPlaygroundPlugin } public setup( - core: CoreSetup + core: CoreSetup, + { features }: SearchPlaygroundPluginSetupDependencies ) { this.logger.debug('searchPlayground: Setup'); const router = core.http.createRouter(); @@ -40,6 +51,37 @@ export class SearchPlaygroundPlugin this.registerAnalyticsEvents(core); + features.registerKibanaFeature({ + id: PLUGIN_ID, + minimumLicense: 'enterprise', + name: PLUGIN_NAME, + order: 1, + category: DEFAULT_APP_CATEGORIES.enterpriseSearch, + scope: [KibanaFeatureScope.Spaces, KibanaFeatureScope.Security], + app: ['kibana', PLUGIN_ID], + catalogue: [PLUGIN_ID], + privileges: { + all: { + app: ['kibana', PLUGIN_ID], + api: [PLUGIN_ID], + catalogue: [PLUGIN_ID], + savedObject: { + all: [], + read: [], + }, + ui: [], + }, + read: { + disabled: true, + savedObject: { + all: [], + read: [], + }, + ui: [], + }, + }, + }); + return {}; } diff --git a/x-pack/plugins/search_playground/server/routes.ts b/x-pack/plugins/search_playground/server/routes.ts index 115b55d34146a..3aca695cc0b08 100644 --- a/x-pack/plugins/search_playground/server/routes.ts +++ b/x-pack/plugins/search_playground/server/routes.ts @@ -9,6 +9,7 @@ import { schema } from '@kbn/config-schema'; import type { Logger } from '@kbn/logging'; import { IRouter, StartServicesAccessor } from '@kbn/core/server'; import { i18n } from '@kbn/i18n'; +import { PLUGIN_ID } from '../common'; import { sendMessageEvent, SendMessageEventData } from './analytics/events'; import { fetchFields } from './lib/fetch_query_source_fields'; import { AssistClientOptionsWithClient, createAssist as Assist } from './utils/assist'; @@ -53,6 +54,14 @@ export function defineRoutes({ router.post( { path: APIRoutes.POST_QUERY_SOURCE_FIELDS, + options: { + access: 'internal', + }, + security: { + authz: { + requiredPrivileges: [PLUGIN_ID], + }, + }, validate: { body: schema.object({ indices: schema.arrayOf(schema.string()), @@ -74,6 +83,14 @@ export function defineRoutes({ router.post( { path: APIRoutes.POST_CHAT_MESSAGE, + options: { + access: 'internal', + }, + security: { + authz: { + requiredPrivileges: [PLUGIN_ID], + }, + }, validate: { body: schema.object({ data: schema.object({ @@ -194,6 +211,14 @@ export function defineRoutes({ router.get( { path: APIRoutes.GET_INDICES, + options: { + access: 'internal', + }, + security: { + authz: { + requiredPrivileges: [PLUGIN_ID], + }, + }, validate: { query: schema.object({ search_query: schema.maybe(schema.string()), @@ -223,6 +248,14 @@ export function defineRoutes({ router.post( { path: APIRoutes.POST_SEARCH_QUERY, + options: { + access: 'internal', + }, + security: { + authz: { + requiredPrivileges: [PLUGIN_ID], + }, + }, validate: { body: schema.object({ search_query: schema.string(), @@ -287,6 +320,14 @@ export function defineRoutes({ router.post( { path: APIRoutes.GET_INDEX_MAPPINGS, + options: { + access: 'internal', + }, + security: { + authz: { + requiredPrivileges: [PLUGIN_ID], + }, + }, validate: { body: schema.object({ indices: schema.arrayOf(schema.string()), diff --git a/x-pack/plugins/search_playground/server/types.ts b/x-pack/plugins/search_playground/server/types.ts index c3f1e8571a6b7..e56134b4f2e07 100644 --- a/x-pack/plugins/search_playground/server/types.ts +++ b/x-pack/plugins/search_playground/server/types.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { PluginStartContract as ActionsPluginStartContract } from '@kbn/actions-plugin/server'; -import { CloudStart } from '@kbn/cloud-plugin/server'; +import type { PluginStartContract as ActionsPluginStartContract } from '@kbn/actions-plugin/server'; +import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/server'; +import type { FeaturesPluginSetup } from '@kbn/features-plugin/server'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SearchPlaygroundPluginSetup {} @@ -14,6 +15,11 @@ export interface SearchPlaygroundPluginSetup {} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SearchPlaygroundPluginStart {} +export interface SearchPlaygroundPluginSetupDependencies { + cloud?: CloudSetup; + features: FeaturesPluginSetup; +} + export interface SearchPlaygroundPluginStartDependencies { actions: ActionsPluginStartContract; cloud?: CloudStart; diff --git a/x-pack/plugins/search_playground/tsconfig.json b/x-pack/plugins/search_playground/tsconfig.json index 73204bade51c3..d0b14624fcdf3 100644 --- a/x-pack/plugins/search_playground/tsconfig.json +++ b/x-pack/plugins/search_playground/tsconfig.json @@ -17,7 +17,6 @@ "@kbn/i18n", "@kbn/i18n-react", "@kbn/kibana-react-plugin", - "@kbn/security-plugin", "@kbn/user-profile-components", "@kbn/shared-ux-router", "@kbn/shared-ux-page-kibana-template", @@ -26,8 +25,6 @@ "@kbn/share-plugin", "@kbn/cloud-plugin", "@kbn/actions-plugin", - "@kbn/shared-ux-utility", - "@kbn/core-lifecycle-browser", "@kbn/stack-connectors-plugin", "@kbn/cases-plugin", "@kbn/triggers-actions-ui-plugin", @@ -46,6 +43,10 @@ "@kbn/discover-utils", "@kbn/data-plugin", "@kbn/search-index-documents", + "@kbn/search-navigation", + "@kbn/features-plugin", + "@kbn/security-plugin", + "@kbn/licensing-plugin", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/search_solution/search_navigation/public/plugin.ts b/x-pack/plugins/search_solution/search_navigation/public/plugin.ts index 4b618a6245c40..ddaf0b059fceb 100644 --- a/x-pack/plugins/search_solution/search_navigation/public/plugin.ts +++ b/x-pack/plugins/search_solution/search_navigation/public/plugin.ts @@ -12,13 +12,17 @@ import type { PluginInitializerContext, ScopedHistory, } from '@kbn/core/public'; -import type { ChromeStyle } from '@kbn/core-chrome-browser'; +import type { Subscription } from 'rxjs'; +import type { ChromeBreadcrumb, ChromeStyle } from '@kbn/core-chrome-browser'; +import { i18n } from '@kbn/i18n'; import type { Logger } from '@kbn/logging'; import type { SearchNavigationPluginSetup, SearchNavigationPluginStart, ClassicNavItem, ClassicNavigationFactoryFn, + SearchNavigationSetBreadcrumbsOptions, + AppPluginStartDependencies, } from './types'; export class SearchNavigationPlugin @@ -28,8 +32,10 @@ export class SearchNavigationPlugin private currentChromeStyle: ChromeStyle | undefined = undefined; private baseClassicNavItemsFn: (() => ClassicNavItem[]) | undefined = undefined; private coreStart: CoreStart | undefined = undefined; + private pluginsStart: AppPluginStartDependencies | undefined = undefined; private classicNavFactory: ClassicNavigationFactoryFn | undefined = undefined; private onAppMountHandlers: Array<() => Promise> = []; + private chromeSub: Subscription | undefined; constructor(private readonly initializerContext: PluginInitializerContext) { this.logger = this.initializerContext.logger.get(); @@ -39,9 +45,10 @@ export class SearchNavigationPlugin return {}; } - public start(core: CoreStart): SearchNavigationPluginStart { + public start(core: CoreStart, plugins: AppPluginStartDependencies): SearchNavigationPluginStart { this.coreStart = core; - core.chrome.getChromeStyle$().subscribe((value) => { + this.pluginsStart = plugins; + this.chromeSub = core.chrome.getChromeStyle$().subscribe((value) => { this.currentChromeStyle = value; }); @@ -54,10 +61,19 @@ export class SearchNavigationPlugin registerOnAppMountHandler: this.registerOnAppMountHandler.bind(this), setGetBaseClassicNavItems: this.setGetBaseClassicNavItems.bind(this), useClassicNavigation: this.useClassicNavigation.bind(this), + breadcrumbs: { + setSearchBreadCrumbs: this.setBreadcrumbs.bind(this), + clearBreadcrumbs: this.clearBreadcrumbs.bind(this), + }, }; } - public stop() {} + public stop() { + if (this.chromeSub) { + this.chromeSub.unsubscribe(); + this.chromeSub = undefined; + } + } private async handleOnAppMount() { if (this.onAppMountHandlers.length === 0) return; @@ -89,4 +105,36 @@ export class SearchNavigationPlugin return this.classicNavFactory(this.baseClassicNavItemsFn(), this.coreStart, history); } + + private setBreadcrumbs( + breadcrumbs: ChromeBreadcrumb[], + { forClassicChromeStyle = false }: SearchNavigationSetBreadcrumbsOptions = {} + ) { + if (forClassicChromeStyle === true && this.currentChromeStyle !== 'classic') return; + + const searchBreadcrumbs = [this.getSearchHomeBreadcrumb(), ...breadcrumbs]; + if (this.pluginsStart?.serverless) { + this.pluginsStart.serverless.setBreadcrumbs(searchBreadcrumbs); + } else { + this.coreStart?.chrome.setBreadcrumbs(searchBreadcrumbs); + } + } + + private clearBreadcrumbs() { + if (this.pluginsStart?.serverless) { + this.pluginsStart.serverless.setBreadcrumbs([]); + } else { + this.coreStart?.chrome.setBreadcrumbs([]); + } + } + + private getSearchHomeBreadcrumb(): ChromeBreadcrumb { + // TODO: When search_navigation handles solution nav, use the default + // home deep link for this breadcrumb's path. + return { + text: i18n.translate('xpack.searchNavigation.breadcrumbs.home.title', { + defaultMessage: 'Elasticsearch', + }), + }; + } } diff --git a/x-pack/plugins/search_solution/search_navigation/public/types.ts b/x-pack/plugins/search_solution/search_navigation/public/types.ts index 91e8cc73524e2..abba2a55a75c3 100644 --- a/x-pack/plugins/search_solution/search_navigation/public/types.ts +++ b/x-pack/plugins/search_solution/search_navigation/public/types.ts @@ -6,7 +6,7 @@ */ import type { ReactNode } from 'react'; -import type { AppDeepLinkId } from '@kbn/core-chrome-browser'; +import type { AppDeepLinkId, ChromeBreadcrumb } from '@kbn/core-chrome-browser'; import type { CoreStart, ScopedHistory } from '@kbn/core/public'; import type { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public'; import type { SolutionNavProps } from '@kbn/shared-ux-page-solution-nav'; @@ -20,6 +20,13 @@ export interface SearchNavigationPluginStart { // This is temporary until we can migrate building the class nav item list out of `enterprise_search` plugin setGetBaseClassicNavItems: (classicNavItemsFn: () => ClassicNavItem[]) => void; useClassicNavigation: (history: ScopedHistory) => SolutionNavProps | undefined; + breadcrumbs: { + setSearchBreadCrumbs: ( + breadcrumbs: ChromeBreadcrumb[], + options?: SearchNavigationSetBreadcrumbsOptions + ) => void; + clearBreadcrumbs: () => void; + }; } export interface AppPluginSetupDependencies { @@ -49,3 +56,10 @@ export type ClassicNavigationFactoryFn = ( core: CoreStart, history: ScopedHistory ) => SolutionNavProps | undefined; + +export interface SearchNavigationSetBreadcrumbsOptions { + // When set to `true` breadcrumbs are only set when chrome style is set to classic. + // This option is for pages who rely on Solution Navigation for breadcrumbs, but still + // need to explicitly set the page breadcrumbs for classic solution view. + forClassicChromeStyle?: boolean; +} diff --git a/x-pack/plugins/search_solution/search_navigation/tsconfig.json b/x-pack/plugins/search_solution/search_navigation/tsconfig.json index 6d61fbb24ec89..3be41403c936e 100644 --- a/x-pack/plugins/search_solution/search_navigation/tsconfig.json +++ b/x-pack/plugins/search_solution/search_navigation/tsconfig.json @@ -4,11 +4,8 @@ "outDir": "target/types" }, "include": [ - "__mocks__/**/*", "common/**/*", "public/**/*", - "server/**/*", - "../../../../typings/**/*" ], "kbn_references": [ "@kbn/core", diff --git a/x-pack/plugins/serverless_search/kibana.jsonc b/x-pack/plugins/serverless_search/kibana.jsonc index f7b404edb37b1..cae0a693846f1 100644 --- a/x-pack/plugins/serverless_search/kibana.jsonc +++ b/x-pack/plugins/serverless_search/kibana.jsonc @@ -35,6 +35,7 @@ "indexManagement", "searchConnectors", "searchInferenceEndpoints", + "searchPlayground", "usageCollection" ], "requiredBundles": ["kibanaReact"] diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 63c26a6683173..519225179e043 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -17794,7 +17794,6 @@ "xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.panelTitle": "Générer une clé d’API", "xpack.enterpriseSearch.content.overview.gettingStarted.pageDescription": "Configurez votre client de langage de programmation, ingérez des données, et vous serez prêt à commencer vos recherches en quelques minutes.", "xpack.enterpriseSearch.content.overview.gettingStarted.pageTitle": "Clients linguistiques Elasticsearch", - "xpack.enterpriseSearch.content.playground.breadcrumb": "Playground", "xpack.enterpriseSearch.content.searchIndex.cancelSync.successMessage": "Annulation réussie de la synchronisation", "xpack.enterpriseSearch.content.searchIndex.cancelSyncs.successMessage": "Annulation réussie des synchronisations", "xpack.enterpriseSearch.content.searchIndex.configurationTabLabel": "Configuration", @@ -18353,7 +18352,6 @@ "xpack.enterpriseSearch.navigation.appSearchEnginesLinkLabel": "Moteurs", "xpack.enterpriseSearch.navigation.contentConnectorsLinkLabel": "Connecteurs", "xpack.enterpriseSearch.navigation.contentIndicesLinkLabel": "Index", - "xpack.enterpriseSearch.navigation.contentPlaygroundLinkLabel": "Playground", "xpack.enterpriseSearch.navigation.contentWebcrawlersLinkLabel": "Robots d'indexation", "xpack.enterpriseSearch.navigation.relevanceInferenceEndpointsLinkLabel": "Points de terminaison d'inférence", "xpack.enterpriseSearch.notFound.action1": "Retour à votre tableau de bord", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 446ff88246a7a..caf9062a48543 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -17654,7 +17654,6 @@ "xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.panelTitle": "APIキーを生成", "xpack.enterpriseSearch.content.overview.gettingStarted.pageDescription": "プログラミング言語のクライアントを設定し、データを取り込めば、数分で検索を開始できます。", "xpack.enterpriseSearch.content.overview.gettingStarted.pageTitle": "Elasticsearch言語クライアント", - "xpack.enterpriseSearch.content.playground.breadcrumb": "Playground", "xpack.enterpriseSearch.content.searchIndex.cancelSync.successMessage": "同期が正常にキャンセルされました", "xpack.enterpriseSearch.content.searchIndex.cancelSyncs.successMessage": "同期が正常にキャンセルされました", "xpack.enterpriseSearch.content.searchIndex.configurationTabLabel": "構成", @@ -18211,7 +18210,6 @@ "xpack.enterpriseSearch.navigation.appSearchEnginesLinkLabel": "エンジン", "xpack.enterpriseSearch.navigation.contentConnectorsLinkLabel": "コネクター", "xpack.enterpriseSearch.navigation.contentIndicesLinkLabel": "インデックス", - "xpack.enterpriseSearch.navigation.contentPlaygroundLinkLabel": "Playground", "xpack.enterpriseSearch.navigation.contentWebcrawlersLinkLabel": "Webクローラー", "xpack.enterpriseSearch.navigation.relevanceInferenceEndpointsLinkLabel": "推論エンドポイント", "xpack.enterpriseSearch.notFound.action1": "ダッシュボードに戻す", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 20e1de9fc8cc9..74e0de50a811f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -17354,7 +17354,6 @@ "xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.panelTitle": "生成 API 密钥", "xpack.enterpriseSearch.content.overview.gettingStarted.pageDescription": "设置您的编程语言客户端,采集一些数据,如此即可在数分钟内开始搜索。", "xpack.enterpriseSearch.content.overview.gettingStarted.pageTitle": "Elasticsearch 语言客户端", - "xpack.enterpriseSearch.content.playground.breadcrumb": "Playground", "xpack.enterpriseSearch.content.searchIndex.cancelSync.successMessage": "已成功取消同步", "xpack.enterpriseSearch.content.searchIndex.cancelSyncs.successMessage": "已成功取消同步", "xpack.enterpriseSearch.content.searchIndex.configurationTabLabel": "配置", @@ -17909,7 +17908,6 @@ "xpack.enterpriseSearch.navigation.appSearchEnginesLinkLabel": "引擎", "xpack.enterpriseSearch.navigation.contentConnectorsLinkLabel": "连接器", "xpack.enterpriseSearch.navigation.contentIndicesLinkLabel": "索引", - "xpack.enterpriseSearch.navigation.contentPlaygroundLinkLabel": "Playground", "xpack.enterpriseSearch.navigation.contentWebcrawlersLinkLabel": "网络爬虫", "xpack.enterpriseSearch.navigation.relevanceInferenceEndpointsLinkLabel": "推理终端", "xpack.enterpriseSearch.notFound.action1": "返回到您的仪表板", diff --git a/x-pack/test/api_integration/apis/features/features/features.ts b/x-pack/test/api_integration/apis/features/features/features.ts index 7541b2171b2cb..42dcd94234c98 100644 --- a/x-pack/test/api_integration/apis/features/features/features.ts +++ b/x-pack/test/api_integration/apis/features/features/features.ts @@ -129,6 +129,7 @@ export default function ({ getService }: FtrProviderContext) { 'rulesSettings', 'uptime', 'searchInferenceEndpoints', + 'searchPlayground', 'siem', 'slo', 'securitySolutionAssistant', @@ -180,6 +181,7 @@ export default function ({ getService }: FtrProviderContext) { 'rulesSettings', 'uptime', 'searchInferenceEndpoints', + 'searchPlayground', 'siem', 'slo', 'securitySolutionAssistant', diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index 4cf8cc46a9338..c59fe61e7e1d1 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -60,6 +60,7 @@ export default function ({ getService }: FtrProviderContext) { ], observabilityAIAssistant: ['all', 'read', 'minimal_all', 'minimal_read'], slo: ['all', 'read', 'minimal_all', 'minimal_read'], + searchPlayground: ['all', 'read', 'minimal_all', 'minimal_read'], searchInferenceEndpoints: ['all', 'read', 'minimal_all', 'minimal_read'], fleetv2: ['all', 'read', 'minimal_all', 'minimal_read'], fleet: ['all', 'read', 'minimal_all', 'minimal_read'], diff --git a/x-pack/test/api_integration/apis/security/privileges_basic.ts b/x-pack/test/api_integration/apis/security/privileges_basic.ts index 3911d95ea9bed..37db0e71030af 100644 --- a/x-pack/test/api_integration/apis/security/privileges_basic.ts +++ b/x-pack/test/api_integration/apis/security/privileges_basic.ts @@ -50,6 +50,7 @@ export default function ({ getService }: FtrProviderContext) { securitySolutionAttackDiscovery: ['all', 'read', 'minimal_all', 'minimal_read'], securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read'], securitySolutionCasesV2: ['all', 'read', 'minimal_all', 'minimal_read'], + searchPlayground: ['all', 'read', 'minimal_all', 'minimal_read'], searchInferenceEndpoints: ['all', 'read', 'minimal_all', 'minimal_read'], fleetv2: ['all', 'read', 'minimal_all', 'minimal_read'], fleet: ['all', 'read', 'minimal_all', 'minimal_read'], @@ -146,6 +147,7 @@ export default function ({ getService }: FtrProviderContext) { ], observabilityAIAssistant: ['all', 'read', 'minimal_all', 'minimal_read'], slo: ['all', 'read', 'minimal_all', 'minimal_read'], + searchPlayground: ['all', 'read', 'minimal_all', 'minimal_read'], searchInferenceEndpoints: ['all', 'read', 'minimal_all', 'minimal_read'], fleetv2: ['all', 'read', 'minimal_all', 'minimal_read'], fleet: ['all', 'read', 'minimal_all', 'minimal_read'], diff --git a/x-pack/test/functional_search/tests/solution_navigation.ts b/x-pack/test/functional_search/tests/solution_navigation.ts index 89cee21a81d66..03a4614017ba2 100644 --- a/x-pack/test/functional_search/tests/solution_navigation.ts +++ b/x-pack/test/functional_search/tests/solution_navigation.ts @@ -155,15 +155,15 @@ export default function searchSolutionNavigation({ // check Build // > Playground await solutionNavigation.sidenav.clickLink({ - deepLinkId: 'enterpriseSearchApplications:playground', + deepLinkId: 'searchPlayground', }); await solutionNavigation.sidenav.expectLinkActive({ - deepLinkId: 'enterpriseSearchApplications:playground', + deepLinkId: 'searchPlayground', }); await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Build' }); await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Playground' }); await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ - deepLinkId: 'enterpriseSearchApplications:playground', + deepLinkId: 'searchPlayground', }); // > Search applications await solutionNavigation.sidenav.clickLink({ @@ -304,7 +304,7 @@ export default function searchSolutionNavigation({ 'enterpriseSearchContent:connectors', 'enterpriseSearchContent:webCrawlers', 'build', - 'enterpriseSearchApplications:playground', + 'searchPlayground', 'enterpriseSearchApplications:searchApplications', 'enterpriseSearchAnalytics', 'relevance', diff --git a/x-pack/test/spaces_api_integration/spaces_only/telemetry/telemetry.ts b/x-pack/test/spaces_api_integration/spaces_only/telemetry/telemetry.ts index a74fbf6b75383..1e18525df2ecc 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/telemetry/telemetry.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/telemetry/telemetry.ts @@ -84,6 +84,7 @@ export default function ({ getService }: FtrProviderContext) { apm: 0, enterpriseSearch: 0, searchInferenceEndpoints: 0, + searchPlayground: 0, siem: 0, securitySolutionCases: 0, securitySolutionCasesV2: 0, diff --git a/x-pack/test/ui_capabilities/security_and_spaces/tests/catalogue.ts b/x-pack/test/ui_capabilities/security_and_spaces/tests/catalogue.ts index ddcc187fad6a4..ffe278d152523 100644 --- a/x-pack/test/ui_capabilities/security_and_spaces/tests/catalogue.ts +++ b/x-pack/test/ui_capabilities/security_and_spaces/tests/catalogue.ts @@ -93,6 +93,7 @@ export default function catalogueTests({ getService }: FtrProviderContext) { 'enterpriseSearchVectorSearch', 'enterpriseSearchSemanticSearch', 'enterpriseSearchElasticsearch', + 'searchPlayground', 'searchInferenceEndpoints', 'appSearch', 'observabilityAIAssistant', diff --git a/x-pack/test/ui_capabilities/security_and_spaces/tests/nav_links.ts b/x-pack/test/ui_capabilities/security_and_spaces/tests/nav_links.ts index 6005e30ff2565..934f9af8d6b8c 100644 --- a/x-pack/test/ui_capabilities/security_and_spaces/tests/nav_links.ts +++ b/x-pack/test/ui_capabilities/security_and_spaces/tests/nav_links.ts @@ -64,6 +64,7 @@ export default function navLinksTests({ getService }: FtrProviderContext) { 'monitoring', 'observabilityAIAssistant', 'enterpriseSearch', + 'searchPlayground', 'searchInferenceEndpoints', 'guidedOnboardingFeature', 'securitySolutionAssistant',