Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/deeplinks/search/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ 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';
export const SEARCH_INDICES_START = 'elasticsearchStart';
export const SEARCH_INDICES = 'elasticsearchIndices';
8 changes: 7 additions & 1 deletion packages/deeplinks/search/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import {
SERVERLESS_ES_SEARCH_PLAYGROUND_ID,
SERVERLESS_ES_SEARCH_INFERENCE_ENDPOINTS_ID,
SEARCH_HOMEPAGE,
SEARCH_INDICES_START,
SEARCH_INDICES,
} from './constants';

export type EnterpriseSearchApp = typeof ENTERPRISE_SEARCH_APP_ID;
Expand All @@ -34,6 +36,8 @@ 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 SearchStart = typeof SEARCH_INDICES_START;
export type SearchIndices = typeof SEARCH_INDICES;

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

Expand All @@ -59,4 +63,6 @@ export type DeepLinkId =
| `${EnterpriseSearchContentApp}:${ContentLinkId}`
| `${EnterpriseSearchApplicationsApp}:${ApplicationsLinkId}`
| `${EnterpriseSearchAppsearchApp}:${AppsearchLinkId}`
| `${EnterpriseSearchRelevanceApp}:${RelevanceLinkId}`;
| `${EnterpriseSearchRelevanceApp}:${RelevanceLinkId}`
| SearchStart
| SearchIndices;
4 changes: 4 additions & 0 deletions x-pack/plugins/search_indices/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
* 2.0.
*/

import type { SearchIndices, SearchStart } from '@kbn/deeplinks-search/deep_links';

export const PLUGIN_ID = 'searchIndices';
export const PLUGIN_NAME = 'searchIndices';
export const START_APP_ID: SearchStart = 'elasticsearchStart';
export const INDICES_APP_ID: SearchIndices = 'elasticsearchIndices';

export type { IndicesStatusResponse, UserStartPrivilegesResponse } from './types';
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,17 @@ export const CreateIndexForm = ({
const [indexNameHasError, setIndexNameHasError] = useState<boolean>(false);
const usageTracker = useUsageTracker();
const { createIndex, isLoading } = useCreateIndex();
const onCreateIndex = useCallback(() => {
if (!isValidIndexName(formState.indexName)) {
return;
}
usageTracker.click(AnalyticsEvents.startCreateIndexClick);
createIndex({ indexName: formState.indexName });
}, [usageTracker, createIndex, formState.indexName]);
const onCreateIndex = useCallback(
(e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!isValidIndexName(formState.indexName)) {
return;
}
usageTracker.click(AnalyticsEvents.startCreateIndexClick);
createIndex({ indexName: formState.indexName });
},
[usageTracker, createIndex, formState.indexName]
);
const onIndexNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newIndexName = e.target.value;
setFormState({ ...formState, indexName: e.target.value });
Expand All @@ -78,7 +82,12 @@ export const CreateIndexForm = ({

return (
<>
<EuiForm data-test-subj="createIndexUIView" fullWidth component="form">
<EuiForm
data-test-subj="createIndexUIView"
fullWidth
component="form"
onSubmit={onCreateIndex}
>
<EuiFormRow
label={i18n.translate('xpack.searchIndices.startPage.createIndex.name.label', {
defaultMessage: 'Name your index',
Expand Down Expand Up @@ -137,11 +146,9 @@ export const CreateIndexForm = ({
color="primary"
iconSide="left"
iconType="sparkles"
data-telemetry-id="searchIndices-start-createIndexBtn"
data-test-subj="createIndexBtn"
disabled={indexNameHasError || isLoading}
isLoading={isLoading}
onClick={onCreateIndex}
type="submit"
>
{CREATE_INDEX_CONTENT}
Expand Down Expand Up @@ -181,11 +188,7 @@ export const CreateIndexForm = ({
defaultMessage="Already have some data? {link}"
values={{
link: (
<EuiLink
data-telemetry-id="searchIndices-start-uploadFile"
data-test-subj="uploadFileLink"
onClick={onFileUpload}
>
<EuiLink data-test-subj="uploadFileLink" onClick={onFileUpload}>
{i18n.translate(
'xpack.searchIndices.startPage.createIndex.fileUpload.link',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ export const ElasticsearchStart = ({ userPrivileges }: ElasticsearchStartProps)
iconSide="right"
iconType="popout"
data-test-subj="analyzeLogsBtn"
data-telemetry-id="searchIndicesStartCollectLogsLink"
href={docLinks.analyzeLogs}
target="_blank"
>
Expand Down Expand Up @@ -249,7 +248,6 @@ export const ElasticsearchStart = ({ userPrivileges }: ElasticsearchStartProps)
iconSide="right"
iconType="popout"
data-test-subj="startO11yTrialBtn"
data-telemetry-id="searchIndicesStartO11yTrialLink"
href={o11yTrialLink}
target="_blank"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { useEffect } from 'react';
import { useEffect, useState } from 'react';

import type { IndicesStatusResponse } from '../../../../common';

Expand All @@ -15,13 +15,30 @@ import { navigateToIndexDetails } from './utils';

export const useIndicesRedirect = (indicesStatus?: IndicesStatusResponse) => {
const { application, http } = useKibana().services;
const [lastStatus, setLastStatus] = useState<IndicesStatusResponse | undefined>(() => undefined);
const [hasDoneRedirect, setHasDoneRedirect] = useState(() => false);
return useEffect(() => {
if (!indicesStatus) return;
if (indicesStatus.indexNames.length === 0) return;
if (hasDoneRedirect) {
return;
}
if (!indicesStatus) {
return;
}
if (indicesStatus.indexNames.length === 0) {
setLastStatus(indicesStatus);
return;
}
if (lastStatus === undefined && indicesStatus.indexNames.length > 0) {
application.navigateToApp('management', { deepLinkId: 'index_management' });
setHasDoneRedirect(true);
return;
}
if (indicesStatus.indexNames.length === 1) {
navigateToIndexDetails(application, http, indicesStatus.indexNames[0]);
setHasDoneRedirect(true);
return;
}
application.navigateToApp('management', { deepLinkId: 'index_management' });
}, [application, http, indicesStatus]);
setHasDoneRedirect(true);
}, [application, http, indicesStatus, lastStatus, hasDoneRedirect]);
};
18 changes: 13 additions & 5 deletions x-pack/plugins/search_indices/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import type {
SearchIndicesServicesContextDeps,
} from './types';
import { initQueryClient } from './services/query_client';
import { INDICES_APP_ID, START_APP_ID } from '../common';
import { INDICES_APP_BASE, START_APP_BASE } from './routes';

export class SearchIndicesPlugin
implements Plugin<SearchIndicesPluginSetup, SearchIndicesPluginStart>
Expand All @@ -26,8 +28,8 @@ export class SearchIndicesPlugin
const queryClient = initQueryClient(core.notifications.toasts);

core.application.register({
id: 'elasticsearchStart',
appRoute: '/app/elasticsearch/start',
id: START_APP_ID,
appRoute: START_APP_BASE,
title: i18n.translate('xpack.searchIndices.elasticsearchStart.startAppTitle', {
defaultMessage: 'Elasticsearch Start',
}),
Expand All @@ -43,8 +45,8 @@ export class SearchIndicesPlugin
},
});
core.application.register({
id: 'elasticsearchIndices',
appRoute: '/app/elasticsearch/indices',
id: INDICES_APP_ID,
appRoute: INDICES_APP_BASE,
title: i18n.translate('xpack.searchIndices.elasticsearchIndices.startAppTitle', {
defaultMessage: 'Elasticsearch Indices',
}),
Expand All @@ -62,12 +64,18 @@ export class SearchIndicesPlugin

return {
enabled: true,
startAppId: START_APP_ID,
startRoute: START_APP_BASE,
};
}

public start(core: CoreStart): SearchIndicesPluginStart {
docLinks.setDocLinks(core.docLinks.links);
return {};
return {
enabled: true,
startAppId: START_APP_ID,
startRoute: START_APP_BASE,
};
}

public stop() {}
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/search_indices/public/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ export enum SearchIndexDetailsTabs {
MAPPINGS = 'mappings',
SETTINGS = 'settings',
}

export const START_APP_BASE = '/app/elasticsearch/start';
export const INDICES_APP_BASE = '/app/elasticsearch/indices';
13 changes: 10 additions & 3 deletions x-pack/plugins/search_indices/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ import type {
MappingProperty,
MappingPropertyBase,
} from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { IndexManagementPluginStart } from '@kbn/index-management-shared-types';
import type { IndexManagementPluginStart } from '@kbn/index-management-shared-types';
import type { AppDeepLinkId } from '@kbn/core-chrome-browser';

export interface SearchIndicesPluginSetup {
enabled: boolean;
startAppId: string;
startRoute: string;
}

export interface SearchIndicesPluginStart {
enabled: boolean;
startAppId: AppDeepLinkId;
startRoute: string;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface SearchIndicesPluginStart {}

export interface AppPluginStartDependencies {
navigation: NavigationPublicPluginStart;
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/search_indices/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
"@kbn/es-types",
"@kbn/search-api-keys-server",
"@kbn/search-api-keys-components",
"@kbn/search-shared-ui"
"@kbn/search-shared-ui",
"@kbn/deeplinks-search",
"@kbn/core-chrome-browser"
],
"exclude": [
"target/**/*",
Expand Down
33 changes: 30 additions & 3 deletions x-pack/plugins/serverless_search/public/navigation_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,27 @@
* 2.0.
*/

import type { NavigationTreeDefinition } from '@kbn/core-chrome-browser';
import type {
AppDeepLinkId,
NavigationTreeDefinition,
NodeDefinition,
} from '@kbn/core-chrome-browser';
import { i18n } from '@kbn/i18n';
import { CONNECTORS_LABEL } from '../common/i18n_string';

export const navigationTree = (): NavigationTreeDefinition => ({
const gettingStartedItem: NodeDefinition<AppDeepLinkId, string, string> = {
id: 'gettingStarted',
title: i18n.translate('xpack.serverlessSearch.nav.gettingStarted', {
defaultMessage: 'Getting Started',
}),
link: 'serverlessElasticsearch',
spaceBefore: 'm',
};

export const navigationTree = (
homeLink: AppDeepLinkId = 'serverlessElasticsearch' as AppDeepLinkId,
showGettingStarted: boolean
): NavigationTreeDefinition => ({
body: [
{
type: 'navGroup',
Expand All @@ -25,7 +41,7 @@ export const navigationTree = (): NavigationTreeDefinition => ({
title: i18n.translate('xpack.serverlessSearch.nav.home', {
defaultMessage: 'Home',
}),
link: 'serverlessElasticsearch',
link: homeLink,
spaceBefore: 'm',
},
{
Expand Down Expand Up @@ -70,6 +86,16 @@ export const navigationTree = (): NavigationTreeDefinition => ({
link: 'management:index_management',
breadcrumbStatus:
'hidden' /* management sub-pages set their breadcrumbs themselves */,
getIsActive: ({ pathNameSerialized, prepend }) => {
return (
pathNameSerialized.startsWith(
prepend('/app/management/data/index_management/')
) ||
pathNameSerialized.startsWith(
prepend('/app/elasticsearch/indices/index_details/')
)
);
},
},
{
title: CONNECTORS_LABEL,
Expand Down Expand Up @@ -112,6 +138,7 @@ export const navigationTree = (): NavigationTreeDefinition => ({
},
],
},
...(showGettingStarted ? [gettingStartedItem] : []),
],
},
],
Expand Down
37 changes: 32 additions & 5 deletions x-pack/plugins/serverless_search/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export class ServerlessSearchPlugin
const homeTitle = i18n.translate('xpack.serverlessSearch.app.home.title', {
defaultMessage: 'Home',
});
const useGlobalEmptyState = setupDeps.searchIndices?.enabled ?? false;
const serverlessElasticsearchAppRoute = useGlobalEmptyState
? '/app/elasticsearch/getting_started'
: '/app/elasticsearch';

core.application.register({
id: 'serverlessElasticsearch',
Expand All @@ -81,7 +85,7 @@ export class ServerlessSearchPlugin
}),
euiIconType: 'logoElastic',
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
appRoute: '/app/elasticsearch',
appRoute: serverlessElasticsearchAppRoute,
async mount({ element, history }: AppMountParameters) {
const { renderApp } = await import('./application/elasticsearch');
const [coreStart, services] = await core.getStartServices();
Expand Down Expand Up @@ -120,6 +124,24 @@ export class ServerlessSearchPlugin
},
});

if (useGlobalEmptyState) {
const redirectApp = setupDeps.searchIndices!.startAppId;
core.application.register({
id: 'serverlessHomeRedirect',
title: homeTitle,
appRoute: '/app/elasticsearch',
euiIconType: 'logoElastic',
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
visibleIn: [],
async mount({}: AppMountParameters) {
const [coreStart] = await core.getStartServices();
coreStart.chrome.docTitle.change(homeTitle);
coreStart.application.navigateToApp(redirectApp);
return () => {};
},
});
}

setupDeps.discover.showInlineTopNav();

return {};
Expand All @@ -130,10 +152,15 @@ export class ServerlessSearchPlugin
services: ServerlessSearchPluginStartDependencies
): ServerlessSearchPluginStart {
const { serverless, management, indexManagement, security } = services;

serverless.setProjectHome('/app/elasticsearch');

const navigationTree$ = of(navigationTree());
const useGlobalEmptyState = services.searchIndices?.enabled ?? false;
const homeRoute = useGlobalEmptyState
? services.searchIndices!.startRoute
: '/app/elasticsearch';
serverless.setProjectHome(homeRoute);

const navigationTree$ = of(
navigationTree(services.searchIndices?.startAppId, useGlobalEmptyState)
);
serverless.initNavigation('search', navigationTree$, { dataTestSubj: 'svlSearchSideNav' });

const extendCardNavDefinitions = serverless.getNavigationCards(
Expand Down
Loading