mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Search] Homepage Plugin setup (#186224)
## Summary Introducing the `search_homepage` plugin along with integration into `enterprise_search` and `serverless_search` behind a feature flag. This will allow implementing the feature gated behind the feature flag. To test these changes you can enable the feature flag with the Kibana Dev Console using the following command: ``` POST kbn:/internal/kibana/settings/searchHomepage:homepageEnabled {"value": true} ``` You can then disable the feature flag with the following command: ``` DELETE kbn:/internal/kibana/settings/searchHomepage:homepageEnabled ``` ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
e2b772aeae
commit
74c4d3a85e
59 changed files with 1025 additions and 56 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -716,6 +716,7 @@ packages/kbn-search-connectors @elastic/search-kibana
|
|||
x-pack/plugins/search_connectors @elastic/search-kibana
|
||||
packages/kbn-search-errors @elastic/kibana-data-discovery
|
||||
examples/search_examples @elastic/kibana-data-discovery
|
||||
x-pack/plugins/search_homepage @elastic/search-kibana
|
||||
packages/kbn-search-index-documents @elastic/search-kibana
|
||||
x-pack/plugins/search_inference_endpoints @elastic/search-kibana
|
||||
x-pack/plugins/search_notebooks @elastic/search-kibana
|
||||
|
|
|
@ -69,3 +69,6 @@ xpack.searchInferenceEndpoints.ui.enabled: false
|
|||
|
||||
# Search Notebooks
|
||||
xpack.search.notebooks.catalog.url: https://elastic-enterprise-search.s3.us-east-2.amazonaws.com/serverless/catalog.json
|
||||
|
||||
# Search Homepage
|
||||
xpack.search.homepage.ui.enabled: true
|
||||
|
|
|
@ -789,6 +789,10 @@ It uses Chromium and Puppeteer underneath to run the browser in headless mode.
|
|||
|This plugin contains common assets and endpoints for the use of connectors in Kibana. Primarily used by the enterprise_search and serverless_search plugins.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/x-pack/plugins/search_homepage/README.mdx[searchHomepage]
|
||||
|The Search Homepage is a shared homepage for elasticsearch users.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/x-pack/plugins/search_inference_endpoints/README.md[searchInferenceEndpoints]
|
||||
|The Inference Endpoints is a tool used to manage inference endpoints
|
||||
|
||||
|
|
|
@ -727,6 +727,7 @@
|
|||
"@kbn/search-connectors-plugin": "link:x-pack/plugins/search_connectors",
|
||||
"@kbn/search-errors": "link:packages/kbn-search-errors",
|
||||
"@kbn/search-examples-plugin": "link:examples/search_examples",
|
||||
"@kbn/search-homepage": "link:x-pack/plugins/search_homepage",
|
||||
"@kbn/search-index-documents": "link:packages/kbn-search-index-documents",
|
||||
"@kbn/search-inference-endpoints": "link:x-pack/plugins/search_inference_endpoints",
|
||||
"@kbn/search-notebooks": "link:x-pack/plugins/search_notebooks",
|
||||
|
|
|
@ -17,3 +17,4 @@ export const SERVERLESS_ES_APP_ID = 'serverlessElasticsearch';
|
|||
export const SERVERLESS_ES_CONNECTORS_ID = 'serverlessConnectors';
|
||||
export const SERVERLESS_ES_SEARCH_PLAYGROUND_ID = 'searchPlayground';
|
||||
export const SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID = 'searchInferenceEndpoints';
|
||||
export const SEARCH_HOMEPAGE = 'searchHomepage';
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
ENTERPRISE_SEARCH_WORKPLACESEARCH_APP_ID,
|
||||
SERVERLESS_ES_SEARCH_PLAYGROUND_ID,
|
||||
SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID,
|
||||
SEARCH_HOMEPAGE,
|
||||
} from './constants';
|
||||
|
||||
export type EnterpriseSearchApp = typeof ENTERPRISE_SEARCH_APP_ID;
|
||||
|
@ -29,6 +30,7 @@ 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 SearchInferenceEndpointsId = typeof SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID;
|
||||
export type SearchHomepage = typeof SEARCH_HOMEPAGE;
|
||||
|
||||
export type ContentLinkId = 'searchIndices' | 'connectors' | 'webCrawlers';
|
||||
|
||||
|
@ -47,6 +49,7 @@ export type DeepLinkId =
|
|||
| ConnectorsId
|
||||
| SearchPlaygroundId
|
||||
| SearchInferenceEndpointsId
|
||||
| SearchHomepage
|
||||
| `${EnterpriseSearchContentApp}:${ContentLinkId}`
|
||||
| `${EnterpriseSearchApplicationsApp}:${ApplicationsLinkId}`
|
||||
| `${EnterpriseSearchAppsearchApp}:${AppsearchLinkId}`;
|
||||
|
|
|
@ -132,6 +132,7 @@ pageLoadAssetSize:
|
|||
screenshotMode: 17856
|
||||
screenshotting: 22870
|
||||
searchConnectors: 30000
|
||||
searchHomepage: 19831
|
||||
searchInferenceEndpoints: 20470
|
||||
searchNotebooks: 18942
|
||||
searchPlayground: 19325
|
||||
|
|
|
@ -313,8 +313,9 @@ 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.search.homepage.ui.enabled (boolean)',
|
||||
'xpack.searchInferenceEndpoints.ui.enabled (boolean)',
|
||||
'xpack.searchPlayground.ui.enabled (boolean)',
|
||||
'xpack.security.loginAssistanceMessage (string)',
|
||||
'xpack.security.sameSiteCookies (alternatives)',
|
||||
'xpack.security.showInsecureClusterWarning (boolean)',
|
||||
|
|
|
@ -1426,6 +1426,8 @@
|
|||
"@kbn/search-errors/*": ["packages/kbn-search-errors/*"],
|
||||
"@kbn/search-examples-plugin": ["examples/search_examples"],
|
||||
"@kbn/search-examples-plugin/*": ["examples/search_examples/*"],
|
||||
"@kbn/search-homepage": ["x-pack/plugins/search_homepage"],
|
||||
"@kbn/search-homepage/*": ["x-pack/plugins/search_homepage/*"],
|
||||
"@kbn/search-index-documents": ["packages/kbn-search-index-documents"],
|
||||
"@kbn/search-index-documents/*": ["packages/kbn-search-index-documents/*"],
|
||||
"@kbn/search-inference-endpoints": ["x-pack/plugins/search_inference_endpoints"],
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
"xpack.rollupJobs": ["plugins/rollup"],
|
||||
"xpack.runtimeFields": "plugins/runtime_fields",
|
||||
"xpack.screenshotting": "plugins/screenshotting",
|
||||
"xpack.searchHomepage": "plugins/search_homepage",
|
||||
"xpack.searchNotebooks": "plugins/search_notebooks",
|
||||
"xpack.searchPlayground": "plugins/search_playground",
|
||||
"xpack.searchInferenceEndpoints": "plugins/search_inference_endpoints",
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
"guidedOnboarding",
|
||||
"console",
|
||||
"searchConnectors",
|
||||
"searchHomepage",
|
||||
"searchPlayground",
|
||||
"searchInferenceEndpoints",
|
||||
"embeddable",
|
||||
|
|
|
@ -45,6 +45,7 @@ export const mockKibanaValues = {
|
|||
history: mockHistory,
|
||||
indexMappingComponent: null,
|
||||
isCloud: false,
|
||||
isSearchHomepageEnabled: false,
|
||||
isSidebarEnabled: true,
|
||||
lens: {
|
||||
EmbeddableComponent: jest.fn(),
|
||||
|
@ -64,6 +65,7 @@ export const mockKibanaValues = {
|
|||
hasWebCrawler: true,
|
||||
},
|
||||
renderHeaderActions: jest.fn(),
|
||||
searchHomepage: null,
|
||||
searchInferenceEndpoints: null,
|
||||
searchPlayground: searchPlaygroundMock.createStart(),
|
||||
security: securityMock.createStart(),
|
||||
|
|
|
@ -117,6 +117,7 @@ export const renderApp = (
|
|||
guidedOnboarding,
|
||||
history,
|
||||
indexMappingComponent,
|
||||
isSearchHomepageEnabled: plugins.searchHomepage?.isHomepageFeatureEnabled() ?? false,
|
||||
isSidebarEnabled,
|
||||
lens,
|
||||
ml,
|
||||
|
@ -127,6 +128,7 @@ export const renderApp = (
|
|||
params.setHeaderActionMenu(
|
||||
HeaderActions ? renderHeaderActions.bind(null, HeaderActions, store, params) : undefined
|
||||
),
|
||||
searchHomepage: plugins.searchHomepage,
|
||||
searchPlayground: plugins.searchPlayground,
|
||||
searchInferenceEndpoints: plugins.searchInferenceEndpoints,
|
||||
security,
|
||||
|
|
|
@ -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 { TestHelper } from '../../../test_helpers/test_utils.test_helper';
|
||||
|
||||
import { SearchHomepagePageTemplate } from './page_template';
|
||||
|
||||
describe('SearchHomepagePageTemplate', () => {
|
||||
beforeAll(() => {
|
||||
TestHelper.prepare();
|
||||
});
|
||||
|
||||
it('renders as expected', async () => {
|
||||
const { container } = TestHelper.render(
|
||||
<SearchHomepagePageTemplate>
|
||||
<div>Test</div>
|
||||
</SearchHomepagePageTemplate>
|
||||
);
|
||||
|
||||
expect(container.querySelector('.kbnSolutionNav__title')).toHaveTextContent('Search');
|
||||
});
|
||||
});
|
|
@ -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 React from 'react';
|
||||
|
||||
import { SEARCH_PRODUCT_NAME } from '../../../../../common/constants';
|
||||
import { SetSearchChrome } from '../../../shared/kibana_chrome';
|
||||
import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout';
|
||||
import { useEnterpriseSearchNav } from '../../../shared/layout';
|
||||
import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry';
|
||||
|
||||
export const SearchHomepagePageTemplate: React.FC<PageTemplateProps> = ({
|
||||
children,
|
||||
pageChrome,
|
||||
pageViewTelemetry,
|
||||
...pageTemplateProps
|
||||
}) => {
|
||||
return (
|
||||
<EnterpriseSearchPageTemplateWrapper
|
||||
{...pageTemplateProps}
|
||||
solutionNav={{
|
||||
name: SEARCH_PRODUCT_NAME,
|
||||
items: useEnterpriseSearchNav(),
|
||||
}}
|
||||
setPageChrome={pageChrome && <SetSearchChrome trail={pageChrome} />}
|
||||
>
|
||||
{pageViewTelemetry && (
|
||||
<SendEnterpriseSearchTelemetry action="viewed" metric={pageViewTelemetry} />
|
||||
)}
|
||||
{children}
|
||||
</EnterpriseSearchPageTemplateWrapper>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 { SetSearchChrome } from '../../shared/kibana_chrome';
|
||||
|
||||
import { SearchHomepagePageTemplate } from './layout/page_template';
|
||||
|
||||
export const SearchHomepagePage = () => {
|
||||
const { isSearchHomepageEnabled, searchHomepage } = useValues(KibanaLogic);
|
||||
|
||||
if (!isSearchHomepageEnabled || !searchHomepage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SearchHomepagePageTemplate
|
||||
restrictWidth={false}
|
||||
grow={false}
|
||||
offset={0}
|
||||
pageViewTelemetry="searchHomepage"
|
||||
>
|
||||
<SetSearchChrome />
|
||||
<searchHomepage.SearchHomepage />
|
||||
</SearchHomepagePageTemplate>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 { Routes, Route } from '@kbn/shared-ux-router';
|
||||
|
||||
import { isVersionMismatch } from '../../../common/is_version_mismatch';
|
||||
import type { InitialAppData } from '../../../common/types';
|
||||
import { VersionMismatchPage } from '../shared/version_mismatch';
|
||||
|
||||
import { SearchHomepagePage } from './components/search_homepage';
|
||||
|
||||
export const SearchHomepage: React.FC<InitialAppData> = (props) => {
|
||||
const { enterpriseSearchVersion, kibanaVersion } = props;
|
||||
const incompatibleVersions = isVersionMismatch(enterpriseSearchVersion, kibanaVersion);
|
||||
|
||||
const showView = () => {
|
||||
if (incompatibleVersions) {
|
||||
return (
|
||||
<VersionMismatchPage
|
||||
enterpriseSearchVersion={enterpriseSearchVersion}
|
||||
kibanaVersion={kibanaVersion}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <SearchHomepagePage />;
|
||||
};
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route exact path="/">
|
||||
{showView()}
|
||||
</Route>
|
||||
</Routes>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../../../../..',
|
||||
roots: ['<rootDir>/x-pack/plugins/enterprise_search/public/applications/search_homepage'],
|
||||
collectCoverage: true,
|
||||
coverageReporters: ['text', 'html'],
|
||||
collectCoverageFrom: [
|
||||
'<rootDir>/x-pack/plugins/enterprise_search/public/applications/**/*.{ts,tsx}',
|
||||
'!<rootDir>/x-pack/plugins/enterprise_search/public/*.ts',
|
||||
'!<rootDir>/x-pack/plugins/enterprise_search/server/*.ts',
|
||||
'!<rootDir>/x-pack/plugins/enterprise_search/public/applications/test_helpers/**/*.{ts,tsx}',
|
||||
],
|
||||
coverageDirectory:
|
||||
'<rootDir>/target/kibana-coverage/jest/x-pack/plugins/enterprise_search/public/applications/search_homepage',
|
||||
modulePathIgnorePatterns: [
|
||||
'<rootDir>/x-pack/plugins/enterprise_search/public/applications/app_search/cypress',
|
||||
'<rootDir>/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress',
|
||||
],
|
||||
};
|
|
@ -29,6 +29,7 @@ import { LensPublicStart } from '@kbn/lens-plugin/public';
|
|||
import { MlPluginStart } from '@kbn/ml-plugin/public';
|
||||
import { ELASTICSEARCH_URL_PLACEHOLDER } from '@kbn/search-api-panels/constants';
|
||||
import { ConnectorDefinition } from '@kbn/search-connectors-plugin/public';
|
||||
import type { SearchHomepagePluginStart } from '@kbn/search-homepage/public';
|
||||
import { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public';
|
||||
import { SearchPlaygroundPluginStart } from '@kbn/search-playground/public';
|
||||
import { AuthenticatedUser, SecurityPluginStart } from '@kbn/security-plugin/public';
|
||||
|
@ -58,6 +59,7 @@ export interface KibanaLogicProps {
|
|||
guidedOnboarding?: GuidedOnboardingPluginStart;
|
||||
history: ScopedHistory;
|
||||
indexMappingComponent?: React.FC<IndexMappingProps>;
|
||||
isSearchHomepageEnabled: boolean;
|
||||
isSidebarEnabled: boolean;
|
||||
lens?: LensPublicStart;
|
||||
ml?: MlPluginStart;
|
||||
|
@ -65,6 +67,7 @@ export interface KibanaLogicProps {
|
|||
productAccess: ProductAccess;
|
||||
productFeatures: ProductFeatures;
|
||||
renderHeaderActions(HeaderActions?: FC): void;
|
||||
searchHomepage?: SearchHomepagePluginStart;
|
||||
searchPlayground?: SearchPlaygroundPluginStart;
|
||||
searchInferenceEndpoints?: SearchInferenceEndpointsPluginStart;
|
||||
security?: SecurityPluginStart;
|
||||
|
@ -91,6 +94,7 @@ export interface KibanaValues {
|
|||
history: ScopedHistory;
|
||||
indexMappingComponent: React.FC<IndexMappingProps> | null;
|
||||
isCloud: boolean;
|
||||
isSearchHomepageEnabled: boolean;
|
||||
isSidebarEnabled: boolean;
|
||||
lens: LensPublicStart | null;
|
||||
ml: MlPluginStart | null;
|
||||
|
@ -98,6 +102,7 @@ export interface KibanaValues {
|
|||
productAccess: ProductAccess;
|
||||
productFeatures: ProductFeatures;
|
||||
renderHeaderActions(HeaderActions?: FC): void;
|
||||
searchHomepage: SearchHomepagePluginStart | null;
|
||||
searchPlayground: SearchPlaygroundPluginStart | null;
|
||||
searchInferenceEndpoints: SearchInferenceEndpointsPluginStart | null;
|
||||
security: SecurityPluginStart | null;
|
||||
|
@ -129,6 +134,7 @@ export const KibanaLogic = kea<MakeLogicType<KibanaValues>>({
|
|||
guidedOnboarding: [props.guidedOnboarding || null, {}],
|
||||
history: [props.history, {}],
|
||||
indexMappingComponent: [props.indexMappingComponent || null, {}],
|
||||
isSearchHomepageEnabled: [props.isSearchHomepageEnabled, {}],
|
||||
isSidebarEnabled: [props.isSidebarEnabled, {}],
|
||||
lens: [props.lens || null, {}],
|
||||
ml: [props.ml || null, {}],
|
||||
|
@ -143,6 +149,7 @@ export const KibanaLogic = kea<MakeLogicType<KibanaValues>>({
|
|||
productAccess: [props.productAccess, {}],
|
||||
productFeatures: [props.productFeatures, {}],
|
||||
renderHeaderActions: [props.renderHeaderActions, {}],
|
||||
searchHomepage: [props.searchHomepage || null, {}],
|
||||
searchPlayground: [props.searchPlayground || null, {}],
|
||||
searchInferenceEndpoints: [props.searchInferenceEndpoints || null, {}],
|
||||
security: [props.security || null, {}],
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 { ENTERPRISE_SEARCH_OVERVIEW_PLUGIN } from '../../../../common/constants';
|
||||
|
||||
/**
|
||||
* HACK for base homepage URL, this can be removed and updated to a static
|
||||
* URL when Search Homepage is no longer feature flagged.
|
||||
*/
|
||||
const breadCrumbHome = { url: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL };
|
||||
export const getHomeURL = () => breadCrumbHome.url;
|
||||
export const setBreadcrumbHomeUrl = (url: string) => {
|
||||
breadCrumbHome.url = url;
|
||||
};
|
|
@ -15,7 +15,6 @@ import {
|
|||
APP_SEARCH_PLUGIN,
|
||||
ENTERPRISE_SEARCH_CONTENT_PLUGIN,
|
||||
INFERENCE_ENDPOINTS_PLUGIN,
|
||||
ENTERPRISE_SEARCH_OVERVIEW_PLUGIN,
|
||||
ENTERPRISE_SEARCH_PRODUCT_NAME,
|
||||
AI_SEARCH_PLUGIN,
|
||||
SEARCH_EXPERIENCES_PLUGIN,
|
||||
|
@ -29,6 +28,8 @@ import { HttpLogic } from '../http';
|
|||
import { KibanaLogic } from '../kibana';
|
||||
import { letBrowserHandleEvent, createHref } from '../react_router_helpers';
|
||||
|
||||
import { getHomeURL } from './breadcrumbs_home';
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
|
@ -107,7 +108,7 @@ export const useSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
|
|||
useEuiBreadcrumbs([
|
||||
{
|
||||
text: SEARCH_PRODUCT_NAME,
|
||||
path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL,
|
||||
path: getHomeURL(),
|
||||
shouldNotCreateHref: true,
|
||||
},
|
||||
...breadcrumbs,
|
||||
|
@ -117,7 +118,7 @@ export const useEnterpriseSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
|
|||
useEuiBreadcrumbs([
|
||||
{
|
||||
text: ENTERPRISE_SEARCH_PRODUCT_NAME,
|
||||
path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL,
|
||||
path: getHomeURL(),
|
||||
shouldNotCreateHref: true,
|
||||
},
|
||||
...breadcrumbs,
|
||||
|
|
|
@ -49,7 +49,8 @@ import { generateNavLink } from './nav_link_helpers';
|
|||
* @returns The Enterprise Search navigation items
|
||||
*/
|
||||
export const useEnterpriseSearchNav = (alwaysReturn = false) => {
|
||||
const { isSidebarEnabled, productAccess } = useValues(KibanaLogic);
|
||||
const { isSearchHomepageEnabled, searchHomepage, isSidebarEnabled, productAccess } =
|
||||
useValues(KibanaLogic);
|
||||
const indicesNavItems = useIndicesNav();
|
||||
if (!isSidebarEnabled && !alwaysReturn) return undefined;
|
||||
|
||||
|
@ -66,7 +67,10 @@ export const useEnterpriseSearchNav = (alwaysReturn = false) => {
|
|||
...generateNavLink({
|
||||
shouldNotCreateHref: true,
|
||||
shouldShowActiveForSubroutes: true,
|
||||
to: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL,
|
||||
to:
|
||||
isSearchHomepageEnabled && searchHomepage
|
||||
? searchHomepage.app.appRoute
|
||||
: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL,
|
||||
}),
|
||||
},
|
||||
{
|
||||
|
|
|
@ -62,6 +62,7 @@ export const mockKibanaProps: KibanaLogicProps = {
|
|||
indexMappingComponent: () => {
|
||||
return <></>;
|
||||
},
|
||||
isSearchHomepageEnabled: false,
|
||||
isSidebarEnabled: true,
|
||||
lens: {
|
||||
EmbeddableComponent: jest.fn(),
|
||||
|
@ -84,6 +85,7 @@ export const mockKibanaProps: KibanaLogicProps = {
|
|||
hasWebCrawler: true,
|
||||
},
|
||||
renderHeaderActions: jest.fn(),
|
||||
searchHomepage: undefined,
|
||||
searchPlayground: searchPlaygroundMock.createStart(),
|
||||
security: securityMock.createStart(),
|
||||
setBreadcrumbs: jest.fn(),
|
||||
|
@ -114,7 +116,7 @@ interface TestHelper {
|
|||
defaultMockValues: typeof DEFAULT_VALUES;
|
||||
mountLogic: (logicFile: LogicFile, props?: object) => void;
|
||||
prepare: (options?: PrepareOptions) => void;
|
||||
render: (children: JSX.Element) => void;
|
||||
render: (children: JSX.Element) => ReturnType<typeof testingLibraryRender>;
|
||||
}
|
||||
|
||||
export const TestHelper: TestHelper = {
|
||||
|
@ -147,7 +149,7 @@ export const TestHelper: TestHelper = {
|
|||
TestHelper.actionsToRun.forEach((action) => {
|
||||
action();
|
||||
});
|
||||
testingLibraryRender(
|
||||
return testingLibraryRender(
|
||||
<I18nProvider>
|
||||
<Provider>{children}</Provider>
|
||||
</I18nProvider>
|
||||
|
|
|
@ -67,12 +67,14 @@ const euiItemTypeToNodeDefinition = ({
|
|||
|
||||
export const getNavigationTreeDefinition = ({
|
||||
dynamicItems$,
|
||||
isSearchHomepageEnabled,
|
||||
}: {
|
||||
dynamicItems$: Observable<DynamicSideNavItems>;
|
||||
isSearchHomepageEnabled: boolean;
|
||||
}): AddSolutionNavigationArg => {
|
||||
return {
|
||||
dataTestSubj: 'searchSideNav',
|
||||
homePage: 'enterpriseSearch',
|
||||
homePage: isSearchHomepageEnabled ? 'searchHomepage' : 'enterpriseSearch',
|
||||
icon,
|
||||
id: 'es',
|
||||
navigationTree$: dynamicItems$.pipe(
|
||||
|
@ -84,7 +86,7 @@ export const getNavigationTreeDefinition = ({
|
|||
breadcrumbStatus: 'hidden',
|
||||
children: [
|
||||
{
|
||||
link: 'enterpriseSearch',
|
||||
link: isSearchHomepageEnabled ? 'searchHomepage' : 'enterpriseSearch',
|
||||
},
|
||||
{
|
||||
getIsActive: ({ pathNameSerialized, prepend }) => {
|
||||
|
|
|
@ -32,6 +32,10 @@ import { MlPluginStart } from '@kbn/ml-plugin/public';
|
|||
import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public';
|
||||
import { ELASTICSEARCH_URL_PLACEHOLDER } from '@kbn/search-api-panels/constants';
|
||||
import { SearchConnectorsPluginStart } from '@kbn/search-connectors-plugin/public';
|
||||
import type {
|
||||
SearchHomepagePluginSetup,
|
||||
SearchHomepagePluginStart,
|
||||
} from '@kbn/search-homepage/public';
|
||||
import { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public';
|
||||
import { SearchPlaygroundPluginStart } from '@kbn/search-playground/public';
|
||||
import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/public';
|
||||
|
@ -67,6 +71,7 @@ import {
|
|||
|
||||
import { INFERENCE_ENDPOINTS_PATH } from './applications/enterprise_search_relevance/routes';
|
||||
import { docLinks } from './applications/shared/doc_links';
|
||||
import { setBreadcrumbHomeUrl } from './applications/shared/kibana_chrome/breadcrumbs_home';
|
||||
import type { DynamicSideNavItems } from './navigation_tree';
|
||||
|
||||
export interface ClientData extends InitialAppData {
|
||||
|
@ -80,6 +85,7 @@ export type EnterpriseSearchPublicStart = ReturnType<EnterpriseSearchPlugin['sta
|
|||
interface PluginsSetup {
|
||||
cloud?: CloudSetup;
|
||||
home?: HomePublicPluginSetup;
|
||||
searchHomepage?: SearchHomepagePluginSetup;
|
||||
security?: SecurityPluginSetup;
|
||||
share?: SharePluginSetup;
|
||||
}
|
||||
|
@ -96,6 +102,7 @@ export interface PluginsStart {
|
|||
ml?: MlPluginStart;
|
||||
navigation: NavigationPublicPluginStart;
|
||||
searchConnectors?: SearchConnectorsPluginStart;
|
||||
searchHomepage?: SearchHomepagePluginStart;
|
||||
searchPlayground?: SearchPlaygroundPluginStart;
|
||||
searchInferenceEndpoints?: SearchInferenceEndpointsPluginStart;
|
||||
security?: SecurityPluginStart;
|
||||
|
@ -255,30 +262,56 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
return;
|
||||
}
|
||||
const { cloud, share } = plugins;
|
||||
const useSearchHomepage =
|
||||
plugins.searchHomepage && plugins.searchHomepage.isHomepageFeatureEnabled();
|
||||
|
||||
core.application.register({
|
||||
appRoute: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL,
|
||||
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
|
||||
euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO,
|
||||
id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID,
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const kibanaDeps = await this.getKibanaDeps(core, params, cloud);
|
||||
const { chrome, http } = kibanaDeps.core;
|
||||
chrome.docTitle.change(ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME);
|
||||
if (useSearchHomepage) {
|
||||
const { app } = plugins.searchHomepage!;
|
||||
core.application.register({
|
||||
...app,
|
||||
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
|
||||
euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO,
|
||||
visibleIn: ['home', 'kibanaOverview', 'globalSearch', 'sideNav'],
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const kibanaDeps = await this.getKibanaDeps(core, params, cloud);
|
||||
const { chrome, http } = kibanaDeps.core;
|
||||
chrome.docTitle.change(app.title);
|
||||
|
||||
await this.getInitialData(http);
|
||||
const pluginData = this.getPluginData();
|
||||
await this.getInitialData(http);
|
||||
const pluginData = this.getPluginData();
|
||||
|
||||
const { renderApp } = await import('./applications');
|
||||
const { EnterpriseSearchOverview } = await import(
|
||||
'./applications/enterprise_search_overview'
|
||||
);
|
||||
const { renderApp } = await import('./applications');
|
||||
const { SearchHomepage } = await import('./applications/search_homepage');
|
||||
|
||||
return renderApp(EnterpriseSearchOverview, kibanaDeps, pluginData);
|
||||
},
|
||||
title: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAV_TITLE,
|
||||
visibleIn: ['home', 'kibanaOverview', 'globalSearch', 'sideNav'],
|
||||
});
|
||||
return renderApp(SearchHomepage, kibanaDeps, pluginData);
|
||||
},
|
||||
});
|
||||
setBreadcrumbHomeUrl(app.appRoute);
|
||||
} else {
|
||||
core.application.register({
|
||||
appRoute: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL,
|
||||
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
|
||||
euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO,
|
||||
id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID,
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const kibanaDeps = await this.getKibanaDeps(core, params, cloud);
|
||||
const { chrome, http } = kibanaDeps.core;
|
||||
chrome.docTitle.change(ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME);
|
||||
|
||||
await this.getInitialData(http);
|
||||
const pluginData = this.getPluginData();
|
||||
|
||||
const { renderApp } = await import('./applications');
|
||||
const { EnterpriseSearchOverview } = await import(
|
||||
'./applications/enterprise_search_overview'
|
||||
);
|
||||
|
||||
return renderApp(EnterpriseSearchOverview, kibanaDeps, pluginData);
|
||||
},
|
||||
title: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAV_TITLE,
|
||||
visibleIn: ['home', 'kibanaOverview', 'globalSearch', 'sideNav'],
|
||||
});
|
||||
}
|
||||
|
||||
core.application.register({
|
||||
appRoute: ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL,
|
||||
|
@ -512,14 +545,27 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
}
|
||||
|
||||
if (plugins.home) {
|
||||
plugins.home.featureCatalogue.registerSolution({
|
||||
description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION,
|
||||
icon: 'logoEnterpriseSearch',
|
||||
id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID,
|
||||
order: 100,
|
||||
path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL,
|
||||
title: SEARCH_PRODUCT_NAME,
|
||||
});
|
||||
if (useSearchHomepage) {
|
||||
const { searchHomepage } = plugins;
|
||||
|
||||
plugins.home.featureCatalogue.registerSolution({
|
||||
description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION,
|
||||
icon: 'logoEnterpriseSearch',
|
||||
id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID,
|
||||
order: 100,
|
||||
path: searchHomepage!.app.appRoute,
|
||||
title: SEARCH_PRODUCT_NAME,
|
||||
});
|
||||
} else {
|
||||
plugins.home.featureCatalogue.registerSolution({
|
||||
description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION,
|
||||
icon: 'logoEnterpriseSearch',
|
||||
id: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID,
|
||||
order: 100,
|
||||
path: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL,
|
||||
title: SEARCH_PRODUCT_NAME,
|
||||
});
|
||||
}
|
||||
|
||||
plugins.home.featureCatalogue.register({
|
||||
category: 'data',
|
||||
|
@ -587,7 +633,10 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
|
||||
import('./navigation_tree').then(({ getNavigationTreeDefinition }) => {
|
||||
return plugins.navigation.addSolutionNavigation(
|
||||
getNavigationTreeDefinition({ dynamicItems$: this.sideNavDynamicItems$ })
|
||||
getNavigationTreeDefinition({
|
||||
dynamicItems$: this.sideNavDynamicItems$,
|
||||
isSearchHomepageEnabled: plugins.searchHomepage?.isHomepageFeatureEnabled() ?? false,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
"@kbn/cloud",
|
||||
"@kbn/try-in-console",
|
||||
"@kbn/core-chrome-browser",
|
||||
"@kbn/navigation-plugin"
|
||||
"@kbn/navigation-plugin",
|
||||
"@kbn/search-homepage"
|
||||
]
|
||||
}
|
||||
|
|
3
x-pack/plugins/search_homepage/README.mdx
Normal file
3
x-pack/plugins/search_homepage/README.mdx
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Search Homepage
|
||||
|
||||
The Search Homepage is a shared homepage for elasticsearch users.
|
14
x-pack/plugins/search_homepage/common/index.ts
Normal file
14
x-pack/plugins/search_homepage/common/index.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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 PLUGIN_ID = 'searchHomepage';
|
||||
export const PLUGIN_NAME = 'searchHomepage';
|
||||
|
||||
/**
|
||||
* UI Setting id for the Search Homepage feature flag
|
||||
*/
|
||||
export const HOMEPAGE_FEATURE_FLAG_ID = 'searchHomepage:homepageEnabled';
|
15
x-pack/plugins/search_homepage/jest.config.js
Normal file
15
x-pack/plugins/search_homepage/jest.config.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../..',
|
||||
roots: ['<rootDir>/x-pack/plugins/search_homepage'],
|
||||
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/x-pack/plugins/search_homepage',
|
||||
coverageReporters: ['text', 'html'],
|
||||
collectCoverageFrom: ['<rootDir>/x-pack/plugins/search_homepage/{public,server}/**/*.{ts,tsx}'],
|
||||
};
|
26
x-pack/plugins/search_homepage/kibana.jsonc
Normal file
26
x-pack/plugins/search_homepage/kibana.jsonc
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"type": "plugin",
|
||||
"id": "@kbn/search-homepage",
|
||||
"owner": "@elastic/search-kibana",
|
||||
"plugin": {
|
||||
"id": "searchHomepage",
|
||||
"server": true,
|
||||
"browser": true,
|
||||
"configPath": [
|
||||
"xpack",
|
||||
"search",
|
||||
"homepage"
|
||||
],
|
||||
"requiredPlugins": [
|
||||
"share",
|
||||
],
|
||||
"optionalPlugins": [
|
||||
"cloud",
|
||||
"console",
|
||||
"usageCollection",
|
||||
],
|
||||
"requiredBundles": [
|
||||
"kibanaReact"
|
||||
]
|
||||
}
|
||||
}
|
37
x-pack/plugins/search_homepage/public/application.tsx
Normal file
37
x-pack/plugins/search_homepage/public/application.tsx
Normal file
|
@ -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 React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import { Router } from '@kbn/shared-ux-router';
|
||||
import { SearchHomepageAppPluginStartDependencies } from './types';
|
||||
import { HomepageRouter } from './router';
|
||||
|
||||
export const renderApp = async (
|
||||
core: CoreStart,
|
||||
services: SearchHomepageAppPluginStartDependencies,
|
||||
element: HTMLElement
|
||||
) => {
|
||||
ReactDOM.render(
|
||||
<KibanaRenderContextProvider {...core}>
|
||||
<KibanaContextProvider services={{ ...core, ...services }}>
|
||||
<I18nProvider>
|
||||
<Router history={services.history}>
|
||||
<HomepageRouter />
|
||||
</Router>
|
||||
</I18nProvider>
|
||||
</KibanaContextProvider>
|
||||
</KibanaRenderContextProvider>,
|
||||
element
|
||||
);
|
||||
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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, { useMemo } from 'react';
|
||||
import { EuiPageTemplate } from '@elastic/eui';
|
||||
|
||||
import { useKibana } from '../hooks/use_kibana';
|
||||
import { SearchHomepageBody } from './search_homepage_body';
|
||||
import { SearchHomepageHeader } from './search_homepage_header';
|
||||
|
||||
export const SearchHomepagePage = () => {
|
||||
const {
|
||||
services: { console: consolePlugin },
|
||||
} = useKibana();
|
||||
|
||||
const embeddableConsole = useMemo(
|
||||
() => (consolePlugin?.EmbeddableConsole ? <consolePlugin.EmbeddableConsole /> : null),
|
||||
[consolePlugin]
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiPageTemplate offset={0} restrictWidth={false} data-test-subj="search-homepage" grow={false}>
|
||||
<SearchHomepageHeader />
|
||||
<SearchHomepageBody />
|
||||
{embeddableConsole}
|
||||
</EuiPageTemplate>
|
||||
);
|
||||
};
|
|
@ -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 React from 'react';
|
||||
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
|
||||
|
||||
export const SearchHomepageBody = () => (
|
||||
<KibanaPageTemplate.Section
|
||||
alignment="top"
|
||||
restrictWidth={false}
|
||||
grow
|
||||
css={{
|
||||
position: 'relative',
|
||||
}}
|
||||
contentProps={{ css: { display: 'flex', flexGrow: 1, position: 'absolute', inset: 0 } }}
|
||||
paddingSize="none"
|
||||
className="eui-fullHeight"
|
||||
>
|
||||
<div />
|
||||
</KibanaPageTemplate.Section>
|
||||
);
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 { EuiPageTemplate, EuiTitle } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
export const SearchHomepageHeader = () => (
|
||||
<EuiPageTemplate.Header
|
||||
pageTitle={
|
||||
<EuiTitle data-test-subj="search-homepage-header-title">
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="xpack.searchHomepage.pageTitle"
|
||||
defaultMessage="Welcome to Search"
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
}
|
||||
data-test-subj="search-homepage-header"
|
||||
rightSideItems={[]}
|
||||
/>
|
||||
);
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { SearchHomepageBody } from './search_homepage_body';
|
||||
import { SearchHomepageHeader } from './search_homepage_header';
|
||||
|
||||
export const App: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<SearchHomepageHeader />
|
||||
<SearchHomepageBody />
|
||||
</>
|
||||
);
|
||||
};
|
12
x-pack/plugins/search_homepage/public/embeddable.tsx
Normal file
12
x-pack/plugins/search_homepage/public/embeddable.tsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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 { dynamic } from '@kbn/shared-ux-utility';
|
||||
|
||||
export const SearchHomepage = dynamic(async () => ({
|
||||
default: (await import('./components/stack_app')).App,
|
||||
}));
|
13
x-pack/plugins/search_homepage/public/feature_flags.ts
Normal file
13
x-pack/plugins/search_homepage/public/feature_flags.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 { IUiSettingsClient } from '@kbn/core/public';
|
||||
import { HOMEPAGE_FEATURE_FLAG_ID } from '../common';
|
||||
|
||||
export function isHomepageEnabled(uiSettings: IUiSettingsClient): boolean {
|
||||
return uiSettings.get<boolean>(HOMEPAGE_FEATURE_FLAG_ID, false);
|
||||
}
|
11
x-pack/plugins/search_homepage/public/hooks/use_kibana.ts
Normal file
11
x-pack/plugins/search_homepage/public/hooks/use_kibana.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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 { useKibana as _useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { SearchHomepageServicesContext } from '../types';
|
||||
|
||||
export const useKibana = () => _useKibana<SearchHomepageServicesContext>();
|
20
x-pack/plugins/search_homepage/public/index.ts
Normal file
20
x-pack/plugins/search_homepage/public/index.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 { PluginInitializerContext } from '@kbn/core/public';
|
||||
|
||||
import { SearchHomepagePlugin } from './plugin';
|
||||
|
||||
export function plugin(initializerContext: PluginInitializerContext) {
|
||||
return new SearchHomepagePlugin(initializerContext);
|
||||
}
|
||||
|
||||
export type {
|
||||
SearchHomepagePluginSetup,
|
||||
SearchHomepagePluginStart,
|
||||
SearchHomepageAppInfo,
|
||||
} from './types';
|
80
x-pack/plugins/search_homepage/public/plugin.ts
Normal file
80
x-pack/plugins/search_homepage/public/plugin.ts
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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 {
|
||||
CoreSetup,
|
||||
Plugin,
|
||||
CoreStart,
|
||||
AppMountParameters,
|
||||
PluginInitializerContext,
|
||||
} from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { PLUGIN_ID } from '../common';
|
||||
|
||||
import { SearchHomepage } from './embeddable';
|
||||
import { isHomepageEnabled } from './feature_flags';
|
||||
import {
|
||||
SearchHomepageConfigType,
|
||||
SearchHomepagePluginSetup,
|
||||
SearchHomepagePluginStart,
|
||||
SearchHomepageAppPluginStartDependencies,
|
||||
SearchHomepageAppInfo,
|
||||
} from './types';
|
||||
|
||||
const appInfo: SearchHomepageAppInfo = {
|
||||
id: PLUGIN_ID,
|
||||
appRoute: '/app/elasticsearch/home',
|
||||
title: i18n.translate('xpack.searchHomepage.appTitle', { defaultMessage: 'Home' }),
|
||||
};
|
||||
|
||||
export class SearchHomepagePlugin
|
||||
implements Plugin<SearchHomepagePluginSetup, SearchHomepagePluginStart, {}, {}>
|
||||
{
|
||||
private readonly config: SearchHomepageConfigType;
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.config = initializerContext.config.get<SearchHomepageConfigType>();
|
||||
}
|
||||
|
||||
public setup(
|
||||
core: CoreSetup<SearchHomepageAppPluginStartDependencies, SearchHomepagePluginStart>
|
||||
) {
|
||||
const result: SearchHomepagePluginSetup = {
|
||||
app: appInfo,
|
||||
isHomepageFeatureEnabled() {
|
||||
return isHomepageEnabled(core.uiSettings);
|
||||
},
|
||||
};
|
||||
if (!this.config.ui?.enabled) return result;
|
||||
if (!isHomepageEnabled(core.uiSettings)) return result;
|
||||
|
||||
core.application.register({
|
||||
...result.app,
|
||||
async mount({ element, history }: AppMountParameters) {
|
||||
const { renderApp } = await import('./application');
|
||||
const [coreStart, depsStart] = await core.getStartServices();
|
||||
const startDeps: SearchHomepageAppPluginStartDependencies = {
|
||||
...depsStart,
|
||||
history,
|
||||
};
|
||||
|
||||
return renderApp(coreStart, startDeps, element);
|
||||
},
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
return {
|
||||
app: appInfo,
|
||||
isHomepageFeatureEnabled() {
|
||||
return isHomepageEnabled(core.uiSettings);
|
||||
},
|
||||
SearchHomepage,
|
||||
};
|
||||
}
|
||||
}
|
19
x-pack/plugins/search_homepage/public/router.tsx
Normal file
19
x-pack/plugins/search_homepage/public/router.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { Route, Routes } from '@kbn/shared-ux-router';
|
||||
|
||||
import { SearchHomepagePage } from './components/search_homepage';
|
||||
|
||||
export const HomepageRouter = () => (
|
||||
<Routes>
|
||||
<Route>
|
||||
<SearchHomepagePage />
|
||||
</Route>
|
||||
</Routes>
|
||||
);
|
74
x-pack/plugins/search_homepage/public/types.ts
Normal file
74
x-pack/plugins/search_homepage/public/types.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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 { ComponentProps, FC } from 'react';
|
||||
import type { CloudSetup } from '@kbn/cloud-plugin/public';
|
||||
import type { ConsolePluginStart } from '@kbn/console-plugin/public';
|
||||
import type { AppMountParameters, HttpStart } from '@kbn/core/public';
|
||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import type { App } from './components/stack_app';
|
||||
|
||||
export interface SearchHomepageConfigType {
|
||||
ui: {
|
||||
enabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SearchHomepageAppInfo {
|
||||
appRoute: string;
|
||||
id: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface SearchHomepagePluginSetup {
|
||||
/**
|
||||
* Search Homepage shared information for the Kibana application.
|
||||
* Used to ensure the stack and serverless apps have the same route
|
||||
* and deep links.
|
||||
*/
|
||||
app: SearchHomepageAppInfo;
|
||||
/**
|
||||
* Checks if the Search Homepage feature flag is currently enabled.
|
||||
* @returns true if Search Homepage feature is enabled
|
||||
*/
|
||||
isHomepageFeatureEnabled: () => boolean;
|
||||
}
|
||||
|
||||
export interface SearchHomepagePluginStart {
|
||||
/**
|
||||
* Search Homepage shared information for the Kibana application.
|
||||
* Used to ensure the stack and serverless apps have the same route
|
||||
* and deep links.
|
||||
*/
|
||||
app: SearchHomepageAppInfo;
|
||||
/**
|
||||
* Checks if the Search Homepage feature flag is currently enabled.
|
||||
* @returns true if Search Homepage feature is enabled
|
||||
*/
|
||||
isHomepageFeatureEnabled: () => boolean;
|
||||
/**
|
||||
* SearchHomepage shared component, used to render the search homepage in
|
||||
* the Stack search plugin
|
||||
*/
|
||||
SearchHomepage: FC<ComponentProps<typeof App>>;
|
||||
}
|
||||
|
||||
export interface SearchHomepageAppPluginStartDependencies {
|
||||
history: AppMountParameters['history'];
|
||||
usageCollection?: UsageCollectionStart;
|
||||
share: SharePluginStart;
|
||||
console?: ConsolePluginStart;
|
||||
}
|
||||
|
||||
export interface SearchHomepageServicesContext {
|
||||
http: HttpStart;
|
||||
share: SharePluginStart;
|
||||
cloud?: CloudSetup;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
console?: ConsolePluginStart;
|
||||
}
|
27
x-pack/plugins/search_homepage/server/config.ts
Normal file
27
x-pack/plugins/search_homepage/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 SearchHomepageConfig = TypeOf<typeof configSchema>;
|
||||
|
||||
export const config: PluginConfigDescriptor<SearchHomepageConfig> = {
|
||||
exposeToBrowser: {
|
||||
ui: true,
|
||||
},
|
||||
schema: configSchema,
|
||||
};
|
17
x-pack/plugins/search_homepage/server/index.ts
Normal file
17
x-pack/plugins/search_homepage/server/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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 { PluginInitializerContext } from '@kbn/core/server';
|
||||
|
||||
export { config } from './config';
|
||||
|
||||
export async function plugin(initializerContext: PluginInitializerContext) {
|
||||
const { SearchHomepagePlugin } = await import('./plugin');
|
||||
return new SearchHomepagePlugin(initializerContext);
|
||||
}
|
||||
|
||||
export type { SearchHomepagePluginSetup, SearchHomepagePluginStart } from './types';
|
28
x-pack/plugins/search_homepage/server/plugin.ts
Normal file
28
x-pack/plugins/search_homepage/server/plugin.ts
Normal file
|
@ -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 { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server';
|
||||
|
||||
import { SearchHomepagePluginSetup, SearchHomepagePluginStart } from './types';
|
||||
|
||||
export class SearchHomepagePlugin
|
||||
implements Plugin<SearchHomepagePluginSetup, SearchHomepagePluginStart, {}, {}>
|
||||
{
|
||||
private readonly logger: Logger;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.logger = initializerContext.logger.get();
|
||||
}
|
||||
|
||||
public setup(core: CoreSetup<{}, SearchHomepagePluginStart>) {
|
||||
this.logger.debug('searchHomepage: Setup');
|
||||
return {};
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
return {};
|
||||
}
|
||||
}
|
11
x-pack/plugins/search_homepage/server/types.ts
Normal file
11
x-pack/plugins/search_homepage/server/types.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface SearchHomepagePluginSetup {}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface SearchHomepagePluginStart {}
|
30
x-pack/plugins/search_homepage/tsconfig.json
Normal file
30
x-pack/plugins/search_homepage/tsconfig.json
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types",
|
||||
},
|
||||
"include": [
|
||||
"__mocks__/**/*",
|
||||
"common/**/*",
|
||||
"public/**/*",
|
||||
"server/**/*",
|
||||
],
|
||||
"kbn_references": [
|
||||
"@kbn/core",
|
||||
"@kbn/react-kibana-context-render",
|
||||
"@kbn/kibana-react-plugin",
|
||||
"@kbn/i18n-react",
|
||||
"@kbn/shared-ux-router",
|
||||
"@kbn/shared-ux-page-kibana-template",
|
||||
"@kbn/shared-ux-utility",
|
||||
"@kbn/i18n",
|
||||
"@kbn/cloud-plugin",
|
||||
"@kbn/console-plugin",
|
||||
"@kbn/share-plugin",
|
||||
"@kbn/usage-collection-plugin",
|
||||
"@kbn/config-schema",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
]
|
||||
}
|
|
@ -29,6 +29,7 @@
|
|||
"optionalPlugins": [
|
||||
"indexManagement",
|
||||
"searchConnectors",
|
||||
"searchHomepage",
|
||||
"searchInferenceEndpoints",
|
||||
"usageCollection"
|
||||
],
|
||||
|
|
|
@ -9,7 +9,7 @@ import type { NavigationTreeDefinition } from '@kbn/core-chrome-browser';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { CONNECTORS_LABEL } from '../common/i18n_string';
|
||||
|
||||
export const navigationTree: NavigationTreeDefinition = {
|
||||
export const navigationTree = (useSearchHomepage: boolean = false): NavigationTreeDefinition => ({
|
||||
body: [
|
||||
{
|
||||
type: 'navGroup',
|
||||
|
@ -25,7 +25,7 @@ export const navigationTree: NavigationTreeDefinition = {
|
|||
title: i18n.translate('xpack.serverlessSearch.nav.home', {
|
||||
defaultMessage: 'Home',
|
||||
}),
|
||||
link: 'serverlessElasticsearch',
|
||||
link: useSearchHomepage ? 'searchHomepage' : 'serverlessElasticsearch',
|
||||
spaceBefore: 'm',
|
||||
},
|
||||
{
|
||||
|
@ -149,4 +149,4 @@ export const navigationTree: NavigationTreeDefinition = {
|
|||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
|
|
@ -43,6 +43,9 @@ export class ServerlessSearchPlugin
|
|||
core: CoreSetup<ServerlessSearchPluginStartDependencies, ServerlessSearchPluginStart>,
|
||||
setupDeps: ServerlessSearchPluginSetupDependencies
|
||||
): ServerlessSearchPluginSetup {
|
||||
const { searchHomepage } = setupDeps;
|
||||
const useSearchHomepage = searchHomepage && searchHomepage.isHomepageFeatureEnabled();
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
mutationCache: new MutationCache({
|
||||
onError: (error) => {
|
||||
|
@ -69,6 +72,24 @@ export class ServerlessSearchPlugin
|
|||
},
|
||||
}),
|
||||
});
|
||||
if (useSearchHomepage) {
|
||||
core.application.register({
|
||||
id: 'serverlessHomeRedirect',
|
||||
title: i18n.translate('xpack.serverlessSearch.app.home.title', {
|
||||
defaultMessage: 'Home',
|
||||
}),
|
||||
appRoute: '/app/elasticsearch',
|
||||
euiIconType: 'logoElastic',
|
||||
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
|
||||
visibleIn: [],
|
||||
async mount({}: AppMountParameters) {
|
||||
const [coreStart] = await core.getStartServices();
|
||||
coreStart.application.navigateToApp('searchHomepage');
|
||||
return () => {};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
core.application.register({
|
||||
id: 'serverlessElasticsearch',
|
||||
title: i18n.translate('xpack.serverlessSearch.app.elasticsearch.title', {
|
||||
|
@ -76,7 +97,7 @@ export class ServerlessSearchPlugin
|
|||
}),
|
||||
euiIconType: 'logoElastic',
|
||||
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
|
||||
appRoute: '/app/elasticsearch',
|
||||
appRoute: useSearchHomepage ? '/app/elasticsearch/getting_started' : '/app/elasticsearch',
|
||||
async mount({ element, history }: AppMountParameters) {
|
||||
const { renderApp } = await import('./application/elasticsearch');
|
||||
const [coreStart, services] = await core.getStartServices();
|
||||
|
@ -121,10 +142,12 @@ export class ServerlessSearchPlugin
|
|||
core: CoreStart,
|
||||
services: ServerlessSearchPluginStartDependencies
|
||||
): ServerlessSearchPluginStart {
|
||||
const { serverless, management, indexManagement, security } = services;
|
||||
serverless.setProjectHome('/app/elasticsearch');
|
||||
const { serverless, management, indexManagement, security, searchHomepage } = services;
|
||||
const useSearchHomepage = searchHomepage && searchHomepage.isHomepageFeatureEnabled();
|
||||
|
||||
const navigationTree$ = of(navigationTree);
|
||||
serverless.setProjectHome(useSearchHomepage ? '/app/elasticsearch/home' : '/app/elasticsearch');
|
||||
|
||||
const navigationTree$ = of(navigationTree(searchHomepage?.isHomepageFeatureEnabled() ?? false));
|
||||
serverless.initNavigation('search', navigationTree$, { dataTestSubj: 'svlSearchSideNav' });
|
||||
|
||||
const extendCardNavDefinitions = serverless.getNavigationCards(
|
||||
|
|
|
@ -5,16 +5,20 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public';
|
||||
import { ConsolePluginStart } from '@kbn/console-plugin/public';
|
||||
import { SearchPlaygroundPluginStart } from '@kbn/search-playground/public';
|
||||
import { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public';
|
||||
import { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public';
|
||||
import { SecurityPluginStart } from '@kbn/security-plugin/public';
|
||||
import { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public';
|
||||
import { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import { IndexManagementPluginStart } from '@kbn/index-management-plugin/public';
|
||||
import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public';
|
||||
import type { ConsolePluginStart } from '@kbn/console-plugin/public';
|
||||
import type { SearchInferenceEndpointsPluginStart } from '@kbn/search-inference-endpoints/public';
|
||||
import type { SearchPlaygroundPluginStart } from '@kbn/search-playground/public';
|
||||
import type { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public';
|
||||
import type { SecurityPluginStart } from '@kbn/security-plugin/public';
|
||||
import type { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public';
|
||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { IndexManagementPluginStart } from '@kbn/index-management-plugin/public';
|
||||
import type { DiscoverSetup } from '@kbn/discover-plugin/public';
|
||||
import type {
|
||||
SearchHomepagePluginSetup,
|
||||
SearchHomepagePluginStart,
|
||||
} from '@kbn/search-homepage/public';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface ServerlessSearchPluginSetup {}
|
||||
|
@ -27,6 +31,7 @@ export interface ServerlessSearchPluginSetupDependencies {
|
|||
management: ManagementSetup;
|
||||
serverless: ServerlessPluginSetup;
|
||||
discover: DiscoverSetup;
|
||||
searchHomepage?: SearchHomepagePluginSetup;
|
||||
}
|
||||
|
||||
export interface ServerlessSearchPluginStartDependencies {
|
||||
|
@ -39,4 +44,5 @@ export interface ServerlessSearchPluginStartDependencies {
|
|||
serverless: ServerlessPluginStart;
|
||||
share: SharePluginStart;
|
||||
indexManagement?: IndexManagementPluginStart;
|
||||
searchHomepage?: SearchHomepagePluginStart;
|
||||
}
|
||||
|
|
|
@ -50,5 +50,6 @@
|
|||
"@kbn/react-kibana-context-render",
|
||||
"@kbn/search-playground",
|
||||
"@kbn/search-inference-endpoints",
|
||||
"@kbn/search-homepage",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import { SvlRuleDetailsPageProvider } from './svl_rule_details_ui_page';
|
|||
import { SvlSearchConnectorsPageProvider } from './svl_search_connectors_page';
|
||||
import { SvlManagementPageProvider } from './svl_management_page';
|
||||
import { SvlIngestPipelines } from './svl_ingest_pipelines';
|
||||
import { SvlSearchHomePageProvider } from './svl_search_homepage';
|
||||
|
||||
export const pageObjects = {
|
||||
...xpackFunctionalPageObjects,
|
||||
|
@ -38,4 +39,5 @@ export const pageObjects = {
|
|||
svlRuleDetailsUI: SvlRuleDetailsPageProvider,
|
||||
svlManagementPage: SvlManagementPageProvider,
|
||||
svlIngestPipelines: SvlIngestPipelines,
|
||||
svlSearchHomePage: SvlSearchHomePageProvider,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export function SvlSearchHomePageProvider({ getService }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const browser = getService('browser');
|
||||
|
||||
return {
|
||||
async expectToBeOnHomepage() {
|
||||
expect(await browser.getCurrentUrl()).contain('/app/elasticsearch/home');
|
||||
},
|
||||
async expectToNotBeOnHomepage() {
|
||||
expect(await browser.getCurrentUrl()).not.contain('/app/elasticsearch/home');
|
||||
},
|
||||
async expectHomepageHeader() {
|
||||
await testSubjects.existOrFail('search-homepage-header', { timeout: 2000 });
|
||||
},
|
||||
};
|
||||
}
|
|
@ -16,6 +16,7 @@ import { SvlCommonScreenshotsProvider } from './svl_common_screenshots';
|
|||
import { SvlCasesServiceProvider } from '../../api_integration/services/svl_cases';
|
||||
import { MachineLearningProvider } from './ml';
|
||||
import { LogsSynthtraceProvider } from './log';
|
||||
import { UISettingsServiceProvider } from './ui_settings';
|
||||
|
||||
export const services = {
|
||||
// deployment agnostic FTR services
|
||||
|
@ -30,6 +31,7 @@ export const services = {
|
|||
svlCommonScreenshots: SvlCommonScreenshotsProvider,
|
||||
svlCases: SvlCasesServiceProvider,
|
||||
svlMl: MachineLearningProvider,
|
||||
uiSettings: UISettingsServiceProvider,
|
||||
// log services
|
||||
svlLogsSynthtraceClient: LogsSynthtraceProvider,
|
||||
};
|
||||
|
|
32
x-pack/test_serverless/functional/services/ui_settings.ts
Normal file
32
x-pack/test_serverless/functional/services/ui_settings.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from '../ftr_provider_context';
|
||||
import { RoleCredentials } from '../../shared/services';
|
||||
|
||||
export function UISettingsServiceProvider({ getService }: FtrProviderContext) {
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
|
||||
return {
|
||||
async setUiSetting(role: RoleCredentials, settingId: string, value: unknown) {
|
||||
await supertestWithoutAuth
|
||||
.post(`/internal/kibana/settings/${settingId}`)
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.set(role.apiKeyHeader)
|
||||
.send({ value })
|
||||
.expect(200);
|
||||
},
|
||||
async deleteUISetting(role: RoleCredentials, settingId: string) {
|
||||
await supertestWithoutAuth
|
||||
.delete(`/internal/kibana/settings/${settingId}`)
|
||||
.set(svlCommonApi.getInternalRequestHeader())
|
||||
.set(role.apiKeyHeader)
|
||||
.expect(200);
|
||||
},
|
||||
};
|
||||
}
|
|
@ -23,5 +23,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
|||
loadTestFile(require.resolve('./playground_overview'));
|
||||
|
||||
loadTestFile(require.resolve('./ml'));
|
||||
loadTestFile(require.resolve('./search_homepage'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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 { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { RoleCredentials } from '../../../shared/services';
|
||||
|
||||
import { testHasEmbeddedConsole } from './embedded_console';
|
||||
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
const pageObjects = getPageObjects(['svlCommonPage', 'svlCommonNavigation', 'svlSearchHomePage']);
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const uiSettings = getService('uiSettings');
|
||||
let roleAuthc: RoleCredentials;
|
||||
|
||||
const HOMEPAGE_FF_UI_SETTING = 'searchHomepage:homepageEnabled';
|
||||
describe('Search Homepage', function () {
|
||||
this.tags('skipMKI');
|
||||
before(async () => {
|
||||
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
|
||||
// Enable Homepage Feature Flag
|
||||
await uiSettings.setUiSetting(roleAuthc, HOMEPAGE_FF_UI_SETTING, true);
|
||||
|
||||
await pageObjects.svlCommonPage.login();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
if (!roleAuthc) return;
|
||||
|
||||
// Disable Homepage Feature Flag
|
||||
await uiSettings.deleteUISetting(roleAuthc, HOMEPAGE_FF_UI_SETTING);
|
||||
|
||||
await pageObjects.svlCommonPage.forceLogout();
|
||||
});
|
||||
|
||||
it('has search homepage with Home sidenav', async () => {
|
||||
pageObjects.svlSearchHomePage.expectToBeOnHomepage();
|
||||
pageObjects.svlSearchHomePage.expectHomepageHeader();
|
||||
// Navigate to another page
|
||||
await pageObjects.svlCommonNavigation.sidenav.clickLink({
|
||||
deepLinkId: 'serverlessConnectors',
|
||||
});
|
||||
pageObjects.svlSearchHomePage.expectToNotBeOnHomepage();
|
||||
// Click Home in Side nav
|
||||
await pageObjects.svlCommonNavigation.sidenav.clickLink({
|
||||
deepLinkId: 'searchHomepage',
|
||||
});
|
||||
pageObjects.svlSearchHomePage.expectToBeOnHomepage();
|
||||
});
|
||||
|
||||
it('has embedded dev console', async () => {
|
||||
testHasEmbeddedConsole(pageObjects);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -6056,6 +6056,10 @@
|
|||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/search-homepage@link:x-pack/plugins/search_homepage":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/search-index-documents@link:packages/kbn-search-index-documents":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue