mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
# Backport This will backport the following commits from `main` to `8.14`: - [[Serverless] Playground in Serverless (#181474)](https://github.com/elastic/kibana/pull/181474) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Samiul Monir","email":"150824886+Samiul-TheSoccerFan@users.noreply.github.com"},"sourceCommit":{"committedDate":"2024-04-26T18:12:51Z","message":"[Serverless] Playground in Serverless (#181474)\n\n## Summary\r\n\r\nThis PR:\r\n\r\n- Integrate Playground into Serverless\r\n- Redesign of Navigation Menu\r\n- Refactor Playground docs\r\n\r\n## UI changes:\r\n### Playground in Serverless\r\n\r\n\r\n\r\n### Playground with docs and indices\r\n\r\n\r\n\r\n### Playground in action\r\n\r\n\r\n\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [ ] Any text added follows [EUI's writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\r\nsentence case text and includes [i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n- [ ]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [ ] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n- [ ] [Flaky Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is usable by keyboard only (learn more\r\nabout [keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI touched in this PR does not create any new axe failures\r\n(run axe in browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n- [ ] If a plugin configuration key changed, check if it needs to be\r\nallowlisted in the cloud and added to the [docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n- [ ] This renders correctly on smaller devices using a responsive\r\nlayout. (You can test this [in your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n- [ ] This was checked for [cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for breaking API changes and was [labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"41fd6432be054eff743bfbf2a3f4402a0ae42733","branchLabelMapping":{"^v8.15.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:EnterpriseSearch","v8.14.0","v8.15.0"],"number":181474,"url":"https://github.com/elastic/kibana/pull/181474","mergeCommit":{"message":"[Serverless] Playground in Serverless (#181474)\n\n## Summary\r\n\r\nThis PR:\r\n\r\n- Integrate Playground into Serverless\r\n- Redesign of Navigation Menu\r\n- Refactor Playground docs\r\n\r\n## UI changes:\r\n### Playground in Serverless\r\n\r\n\r\n\r\n### Playground with docs and indices\r\n\r\n\r\n\r\n### Playground in action\r\n\r\n\r\n\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [ ] Any text added follows [EUI's writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\r\nsentence case text and includes [i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n- [ ]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [ ] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n- [ ] [Flaky Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is usable by keyboard only (learn more\r\nabout [keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI touched in this PR does not create any new axe failures\r\n(run axe in browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n- [ ] If a plugin configuration key changed, check if it needs to be\r\nallowlisted in the cloud and added to the [docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n- [ ] This renders correctly on smaller devices using a responsive\r\nlayout. (You can test this [in your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n- [ ] This was checked for [cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for breaking API changes and was [labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"41fd6432be054eff743bfbf2a3f4402a0ae42733"}},"sourceBranch":"main","suggestedTargetBranches":["8.14"],"targetPullRequestStates":[{"branch":"8.14","label":"v8.14.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.15.0","labelRegex":"^v8.15.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/181474","number":181474,"mergeCommit":{"message":"[Serverless] Playground in Serverless (#181474)\n\n## Summary\r\n\r\nThis PR:\r\n\r\n- Integrate Playground into Serverless\r\n- Redesign of Navigation Menu\r\n- Refactor Playground docs\r\n\r\n## UI changes:\r\n### Playground in Serverless\r\n\r\n\r\n\r\n### Playground with docs and indices\r\n\r\n\r\n\r\n### Playground in action\r\n\r\n\r\n\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n- [ ] Any text added follows [EUI's writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing), uses\r\nsentence case text and includes [i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n- [ ]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas added for features that require explanation or tutorials\r\n- [ ] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios\r\n- [ ] [Flaky Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is usable by keyboard only (learn more\r\nabout [keyboard accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] Any UI touched in this PR does not create any new axe failures\r\n(run axe in browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n- [ ] If a plugin configuration key changed, check if it needs to be\r\nallowlisted in the cloud and added to the [docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n- [ ] This renders correctly on smaller devices using a responsive\r\nlayout. (You can test this [in your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n- [ ] This was checked for [cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n\r\n### For maintainers\r\n\r\n- [ ] This was checked for breaking API changes and was [labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"41fd6432be054eff743bfbf2a3f4402a0ae42733"}}]}] BACKPORT--> Co-authored-by: Samiul Monir <150824886+Samiul-TheSoccerFan@users.noreply.github.com>
This commit is contained in:
parent
a4cb49799d
commit
94e4ede666
46 changed files with 499 additions and 145 deletions
|
@ -28,8 +28,9 @@ xpack.serverless.plugin.developer.projectSwitcher.currentType: 'search'
|
|||
# Specify in telemetry the project type
|
||||
telemetry.labels.serverless: search
|
||||
|
||||
# Alerts config
|
||||
xpack.actions.enabledActionTypes: ['.email', '.index', '.slack', '.jira', '.webhook', '.teams']
|
||||
# Alerts and LLM config
|
||||
xpack.actions.enabledActionTypes:
|
||||
['.email', '.index', '.slack', '.jira', '.webhook', '.teams', '.gen-ai', '.bedrock']
|
||||
|
||||
# Customize empty page state for analytics apps
|
||||
no_data_page.analyticsNoDataPageFlavor: 'serverless_search'
|
||||
|
@ -43,3 +44,6 @@ xpack.ml.nlp.enabled: true
|
|||
xpack.ml.compatibleModuleType: 'search'
|
||||
|
||||
data_visualizer.resultLinks.fileBeat.enabled: false
|
||||
|
||||
# Search Playground
|
||||
xpack.searchPlayground.ui.enabled: false
|
||||
|
|
|
@ -14,3 +14,4 @@ export const ENTERPRISE_SEARCH_APPSEARCH_APP_ID = 'appSearch';
|
|||
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_SEARCH_PLAYGROUND_ID = 'searchPlayground';
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
ENTERPRISE_SEARCH_ANALYTICS_APP_ID,
|
||||
ENTERPRISE_SEARCH_APPSEARCH_APP_ID,
|
||||
ENTERPRISE_SEARCH_WORKPLACESEARCH_APP_ID,
|
||||
SERVERLESS_ES_SEARCH_PLAYGROUND_ID,
|
||||
} from './constants';
|
||||
|
||||
export type EnterpriseSearchApp = typeof ENTERPRISE_SEARCH_APP_ID;
|
||||
|
@ -25,6 +26,7 @@ export type EnterpriseSearchAppsearchApp = typeof ENTERPRISE_SEARCH_APPSEARCH_AP
|
|||
export type EnterpriseSearchWorkplaceSearchApp = typeof ENTERPRISE_SEARCH_WORKPLACESEARCH_APP_ID;
|
||||
export type ServerlessSearchApp = typeof SERVERLESS_ES_APP_ID;
|
||||
export type ConnectorsId = typeof SERVERLESS_ES_CONNECTORS_ID;
|
||||
export type SearchPlaygroundId = typeof SERVERLESS_ES_SEARCH_PLAYGROUND_ID;
|
||||
|
||||
export type ContentLinkId = 'searchIndices' | 'connectors' | 'webCrawlers';
|
||||
|
||||
|
@ -41,6 +43,7 @@ export type DeepLinkId =
|
|||
| EnterpriseSearchWorkplaceSearchApp
|
||||
| ServerlessSearchApp
|
||||
| ConnectorsId
|
||||
| SearchPlaygroundId
|
||||
| `${EnterpriseSearchContentApp}:${ContentLinkId}`
|
||||
| `${EnterpriseSearchApplicationsApp}:${ApplicationsLinkId}`
|
||||
| `${EnterpriseSearchAppsearchApp}:${AppsearchLinkId}`;
|
||||
|
|
|
@ -206,7 +206,6 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
|
|||
licenseManagement: `${ENTERPRISE_SEARCH_DOCS}license-management.html`,
|
||||
machineLearningStart: `${ELASTICSEARCH_DOCS}nlp-example.html`,
|
||||
mailService: `${ENTERPRISE_SEARCH_DOCS}mailer-configuration.html`,
|
||||
playground: `${KIBANA_DOCS}playground.html`,
|
||||
mlDocumentEnrichment: `${ELASTICSEARCH_DOCS}ingest-pipeline-search-inference.html`,
|
||||
searchApplicationsTemplates: `${ELASTICSEARCH_DOCS}search-application-api.html`,
|
||||
searchApplicationsSearchApi: `${ELASTICSEARCH_DOCS}search-application-security.html`,
|
||||
|
@ -939,5 +938,8 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
|
|||
telemetry: {
|
||||
settings: `${KIBANA_DOCS}telemetry-settings-kbn.html`,
|
||||
},
|
||||
playground: {
|
||||
chatPlayground: `${KIBANA_DOCS}playground.html`,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -170,7 +170,6 @@ export interface DocLinks {
|
|||
readonly languageClients: string;
|
||||
readonly licenseManagement: string;
|
||||
readonly machineLearningStart: string;
|
||||
readonly playground: string;
|
||||
readonly mailService: string;
|
||||
readonly mlDocumentEnrichment: string;
|
||||
readonly searchApplicationsTemplates: string;
|
||||
|
@ -648,6 +647,9 @@ export interface DocLinks {
|
|||
readonly telemetry: {
|
||||
readonly settings: string;
|
||||
};
|
||||
readonly playground: {
|
||||
readonly chatPlayground: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type BuildFlavor = 'serverless' | 'traditional';
|
||||
|
|
|
@ -311,6 +311,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
|
|||
// 'xpack.reporting.poll.jobsRefresh.intervalErrorMultiplier (number)',
|
||||
'xpack.rollup.ui.enabled (boolean)',
|
||||
'xpack.saved_object_tagging.cache_refresh_interval (duration)',
|
||||
'xpack.searchPlayground.ui.enabled (boolean)',
|
||||
'xpack.security.loginAssistanceMessage (string)',
|
||||
'xpack.security.sameSiteCookies (alternatives)',
|
||||
'xpack.security.showInsecureClusterWarning (boolean)',
|
||||
|
|
|
@ -7,25 +7,21 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import { EuiButtonEmpty } from '@elastic/eui';
|
||||
import { useValues } from 'kea';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { KibanaLogic } from '../../../shared/kibana';
|
||||
|
||||
import { docLinks } from '../../../shared/doc_links';
|
||||
import { EndpointsHeaderAction } from '../../../shared/layout/endpoints_header_action';
|
||||
|
||||
export const PlaygroundHeaderDocsAction: React.FC = () => (
|
||||
<EndpointsHeaderAction>
|
||||
<EuiButtonEmpty
|
||||
data-telemetry-id="entSearchApplications-playground-documentationLink"
|
||||
data-test-subj="playground-documentation-link"
|
||||
href={docLinks.playground}
|
||||
target="_blank"
|
||||
iconType="documents"
|
||||
>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.playground.header.docLink', {
|
||||
defaultMessage: 'Playground Docs',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
</EndpointsHeaderAction>
|
||||
);
|
||||
export const PlaygroundHeaderDocsAction: React.FC = () => {
|
||||
const { searchPlayground } = useValues(KibanaLogic);
|
||||
|
||||
if (!searchPlayground) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<EndpointsHeaderAction>
|
||||
<searchPlayground.PlaygroundHeaderDocs />
|
||||
</EndpointsHeaderAction>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -124,7 +124,6 @@ class DocLinks {
|
|||
public licenseManagement: string;
|
||||
public machineLearningStart: string;
|
||||
public mlDocumentEnrichment: string;
|
||||
public playground: string;
|
||||
public pluginsIngestAttachment: string;
|
||||
public queryDsl: string;
|
||||
public restApis: string;
|
||||
|
@ -302,7 +301,6 @@ class DocLinks {
|
|||
this.licenseManagement = '';
|
||||
this.machineLearningStart = '';
|
||||
this.mlDocumentEnrichment = '';
|
||||
this.playground = '';
|
||||
this.pluginsIngestAttachment = '';
|
||||
this.queryDsl = '';
|
||||
this.restApis = '';
|
||||
|
@ -482,7 +480,6 @@ class DocLinks {
|
|||
this.licenseManagement = docLinks.links.enterpriseSearch.licenseManagement;
|
||||
this.machineLearningStart = docLinks.links.enterpriseSearch.machineLearningStart;
|
||||
this.mlDocumentEnrichment = docLinks.links.enterpriseSearch.mlDocumentEnrichment;
|
||||
this.playground = docLinks.links.enterpriseSearch.playground;
|
||||
this.pluginsIngestAttachment = docLinks.links.plugins.ingestAttachment;
|
||||
this.queryDsl = docLinks.links.query.queryDsl;
|
||||
this.restApis = docLinks.links.apis.restApis;
|
||||
|
|
|
@ -14,6 +14,7 @@ const createStartMock = (): Start => {
|
|||
PlaygroundProvider: jest.fn(),
|
||||
PlaygroundToolbar: jest.fn(),
|
||||
Playground: jest.fn(),
|
||||
PlaygroundHeaderDocs: jest.fn(),
|
||||
};
|
||||
|
||||
return startContract;
|
||||
|
|
20
x-pack/plugins/search_playground/common/doc_links.ts
Normal file
20
x-pack/plugins/search_playground/common/doc_links.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 { DocLinks } from '@kbn/doc-links';
|
||||
|
||||
class PlaygroundDocLinks {
|
||||
public chatPlayground: string = '';
|
||||
|
||||
constructor() {}
|
||||
|
||||
setDocLinks(newDocLinks: DocLinks) {
|
||||
this.chatPlayground = newDocLinks.playground.chatPlayground;
|
||||
}
|
||||
}
|
||||
|
||||
export const docLinks = new PlaygroundDocLinks();
|
10
x-pack/plugins/search_playground/common/is_not_nullish.ts
Normal file
10
x-pack/plugins/search_playground/common/is_not_nullish.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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 function isNotNullish<T>(value: T | null | undefined): value is T {
|
||||
return value !== null && value !== undefined;
|
||||
}
|
|
@ -25,6 +25,7 @@ export enum APIRoutes {
|
|||
POST_API_KEY = '/internal/search_playground/api_key',
|
||||
POST_CHAT_MESSAGE = '/internal/search_playground/chat',
|
||||
POST_QUERY_SOURCE_FIELDS = '/internal/search_playground/query_source_fields',
|
||||
GET_INDICES = '/internal/search_playground/indices',
|
||||
}
|
||||
|
||||
export enum LLMs {
|
||||
|
@ -43,3 +44,9 @@ export interface ChatRequestData {
|
|||
source_fields: string;
|
||||
doc_size: number;
|
||||
}
|
||||
|
||||
export interface SearchPlaygroundConfigType {
|
||||
ui: {
|
||||
enabled: boolean;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"actions",
|
||||
"encryptedSavedObjects",
|
||||
"navigation",
|
||||
"share",
|
||||
"security",
|
||||
"stackConnectors",
|
||||
"triggersActionsUi",
|
||||
|
|
|
@ -7,53 +7,26 @@
|
|||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { CoreStart, AppMountParameters } from '@kbn/core/public';
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import { BrowserRouter as Router } from '@kbn/shared-ux-router';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
|
||||
import { PLUGIN_ID } from '../common';
|
||||
import { Router } from '@kbn/shared-ux-router';
|
||||
import { AppPluginStartDependencies } from './types';
|
||||
import { App } from './components/app';
|
||||
import { PlaygroundProvider } from './providers/playground_provider';
|
||||
|
||||
export const renderApp = (
|
||||
export const renderApp = async (
|
||||
core: CoreStart,
|
||||
services: AppPluginStartDependencies,
|
||||
{ appBasePath, element }: AppMountParameters
|
||||
element: HTMLElement
|
||||
) => {
|
||||
const navigation = services.navigation;
|
||||
const { PlaygroundRouter } = await import('./playground_router');
|
||||
|
||||
ReactDOM.render(
|
||||
<KibanaThemeProvider theme={core.theme}>
|
||||
<KibanaContextProvider services={{ ...core, ...services }}>
|
||||
<I18nProvider>
|
||||
<Router basename={appBasePath}>
|
||||
<navigation.ui.TopNavMenu appName={PLUGIN_ID} />
|
||||
<PlaygroundProvider
|
||||
defaultValues={{
|
||||
indices: [],
|
||||
}}
|
||||
>
|
||||
<KibanaPageTemplate
|
||||
pageChrome={[
|
||||
i18n.translate('xpack.searchPlayground.breadcrumb', {
|
||||
defaultMessage: 'Playground',
|
||||
}),
|
||||
]}
|
||||
pageHeader={{
|
||||
pageTitle: i18n.translate('xpack.searchPlayground.pageTitle', {
|
||||
defaultMessage: 'Playground',
|
||||
}),
|
||||
}}
|
||||
bottomBorder="extended"
|
||||
restrictWidth={false}
|
||||
>
|
||||
<App />
|
||||
</KibanaPageTemplate>
|
||||
</PlaygroundProvider>
|
||||
<Router history={services.history}>
|
||||
<PlaygroundRouter />
|
||||
</Router>
|
||||
</I18nProvider>
|
||||
</KibanaContextProvider>
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { EuiPageTemplate } from '@elastic/eui';
|
||||
import { PlaygroundProvider } from './providers/playground_provider';
|
||||
|
||||
import { App } from './components/app';
|
||||
import { PlaygroundToolbar } from './embeddable';
|
||||
import { PlaygroundHeaderDocs } from './components/playground_header_docs';
|
||||
|
||||
export const ChatPlaygroundOverview: React.FC = () => {
|
||||
return (
|
||||
<PlaygroundProvider
|
||||
defaultValues={{
|
||||
indices: [],
|
||||
}}
|
||||
>
|
||||
<EuiPageTemplate offset={0} grow restrictWidth data-test-subj="svlPlaygroundPage">
|
||||
<EuiPageTemplate.Header
|
||||
pageTitle={i18n.translate('xpack.searchPlayground.pageTitle', {
|
||||
defaultMessage: 'Playground',
|
||||
})}
|
||||
data-test-subj="svlPlaygroundPageTitle"
|
||||
restrictWidth
|
||||
rightSideItems={[<PlaygroundHeaderDocs />, <PlaygroundToolbar />]}
|
||||
/>
|
||||
<App />
|
||||
</EuiPageTemplate>
|
||||
</PlaygroundProvider>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 { EuiButtonEmpty } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { docLinks } from '../../common/doc_links';
|
||||
|
||||
export const PlaygroundHeaderDocs: React.FC = () => (
|
||||
<EuiButtonEmpty
|
||||
data-telemetry-id="playground-header-documentationLink"
|
||||
data-test-subj="playground-documentation-link"
|
||||
href={docLinks.chatPlayground}
|
||||
target="_blank"
|
||||
iconType="documents"
|
||||
>
|
||||
{i18n.translate('xpack.searchPlayground.pageTitle.header.docLink', {
|
||||
defaultMessage: 'Playground Docs',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
);
|
|
@ -23,6 +23,10 @@ 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<typeof PlaygroundProvider>) =>
|
||||
|
|
|
@ -14,7 +14,7 @@ export const useManagementLink = (connectorId: string) => {
|
|||
} = useKibana();
|
||||
const managementLocator = useMemo(
|
||||
() => share.url.locators.get('MANAGEMENT_APP_LOCATOR'),
|
||||
[share]
|
||||
[share.url.locators]
|
||||
);
|
||||
const [managementLink, setManagementLink] = useState('');
|
||||
useEffect(() => {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 { renderHook } from '@testing-library/react-hooks';
|
||||
import { useQueryIndices } from './use_query_indices';
|
||||
|
||||
jest.mock('./use_kibana', () => ({
|
||||
useKibana: jest.fn().mockReturnValue({
|
||||
services: {
|
||||
services: {
|
||||
http: {},
|
||||
},
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('./use_query_indices', () => ({
|
||||
useQueryIndices: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('useQueryIndices Hook', () => {
|
||||
afterEach(jest.clearAllMocks);
|
||||
|
||||
it('successfully loads indices', async () => {
|
||||
const mockUseQueryIndices = (data: string[]) => {
|
||||
(useQueryIndices as jest.Mock).mockReturnValue({ indices: data, isLoading: false });
|
||||
};
|
||||
const mockIndices = ['index-1', 'index-2'];
|
||||
mockUseQueryIndices(mockIndices);
|
||||
|
||||
const { result } = renderHook(() => useQueryIndices());
|
||||
expect(result.current).toEqual({ indices: ['index-1', 'index-2'], isLoading: false });
|
||||
});
|
||||
});
|
|
@ -8,7 +8,7 @@
|
|||
import { useQuery } from '@tanstack/react-query';
|
||||
import { IndexName } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { useKibana } from './use_kibana';
|
||||
import { ElasticsearchIndex } from '../types';
|
||||
import { APIRoutes } from '../types';
|
||||
|
||||
export const useQueryIndices = (
|
||||
query: string = ''
|
||||
|
@ -19,18 +19,15 @@ export const useQueryIndices = (
|
|||
queryKey: ['indices', query],
|
||||
queryFn: async () => {
|
||||
const response = await services.http.get<{
|
||||
indices: ElasticsearchIndex[];
|
||||
}>('/internal/enterprise_search/indices', {
|
||||
indices: string[];
|
||||
}>(APIRoutes.GET_INDICES, {
|
||||
query: {
|
||||
from: 0,
|
||||
only_show_search_optimized_indices: false,
|
||||
return_hidden_indices: false,
|
||||
search_query: query,
|
||||
size: 20,
|
||||
size: 10,
|
||||
},
|
||||
});
|
||||
|
||||
return response.indices.map((index) => index.name);
|
||||
return response.indices;
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { PluginInitializerContext } from '@kbn/core/public';
|
||||
|
||||
import { SearchPlaygroundPlugin } from './plugin';
|
||||
|
||||
export function plugin() {
|
||||
return new SearchPlaygroundPlugin();
|
||||
export function plugin(initializerContext: PluginInitializerContext) {
|
||||
return new SearchPlaygroundPlugin(initializerContext);
|
||||
}
|
||||
|
||||
export type { SearchPlaygroundPluginSetup, SearchPlaygroundPluginStart } from './types';
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { Route, Routes } from '@kbn/shared-ux-router';
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { ChatPlaygroundOverview } from './chat_playground_overview';
|
||||
|
||||
import { ROOT_PATH, SEARCH_PLAYGROUND_CHAT_PATH } from './routes';
|
||||
|
||||
export const PlaygroundRouter: React.FC = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Redirect exact from={ROOT_PATH} to={SEARCH_PLAYGROUND_CHAT_PATH} />
|
||||
<Route path={SEARCH_PLAYGROUND_CHAT_PATH}>
|
||||
<ChatPlaygroundOverview />
|
||||
</Route>
|
||||
</Routes>
|
||||
);
|
||||
};
|
|
@ -5,11 +5,20 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { CoreSetup, Plugin, CoreStart, AppMountParameters } from '@kbn/core/public';
|
||||
import {
|
||||
CoreSetup,
|
||||
Plugin,
|
||||
CoreStart,
|
||||
AppMountParameters,
|
||||
PluginInitializerContext,
|
||||
} from '@kbn/core/public';
|
||||
import { PLUGIN_ID, PLUGIN_NAME } from '../common';
|
||||
import { docLinks } from '../common/doc_links';
|
||||
import { PlaygroundHeaderDocs } from './components/playground_header_docs';
|
||||
import { PlaygroundToolbar, Playground, getPlaygroundProvider } from './embeddable';
|
||||
import {
|
||||
AppPluginStartDependencies,
|
||||
SearchPlaygroundConfigType,
|
||||
SearchPlaygroundPluginSetup,
|
||||
SearchPlaygroundPluginStart,
|
||||
} from './types';
|
||||
|
@ -17,27 +26,43 @@ import {
|
|||
export class SearchPlaygroundPlugin
|
||||
implements Plugin<SearchPlaygroundPluginSetup, SearchPlaygroundPluginStart>
|
||||
{
|
||||
public setup(core: CoreSetup): SearchPlaygroundPluginSetup {
|
||||
return {};
|
||||
private config: SearchPlaygroundConfigType;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.config = initializerContext.config.get<SearchPlaygroundConfigType>();
|
||||
}
|
||||
|
||||
public setup(
|
||||
core: CoreSetup<AppPluginStartDependencies, SearchPlaygroundPluginStart>
|
||||
): SearchPlaygroundPluginSetup {
|
||||
if (!this.config.ui?.enabled) return {};
|
||||
|
||||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
appRoute: '/app/search_playground',
|
||||
title: PLUGIN_NAME,
|
||||
async mount(params: AppMountParameters) {
|
||||
async mount({ element, history }: AppMountParameters) {
|
||||
const { renderApp } = await import('./application');
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
const startDeps: AppPluginStartDependencies = {
|
||||
...depsStart,
|
||||
history,
|
||||
};
|
||||
|
||||
return renderApp(coreStart, depsStart as AppPluginStartDependencies, params);
|
||||
return renderApp(coreStart, startDeps, element);
|
||||
},
|
||||
});
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
public start(core: CoreStart, deps: AppPluginStartDependencies): SearchPlaygroundPluginStart {
|
||||
docLinks.setDocLinks(core.docLinks.links);
|
||||
return {
|
||||
PlaygroundProvider: getPlaygroundProvider(core, deps),
|
||||
PlaygroundToolbar,
|
||||
Playground,
|
||||
PlaygroundHeaderDocs,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
9
x-pack/plugins/search_playground/public/routes.ts
Normal file
9
x-pack/plugins/search_playground/public/routes.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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 const ROOT_PATH = '/';
|
||||
export const SEARCH_PLAYGROUND_CHAT_PATH = `${ROOT_PATH}chat`;
|
|
@ -19,10 +19,12 @@ import React, { ComponentType } from 'react';
|
|||
import { 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 { ChatRequestData } from '../common/types';
|
||||
import type { App } from './components/app';
|
||||
import type { PlaygroundProvider as PlaygroundProviderComponent } from './providers/playground_provider';
|
||||
import type { Toolbar } from './components/toolbar';
|
||||
import { PlaygroundHeaderDocs } from './components/playground_header_docs';
|
||||
|
||||
export * from '../common/types';
|
||||
|
||||
|
@ -32,11 +34,14 @@ export interface SearchPlaygroundPluginStart {
|
|||
PlaygroundProvider: React.FC<React.ComponentProps<typeof PlaygroundProviderComponent>>;
|
||||
PlaygroundToolbar: React.FC<React.ComponentProps<typeof Toolbar>>;
|
||||
Playground: React.FC<React.ComponentProps<typeof App>>;
|
||||
PlaygroundHeaderDocs: React.FC<React.ComponentProps<typeof PlaygroundHeaderDocs>>;
|
||||
}
|
||||
|
||||
export interface AppPluginStartDependencies {
|
||||
history: AppMountParameters['history'];
|
||||
navigation: NavigationPublicPluginStart;
|
||||
triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
|
||||
share: SharePluginStart;
|
||||
}
|
||||
|
||||
export interface AppServicesContext {
|
||||
|
|
27
x-pack/plugins/search_playground/server/config.ts
Normal file
27
x-pack/plugins/search_playground/server/config.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 { schema, TypeOf } from '@kbn/config-schema';
|
||||
import { PluginConfigDescriptor } from '@kbn/core/server';
|
||||
|
||||
export * from './types';
|
||||
|
||||
const configSchema = schema.object({
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
ui: schema.object({
|
||||
enabled: schema.boolean({ defaultValue: false }),
|
||||
}),
|
||||
});
|
||||
|
||||
export type SearchPlaygroundConfig = TypeOf<typeof configSchema>;
|
||||
|
||||
export const config: PluginConfigDescriptor<SearchPlaygroundConfig> = {
|
||||
exposeToBrowser: {
|
||||
ui: true,
|
||||
},
|
||||
schema: configSchema,
|
||||
};
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import { PluginInitializerContext } from '@kbn/core/server';
|
||||
|
||||
export { config } from './config';
|
||||
|
||||
export async function plugin(initializerContext: PluginInitializerContext) {
|
||||
const { SearchPlaygroundPlugin } = await import('./plugin');
|
||||
return new SearchPlaygroundPlugin(initializerContext);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import type { Client } from '@elastic/elasticsearch';
|
||||
import { createAssist as Assist } from './assist';
|
||||
import { createAssist as Assist } from '../utils/assist';
|
||||
import { ConversationalChain } from './conversational_chain';
|
||||
import { FakeListLLM } from 'langchain/llms/fake';
|
||||
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
@ -17,10 +17,10 @@ import {
|
|||
} from 'ai';
|
||||
import { BaseLanguageModel } from '@langchain/core/language_models/base';
|
||||
import { ElasticsearchRetriever } from './elasticsearch_retriever';
|
||||
import { renderTemplate } from './render_template';
|
||||
import { renderTemplate } from '../utils/render_template';
|
||||
|
||||
import { AssistClient } from './assist';
|
||||
import { getCitations } from './get_citations';
|
||||
import { AssistClient } from '../utils/assist';
|
||||
import { getCitations } from '../utils/get_citations';
|
||||
|
||||
interface RAGOptions {
|
||||
index: string;
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 { ElasticsearchClient } from '@kbn/core/server';
|
||||
|
||||
import { fetchIndices } from './fetch_indices';
|
||||
|
||||
describe('fetch indices', () => {
|
||||
const mockIndexResponse = {
|
||||
'index-1': {
|
||||
aliases: {
|
||||
'search-alias-1': {},
|
||||
'search-alias-2': {},
|
||||
},
|
||||
},
|
||||
'index-2': {
|
||||
aliases: {
|
||||
'search-alias-1': {},
|
||||
'search-alias-2': {},
|
||||
},
|
||||
},
|
||||
'index-3': {
|
||||
aliases: {
|
||||
'search-alias-1': {},
|
||||
'search-alias-2': {},
|
||||
},
|
||||
},
|
||||
};
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
const mockClient = {
|
||||
asCurrentUser: { indices: { get: jest.fn() } },
|
||||
};
|
||||
|
||||
it('returns index data with for non-hidden indices', async () => {
|
||||
mockClient.asCurrentUser.indices.get.mockImplementationOnce(() => {
|
||||
return mockIndexResponse;
|
||||
});
|
||||
|
||||
const indexData = await fetchIndices(
|
||||
mockClient.asCurrentUser as unknown as ElasticsearchClient,
|
||||
undefined
|
||||
);
|
||||
|
||||
expect(indexData).toEqual({
|
||||
indexNames: ['index-1', 'index-2', 'index-3'],
|
||||
});
|
||||
});
|
||||
});
|
52
x-pack/plugins/search_playground/server/lib/fetch_indices.ts
Normal file
52
x-pack/plugins/search_playground/server/lib/fetch_indices.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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 { IndicesIndexState } from '@elastic/elasticsearch/lib/api/types';
|
||||
|
||||
import { ElasticsearchClient } from '@kbn/core/server';
|
||||
|
||||
function isHidden(index: IndicesIndexState): boolean {
|
||||
return index.settings?.index?.hidden === true || index.settings?.index?.hidden === 'true';
|
||||
}
|
||||
function isClosed(index: IndicesIndexState): boolean {
|
||||
return (
|
||||
index.settings?.index?.verified_before_close === true ||
|
||||
index.settings?.index?.verified_before_close === 'true'
|
||||
);
|
||||
}
|
||||
|
||||
export const fetchIndices = async (
|
||||
client: ElasticsearchClient,
|
||||
searchQuery: string | undefined
|
||||
): Promise<{
|
||||
indexNames: string[];
|
||||
}> => {
|
||||
const indexPattern = searchQuery ? `*${searchQuery}*` : '*';
|
||||
const allIndexMatches = await client.indices.get({
|
||||
expand_wildcards: ['open'],
|
||||
// for better performance only compute aliases and settings of indices but not mappings
|
||||
features: ['aliases', 'settings'],
|
||||
// only get specified index properties from ES to keep the response under 536MB
|
||||
// node.js string length limit: https://github.com/nodejs/node/issues/33960
|
||||
filter_path: ['*.aliases', '*.settings.index.hidden', '*.settings.index.verified_before_close'],
|
||||
index: indexPattern,
|
||||
});
|
||||
|
||||
const allIndexNames = Object.keys(allIndexMatches).filter(
|
||||
(indexName) =>
|
||||
allIndexMatches[indexName] &&
|
||||
!isHidden(allIndexMatches[indexName]) &&
|
||||
!isClosed(allIndexMatches[indexName])
|
||||
);
|
||||
const indexNames = searchQuery
|
||||
? allIndexNames.filter((indexName) => indexName.includes(searchQuery.toLowerCase()))
|
||||
: allIndexNames;
|
||||
|
||||
return {
|
||||
indexNames,
|
||||
};
|
||||
};
|
|
@ -9,16 +9,18 @@ import { schema } from '@kbn/config-schema';
|
|||
import { streamFactory } from '@kbn/ml-response-stream/server';
|
||||
import type { Logger } from '@kbn/logging';
|
||||
import { IRouter, StartServicesAccessor } from '@kbn/core/server';
|
||||
import { fetchFields } from './utils/fetch_query_source_fields';
|
||||
import { fetchFields } from './lib/fetch_query_source_fields';
|
||||
import { AssistClientOptionsWithClient, createAssist as Assist } from './utils/assist';
|
||||
import { ConversationalChain } from './utils/conversational_chain';
|
||||
import { ConversationalChain } from './lib/conversational_chain';
|
||||
import { errorHandler } from './utils/error_handler';
|
||||
import {
|
||||
APIRoutes,
|
||||
SearchPlaygroundPluginStart,
|
||||
SearchPlaygroundPluginStartDependencies,
|
||||
} from './types';
|
||||
import { getChatParams } from './utils/get_chat_params';
|
||||
import { getChatParams } from './lib/get_chat_params';
|
||||
import { fetchIndices } from './lib/fetch_indices';
|
||||
import { isNotNullish } from '../common/is_not_nullish';
|
||||
|
||||
export function createRetriever(esQuery: string) {
|
||||
return (question: string) => {
|
||||
|
@ -199,4 +201,35 @@ export function defineRoutes({
|
|||
});
|
||||
})
|
||||
);
|
||||
|
||||
// SECURITY: We don't apply any authorization tags to this route because all actions performed
|
||||
// on behalf of the user making the request and governed by the user's own cluster privileges.
|
||||
router.get(
|
||||
{
|
||||
path: APIRoutes.GET_INDICES,
|
||||
validate: {
|
||||
query: schema.object({
|
||||
search_query: schema.maybe(schema.string()),
|
||||
size: schema.number({ defaultValue: 10, min: 0 }),
|
||||
}),
|
||||
},
|
||||
},
|
||||
errorHandler(async (context, request, response) => {
|
||||
const { search_query: searchQuery, size } = request.query;
|
||||
const {
|
||||
client: { asCurrentUser },
|
||||
} = (await context.core).elasticsearch;
|
||||
|
||||
const { indexNames } = await fetchIndices(asCurrentUser, searchQuery);
|
||||
|
||||
const indexNameSlice = indexNames.slice(0, size).filter(isNotNullish);
|
||||
|
||||
return response.ok({
|
||||
body: {
|
||||
indices: indexNameSlice,
|
||||
},
|
||||
headers: { 'content-type': 'application/json' },
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
"@kbn/cases-plugin",
|
||||
"@kbn/triggers-actions-ui-plugin",
|
||||
"@kbn/elastic-assistant-common",
|
||||
"@kbn/logging"
|
||||
"@kbn/logging",
|
||||
"@kbn/doc-links"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -11,7 +11,6 @@ import { CONNECTORS_LABEL } from '../common/i18n_string';
|
|||
|
||||
export const navigationTree: NavigationTreeDefinition = {
|
||||
body: [
|
||||
{ type: 'recentlyAccessed' },
|
||||
{
|
||||
type: 'navGroup',
|
||||
id: 'search_project_nav',
|
||||
|
@ -38,61 +37,66 @@ export const navigationTree: NavigationTreeDefinition = {
|
|||
getIsActive: ({ pathNameSerialized, prepend }) => {
|
||||
return pathNameSerialized.startsWith(prepend('/app/dev_tools'));
|
||||
},
|
||||
spaceBefore: 'm',
|
||||
},
|
||||
{
|
||||
link: 'discover',
|
||||
spaceBefore: 'm',
|
||||
},
|
||||
{
|
||||
link: 'dashboards',
|
||||
getIsActive: ({ pathNameSerialized, prepend }) => {
|
||||
return pathNameSerialized.startsWith(prepend('/app/dashboards'));
|
||||
},
|
||||
},
|
||||
{
|
||||
link: 'management:triggersActions',
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.alerts', {
|
||||
defaultMessage: 'Alerts',
|
||||
id: 'kibana',
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.kibana', {
|
||||
defaultMessage: 'Kibana',
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.content.indices', {
|
||||
defaultMessage: 'Index Management',
|
||||
}),
|
||||
link: 'management:index_management',
|
||||
breadcrumbStatus: 'hidden' /* management sub-pages set their breadcrumbs themselves */,
|
||||
spaceBefore: 'm',
|
||||
children: [
|
||||
{
|
||||
link: 'discover',
|
||||
},
|
||||
{
|
||||
link: 'dashboards',
|
||||
getIsActive: ({ pathNameSerialized, prepend }) => {
|
||||
return pathNameSerialized.startsWith(prepend('/app/dashboards'));
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.content.pipelines', {
|
||||
defaultMessage: 'Pipelines',
|
||||
id: 'content',
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.content', {
|
||||
defaultMessage: 'Content',
|
||||
}),
|
||||
link: 'management:ingest_pipelines',
|
||||
breadcrumbStatus: 'hidden' /* management sub-pages set their breadcrumbs themselves */,
|
||||
},
|
||||
{
|
||||
title: CONNECTORS_LABEL,
|
||||
link: 'serverlessConnectors',
|
||||
},
|
||||
{
|
||||
link: 'management:api_keys',
|
||||
breadcrumbStatus: 'hidden' /* management sub-pages set their breadcrumbs themselves */,
|
||||
spaceBefore: 'm',
|
||||
children: [
|
||||
{
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.content.indices', {
|
||||
defaultMessage: 'Index Management',
|
||||
}),
|
||||
link: 'management:index_management',
|
||||
breadcrumbStatus:
|
||||
'hidden' /* management sub-pages set their breadcrumbs themselves */,
|
||||
},
|
||||
{
|
||||
title: CONNECTORS_LABEL,
|
||||
link: 'serverlessConnectors',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'build',
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.build', {
|
||||
defaultMessage: 'Build',
|
||||
}),
|
||||
spaceBefore: 'm',
|
||||
children: [
|
||||
{
|
||||
id: 'searchPlayground',
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.build.searchPlayground', {
|
||||
defaultMessage: 'Playground',
|
||||
}),
|
||||
link: 'searchPlayground',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
footer: [
|
||||
{
|
||||
type: 'navItem',
|
||||
id: 'search_getting_started',
|
||||
title: i18n.translate('xpack.serverlessSearch.nav.gettingStarted', {
|
||||
defaultMessage: 'Get started',
|
||||
}),
|
||||
icon: 'launch',
|
||||
link: 'serverlessElasticsearch',
|
||||
},
|
||||
{
|
||||
type: 'navGroup',
|
||||
id: 'project_settings_project_nav',
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public';
|
||||
import { ConsolePluginStart } from '@kbn/console-plugin/public';
|
||||
import { SearchPlaygroundPluginStart } from '@kbn/search-playground/public';
|
||||
import { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public';
|
||||
import { SecurityPluginStart } from '@kbn/security-plugin/public';
|
||||
import { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public';
|
||||
|
@ -30,6 +31,7 @@ export interface ServerlessSearchPluginSetupDependencies {
|
|||
export interface ServerlessSearchPluginStartDependencies {
|
||||
cloud: CloudStart;
|
||||
console: ConsolePluginStart;
|
||||
searchPlayground: SearchPlaygroundPluginStart;
|
||||
management: ManagementStart;
|
||||
security: SecurityPluginStart;
|
||||
serverless: ServerlessPluginStart;
|
||||
|
|
|
@ -47,5 +47,6 @@
|
|||
"@kbn/discover-plugin",
|
||||
"@kbn/search-connectors-plugin",
|
||||
"@kbn/index-management",
|
||||
"@kbn/search-playground",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -38430,11 +38430,8 @@
|
|||
"xpack.serverlessSearch.languages.ruby": "Ruby",
|
||||
"xpack.serverlessSearch.languages.ruby.githubLabel": "elasticsearch-serverless-ruby",
|
||||
"xpack.serverlessSearch.learnMore": "En savoir plus",
|
||||
"xpack.serverlessSearch.nav.alerts": "Alertes",
|
||||
"xpack.serverlessSearch.nav.content.indices": "Gestion des index",
|
||||
"xpack.serverlessSearch.nav.content.pipelines": "Pipelines",
|
||||
"xpack.serverlessSearch.nav.devTools": "Outils de développement",
|
||||
"xpack.serverlessSearch.nav.gettingStarted": "Démarrer",
|
||||
"xpack.serverlessSearch.nav.home": "Accueil",
|
||||
"xpack.serverlessSearch.nav.mngt": "Gestion",
|
||||
"xpack.serverlessSearch.nav.performance": "Performances",
|
||||
|
|
|
@ -38398,11 +38398,8 @@
|
|||
"xpack.serverlessSearch.languages.ruby": "Ruby",
|
||||
"xpack.serverlessSearch.languages.ruby.githubLabel": "elasticsearch-serverless-ruby",
|
||||
"xpack.serverlessSearch.learnMore": "詳細",
|
||||
"xpack.serverlessSearch.nav.alerts": "アラート",
|
||||
"xpack.serverlessSearch.nav.content.indices": "インデックス管理",
|
||||
"xpack.serverlessSearch.nav.content.pipelines": "パイプライン",
|
||||
"xpack.serverlessSearch.nav.devTools": "開発ツール",
|
||||
"xpack.serverlessSearch.nav.gettingStarted": "使ってみる",
|
||||
"xpack.serverlessSearch.nav.home": "ホーム",
|
||||
"xpack.serverlessSearch.nav.mngt": "管理",
|
||||
"xpack.serverlessSearch.nav.performance": "パフォーマンス",
|
||||
|
|
|
@ -38442,11 +38442,8 @@
|
|||
"xpack.serverlessSearch.languages.ruby": "Ruby",
|
||||
"xpack.serverlessSearch.languages.ruby.githubLabel": "elasticsearch-serverless-ruby",
|
||||
"xpack.serverlessSearch.learnMore": "了解详情",
|
||||
"xpack.serverlessSearch.nav.alerts": "告警",
|
||||
"xpack.serverlessSearch.nav.content.indices": "索引管理",
|
||||
"xpack.serverlessSearch.nav.content.pipelines": "管道",
|
||||
"xpack.serverlessSearch.nav.devTools": "开发工具",
|
||||
"xpack.serverlessSearch.nav.gettingStarted": "开始使用",
|
||||
"xpack.serverlessSearch.nav.home": "主页",
|
||||
"xpack.serverlessSearch.nav.mngt": "管理",
|
||||
"xpack.serverlessSearch.nav.performance": "性能",
|
||||
|
|
|
@ -43,5 +43,10 @@ export function SvlManagementPageProvider({ getService }: FtrProviderContext) {
|
|||
async clickOrgMembersManagementCard() {
|
||||
await testSubjects.click('app-card-organization_members');
|
||||
},
|
||||
|
||||
// Ingest Pipelines
|
||||
async clickIngestPipelinesManagementCard() {
|
||||
await testSubjects.click('app-card-ingest_pipelines');
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -71,17 +71,12 @@ export default function ({ getPageObject, getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it("management apps from the sidenav hide the 'stack management' root from the breadcrumbs", async () => {
|
||||
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management:triggersActions' });
|
||||
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['Alerts', 'Rules']);
|
||||
|
||||
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management:index_management' });
|
||||
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['Index Management', 'Indices']);
|
||||
|
||||
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management:ingest_pipelines' });
|
||||
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['Ingest Pipelines']);
|
||||
|
||||
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'management:api_keys' });
|
||||
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts(['API keys']);
|
||||
await svlCommonNavigation.breadcrumbs.expectBreadcrumbTexts([
|
||||
'Content',
|
||||
'Index Management',
|
||||
'Indices',
|
||||
]);
|
||||
});
|
||||
|
||||
it('navigate management', async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue