Skip to content

Commit

Permalink
[Search] Refactor: abstracting classic nav items (#196579)
Browse files Browse the repository at this point in the history
## Summary

Moved the base set of sidenav items from being statically defined in
useEnterpriseSearchNav to using a function that can be shared with the
plugin. Additionally wrapped this generation in a `useMemo` to improve
performance.

This will support the ability to share the classic navigation items for
Search to other plugins so that they can render their own UIs without
sharing components with enterprise_search just to have access to the
side nav defined by enterprise_search.

### Checklist

- [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
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed

---------

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
TattdCodeMonkey and elasticmachine authored Oct 30, 2024
1 parent b9a5d6a commit c4301d0
Show file tree
Hide file tree
Showing 37 changed files with 1,180 additions and 358 deletions.
4 changes: 4 additions & 0 deletions packages/deeplinks/search/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ export const SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID = 'searchInferenceEndpo
export const SEARCH_HOMEPAGE = 'searchHomepage';
export const SEARCH_INDICES_START = 'elasticsearchStart';
export const SEARCH_INDICES = 'elasticsearchIndices';
export const SEARCH_ELASTICSEARCH = 'enterpriseSearchElasticsearch';
export const SEARCH_VECTOR_SEARCH = 'enterpriseSearchVectorSearch';
export const SEARCH_SEMANTIC_SEARCH = 'enterpriseSearchSemanticSearch';
export const SEARCH_AI_SEARCH = 'enterpriseSearchAISearch';
14 changes: 13 additions & 1 deletion packages/deeplinks/search/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ import {
SEARCH_HOMEPAGE,
SEARCH_INDICES_START,
SEARCH_INDICES,
SEARCH_ELASTICSEARCH,
SEARCH_VECTOR_SEARCH,
SEARCH_SEMANTIC_SEARCH,
SEARCH_AI_SEARCH,
} from './constants';

export type EnterpriseSearchApp = typeof ENTERPRISE_SEARCH_APP_ID;
Expand All @@ -38,6 +42,10 @@ export type SearchInferenceEndpointsId = typeof SERVERLESS_ES_SEARCH_INFERENCE_E
export type SearchHomepage = typeof SEARCH_HOMEPAGE;
export type SearchStart = typeof SEARCH_INDICES_START;
export type SearchIndices = typeof SEARCH_INDICES;
export type SearchElasticsearch = typeof SEARCH_ELASTICSEARCH;
export type SearchVectorSearch = typeof SEARCH_VECTOR_SEARCH;
export type SearchSemanticSearch = typeof SEARCH_SEMANTIC_SEARCH;
export type SearchAISearch = typeof SEARCH_AI_SEARCH;

export type ContentLinkId = 'searchIndices' | 'connectors' | 'webCrawlers';

Expand Down Expand Up @@ -65,4 +73,8 @@ export type DeepLinkId =
| `${EnterpriseSearchAppsearchApp}:${AppsearchLinkId}`
| `${EnterpriseSearchRelevanceApp}:${RelevanceLinkId}`
| SearchStart
| SearchIndices;
| SearchIndices
| SearchElasticsearch
| SearchVectorSearch
| SearchSemanticSearch
| SearchAISearch;
4 changes: 4 additions & 0 deletions packages/deeplinks/search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export {
ENTERPRISE_SEARCH_WORKPLACESEARCH_APP_ID,
SERVERLESS_ES_APP_ID,
SERVERLESS_ES_CONNECTORS_ID,
SEARCH_ELASTICSEARCH,
SEARCH_VECTOR_SEARCH,
SEARCH_SEMANTIC_SEARCH,
SEARCH_AI_SEARCH,
} from './constants';

export type {
Expand Down
23 changes: 19 additions & 4 deletions x-pack/plugins/enterprise_search/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import {
ENTERPRISE_SEARCH_ANALYTICS_APP_ID,
ENTERPRISE_SEARCH_APPSEARCH_APP_ID,
ENTERPRISE_SEARCH_WORKPLACESEARCH_APP_ID,
SEARCH_ELASTICSEARCH,
SEARCH_VECTOR_SEARCH,
SEARCH_SEMANTIC_SEARCH,
SEARCH_AI_SEARCH,
} from '@kbn/deeplinks-search';
import { i18n } from '@kbn/i18n';

Expand Down Expand Up @@ -58,7 +62,7 @@ export const ENTERPRISE_SEARCH_CONTENT_PLUGIN = {
};

export const AI_SEARCH_PLUGIN = {
ID: 'enterpriseSearchAISearch',
ID: SEARCH_AI_SEARCH,
NAME: i18n.translate('xpack.enterpriseSearch.aiSearch.productName', {
defaultMessage: 'AI Search',
}),
Expand Down Expand Up @@ -91,7 +95,7 @@ export const ANALYTICS_PLUGIN = {
};

export const ELASTICSEARCH_PLUGIN = {
ID: 'enterpriseSearchElasticsearch',
ID: SEARCH_ELASTICSEARCH,
NAME: i18n.translate('xpack.enterpriseSearch.elasticsearch.productName', {
defaultMessage: 'Elasticsearch',
}),
Expand Down Expand Up @@ -167,7 +171,7 @@ export const VECTOR_SEARCH_PLUGIN = {
defaultMessage:
'Elasticsearch can be used as a vector database, which enables vector search and semantic search use cases.',
}),
ID: 'enterpriseSearchVectorSearch',
ID: SEARCH_VECTOR_SEARCH,
LOGO: 'logoEnterpriseSearch',
NAME: i18n.translate('xpack.enterpriseSearch.vectorSearch.productName', {
defaultMessage: 'Vector Search',
Expand All @@ -184,7 +188,7 @@ export const SEMANTIC_SEARCH_PLUGIN = {
defaultMessage:
'Easily add semantic search to Elasticsearch with inference endpoints and the semantic_text field type, to boost search relevance.',
}),
ID: 'enterpriseSearchSemanticSearch',
ID: SEARCH_SEMANTIC_SEARCH,
LOGO: 'logoEnterpriseSearch',
NAME: i18n.translate('xpack.enterpriseSearch.SemanticSearch.productName', {
defaultMessage: 'Semantic Search',
Expand Down Expand Up @@ -297,3 +301,14 @@ export const CRAWLER = {

// TODO remove this once the connector service types are no longer in "example" state
export const EXAMPLE_CONNECTOR_SERVICE_TYPES = ['opentext_documentum'];

export const GETTING_STARTED_TITLE = i18n.translate('xpack.enterpriseSearch.gettingStarted.title', {
defaultMessage: 'Getting started',
});

export const SEARCH_APPS_BREADCRUMB = i18n.translate(
'xpack.enterpriseSearch.searchApplications.breadcrumb',
{
defaultMessage: 'Search Applications',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const mockKibanaValues = {
data: dataPluginMock.createStartContract(),
esConfig: { elasticsearch_host: 'https://your_deployment_url' },
getChromeStyle$: jest.fn().mockReturnValue(of('classic')),
getNavLinks: jest.fn().mockReturnValue([]),
guidedOnboarding: {},
history: mockHistory,
indexMappingComponent: null,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React, { useLayoutEffect } from 'react';

import { useValues } from 'kea';

import useObservable from 'react-use/lib/useObservable';

import { SEARCH_PRODUCT_NAME } from '../../../../../common/constants';
import { KibanaLogic } from '../../../shared/kibana';
import { SetSearchPlaygroundChrome } from '../../../shared/kibana_chrome/set_chrome';
import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout';
import { useEnterpriseSearchNav } from '../../../shared/layout';
import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry';

import { PlaygroundHeaderDocsAction } from './header_docs_action';

export type SearchPlaygroundPageTemplateProps = Omit<
PageTemplateProps,
'useEndpointHeaderActions'
> & {
hasSchemaConflicts?: boolean;
restrictWidth?: boolean;
searchApplicationName?: string;
};

export const SearchPlaygroundPageTemplate: React.FC<SearchPlaygroundPageTemplateProps> = ({
children,
pageChrome,
pageViewTelemetry,
searchApplicationName,
hasSchemaConflicts,
restrictWidth = true,
...pageTemplateProps
}) => {
const navItems = useEnterpriseSearchNav();

const { renderHeaderActions, getChromeStyle$ } = useValues(KibanaLogic);
const chromeStyle = useObservable(getChromeStyle$(), 'classic');

useLayoutEffect(() => {
renderHeaderActions(PlaygroundHeaderDocsAction);

return () => {
renderHeaderActions();
};
}, []);

return (
<EnterpriseSearchPageTemplateWrapper
{...pageTemplateProps}
solutionNav={{
items: chromeStyle === 'classic' ? navItems : undefined,
name: SEARCH_PRODUCT_NAME,
}}
restrictWidth={restrictWidth}
setPageChrome={pageChrome && <SetSearchPlaygroundChrome trail={pageChrome} />}
useEndpointHeaderActions={false}
>
{pageViewTelemetry && (
<SendEnterpriseSearchTelemetry action="viewed" metric={pageViewTelemetry} />
)}
{children}
</EnterpriseSearchPageTemplateWrapper>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { useValues } from 'kea';
import { i18n } from '@kbn/i18n';

import { KibanaLogic } from '../../../shared/kibana';
import { EnterpriseSearchApplicationsPageTemplate } from '../layout/page_template';

import { SearchPlaygroundPageTemplate } from './page_template';

export const Playground: React.FC = () => {
const { searchPlayground } = useValues(KibanaLogic);
Expand All @@ -22,7 +23,7 @@ export const Playground: React.FC = () => {
}
return (
<searchPlayground.PlaygroundProvider>
<EnterpriseSearchApplicationsPageTemplate
<SearchPlaygroundPageTemplate
pageChrome={[
i18n.translate('xpack.enterpriseSearch.content.playground.breadcrumb', {
defaultMessage: 'Playground',
Expand All @@ -33,10 +34,9 @@ export const Playground: React.FC = () => {
panelled={false}
customPageSections
bottomBorder="extended"
docLink="playground"
>
<searchPlayground.Playground />
</EnterpriseSearchApplicationsPageTemplate>
</SearchPlaygroundPageTemplate>
</searchPlayground.PlaygroundProvider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const ElasticsearchGuide = () => {
}, []);

return (
<EnterpriseSearchElasticsearchPageTemplate>
<EnterpriseSearchElasticsearchPageTemplate pageChrome={[]}>
{isFlyoutOpen && <CreateApiKeyFlyout onClose={() => setIsFlyoutOpen(false)} />}
<EuiTitle size="l" data-test-subj="elasticsearchGuide">
<h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ export const EnterpriseSearchElasticsearchPageTemplate: React.FC<PageTemplatePro
pageViewTelemetry,
...pageTemplateProps
}) => {
const navItems = useEnterpriseSearchNav();
return (
<EnterpriseSearchPageTemplateWrapper
{...pageTemplateProps}
restrictWidth
solutionNav={{
name: SEARCH_PRODUCT_NAME,
items: useEnterpriseSearchNav(),
items: navItems,
}}
setPageChrome={pageChrome && <SetElasticsearchChrome trail={pageChrome} />}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export const renderApp = (
data: plugins.data,
esConfig,
getChromeStyle$: chrome.getChromeStyle$,
getNavLinks: chrome.navLinks.getAll,
guidedOnboarding,
history,
indexMappingComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export interface KibanaLogicProps {
data?: DataPublicPluginStart;
esConfig: ESConfig;
getChromeStyle$: ChromeStart['getChromeStyle$'];
getNavLinks: ChromeStart['navLinks']['getAll'];
guidedOnboarding?: GuidedOnboardingPluginStart;
history: ScopedHistory;
indexMappingComponent?: React.FC<IndexMappingProps>;
Expand Down Expand Up @@ -87,6 +88,7 @@ export interface KibanaValues {
data: DataPublicPluginStart | null;
esConfig: ESConfig;
getChromeStyle$: ChromeStart['getChromeStyle$'];
getNavLinks: ChromeStart['navLinks']['getAll'];
guidedOnboarding: GuidedOnboardingPluginStart | null;
history: ScopedHistory;
indexMappingComponent: React.FC<IndexMappingProps> | null;
Expand Down Expand Up @@ -126,6 +128,7 @@ export const KibanaLogic = kea<MakeLogicType<KibanaValues>>({
data: [props.data || null, {}],
esConfig: [props.esConfig || { elasticsearch_host: ELASTICSEARCH_URL_PLACEHOLDER }, {}],
getChromeStyle$: [props.getChromeStyle$, {}],
getNavLinks: [props.getNavLinks, {}],
guidedOnboarding: [props.guidedOnboarding || null, {}],
history: [props.history, {}],
indexMappingComponent: [props.indexMappingComponent || null, {}],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
VECTOR_SEARCH_PLUGIN,
WORKPLACE_SEARCH_PLUGIN,
SEMANTIC_SEARCH_PLUGIN,
APPLICATIONS_PLUGIN,
GETTING_STARTED_TITLE,
} from '../../../../common/constants';

import { stripLeadingSlash } from '../../../../common/strip_slashes';
Expand Down Expand Up @@ -126,7 +128,11 @@ export const useEnterpriseSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
]);

export const useAnalyticsBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
useSearchBreadcrumbs([{ text: ANALYTICS_PLUGIN.NAME, path: '/' }, ...breadcrumbs]);
useSearchBreadcrumbs([
{ text: APPLICATIONS_PLUGIN.NAV_TITLE },
{ text: ANALYTICS_PLUGIN.NAME, path: '/' },
...breadcrumbs,
]);

export const useElasticsearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
useSearchBreadcrumbs([
Expand Down Expand Up @@ -161,13 +167,25 @@ export const useSearchExperiencesBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =
useSearchBreadcrumbs([{ text: SEARCH_EXPERIENCES_PLUGIN.NAV_TITLE, path: '/' }, ...breadcrumbs]);

export const useEnterpriseSearchApplicationsBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
useSearchBreadcrumbs(breadcrumbs);
useSearchBreadcrumbs([{ text: APPLICATIONS_PLUGIN.NAV_TITLE }, ...breadcrumbs]);

export const useAiSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
useSearchBreadcrumbs([{ text: AI_SEARCH_PLUGIN.NAME, path: '/' }, ...breadcrumbs]);
useSearchBreadcrumbs([
{ text: GETTING_STARTED_TITLE },
{ text: AI_SEARCH_PLUGIN.NAME, path: '/' },
...breadcrumbs,
]);

export const useVectorSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
useSearchBreadcrumbs([{ text: VECTOR_SEARCH_PLUGIN.NAV_TITLE, path: '/' }, ...breadcrumbs]);
useSearchBreadcrumbs([
{ text: GETTING_STARTED_TITLE },
{ text: VECTOR_SEARCH_PLUGIN.NAV_TITLE, path: '/' },
...breadcrumbs,
]);

export const useSemanticSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
useSearchBreadcrumbs([{ text: SEMANTIC_SEARCH_PLUGIN.NAME, path: '/' }, ...breadcrumbs]);
useSearchBreadcrumbs([
{ text: GETTING_STARTED_TITLE },
{ text: SEMANTIC_SEARCH_PLUGIN.NAME, path: '/' },
...breadcrumbs,
]);
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* 2.0.
*/

import { i18n } from '@kbn/i18n';

import {
AI_SEARCH_PLUGIN,
ANALYTICS_PLUGIN,
Expand Down Expand Up @@ -40,7 +42,12 @@ export const searchTitle = (page: Title = []) => generateTitle([...page, SEARCH_
export const analyticsTitle = (page: Title = []) => generateTitle([...page, ANALYTICS_PLUGIN.NAME]);

export const elasticsearchTitle = (page: Title = []) =>
generateTitle([...page, 'Getting started with Elasticsearch']);
generateTitle([
...page,
i18n.translate('xpack.enterpriseSearch.titles.elasticsearch', {
defaultMessage: 'Getting started with Elasticsearch',
}),
]);

export const appSearchTitle = (page: Title = []) =>
generateTitle([...page, APP_SEARCH_PLUGIN.NAME]);
Expand All @@ -61,3 +68,11 @@ export const semanticSearchTitle = (page: Title = []) =>

export const enterpriseSearchContentTitle = (page: Title = []) =>
generateTitle([...page, ENTERPRISE_SEARCH_CONTENT_PLUGIN.NAME]);

export const searchApplicationsTitle = (page: Title = []) =>
generateTitle([
...page,
i18n.translate('xpack.enterpriseSearch.titles.searchApplications', {
defaultMessage: 'Search Applications',
}),
]);
Loading

0 comments on commit c4301d0

Please sign in to comment.