Skip to content

Commit

Permalink
[8.x] [ES3][Search] Create Index Page (#199402) (#199703)
Browse files Browse the repository at this point in the history
# Backport

This will backport the following commits from `main` to `8.x`:
- [[ES3][Search] Create Index Page
(#199402)](#199402)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Rodney
Norris","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-11-11T19:24:32Z","message":"[ES3][Search]
Create Index Page (#199402)\n\n## Summary\r\n\r\nThis PR introduces a
Create Index page for the serverless search\r\nsolution. This page is
almost identical to the new Global Empty State,\r\nbut is navigated to
via the Create Index button in Index Management. The\r\nindex details
redirect logic is also slightly different on the Create\r\nIndex page,
it will only redirect when the \"code\" view is open and a new\r\nindex
is created. instead of redirecting from both UI and Code view
like\r\nthe Global Empty State page does.\r\n\r\nWith the addition of
this page we are also removing the \"Home\" link from\r\nthe serverless
search side nav to reduce confusion when the global empty\r\nstart
redirects to index management when indices exist.\r\n\r\nThere is also
some minor clean-up to ensure both the global empty state\r\nand the new
create index pages have proper document titles
and\r\nbreadcrumbs.\r\n\r\n### Screenshots\r\nUpdates to Global Empty
State:\r\n\r\n![image](https://github.com/user-attachments/assets/bb60734e-543d-4481-b121-d52633d462a8)\r\nCreate
Index Page:\r\n<img width=\"1320\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/0d095eb6-fda3-4783-83ab-20449b5b31f1\">\r\n\r\n###
Checklist\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [x] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [x] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>\r\nCo-authored-by:
Elastic Machine
<[email protected]>","sha":"e03e59b6d482a05435d86a612d92028f264df893","branchLabelMapping":{"^v9.0.0$":"main","^v8.17.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Search","backport:prev-minor","v8.17.0"],"number":199402,"url":"https://github.com/elastic/kibana/pull/199402","mergeCommit":{"message":"[ES3][Search]
Create Index Page (#199402)\n\n## Summary\r\n\r\nThis PR introduces a
Create Index page for the serverless search\r\nsolution. This page is
almost identical to the new Global Empty State,\r\nbut is navigated to
via the Create Index button in Index Management. The\r\nindex details
redirect logic is also slightly different on the Create\r\nIndex page,
it will only redirect when the \"code\" view is open and a new\r\nindex
is created. instead of redirecting from both UI and Code view
like\r\nthe Global Empty State page does.\r\n\r\nWith the addition of
this page we are also removing the \"Home\" link from\r\nthe serverless
search side nav to reduce confusion when the global empty\r\nstart
redirects to index management when indices exist.\r\n\r\nThere is also
some minor clean-up to ensure both the global empty state\r\nand the new
create index pages have proper document titles
and\r\nbreadcrumbs.\r\n\r\n### Screenshots\r\nUpdates to Global Empty
State:\r\n\r\n![image](https://github.com/user-attachments/assets/bb60734e-543d-4481-b121-d52633d462a8)\r\nCreate
Index Page:\r\n<img width=\"1320\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/0d095eb6-fda3-4783-83ab-20449b5b31f1\">\r\n\r\n###
Checklist\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [x] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [x] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>\r\nCo-authored-by:
Elastic Machine
<[email protected]>","sha":"e03e59b6d482a05435d86a612d92028f264df893"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/199402","number":199402,"mergeCommit":{"message":"[ES3][Search]
Create Index Page (#199402)\n\n## Summary\r\n\r\nThis PR introduces a
Create Index page for the serverless search\r\nsolution. This page is
almost identical to the new Global Empty State,\r\nbut is navigated to
via the Create Index button in Index Management. The\r\nindex details
redirect logic is also slightly different on the Create\r\nIndex page,
it will only redirect when the \"code\" view is open and a new\r\nindex
is created. instead of redirecting from both UI and Code view
like\r\nthe Global Empty State page does.\r\n\r\nWith the addition of
this page we are also removing the \"Home\" link from\r\nthe serverless
search side nav to reduce confusion when the global empty\r\nstart
redirects to index management when indices exist.\r\n\r\nThere is also
some minor clean-up to ensure both the global empty state\r\nand the new
create index pages have proper document titles
and\r\nbreadcrumbs.\r\n\r\n### Screenshots\r\nUpdates to Global Empty
State:\r\n\r\n![image](https://github.com/user-attachments/assets/bb60734e-543d-4481-b121-d52633d462a8)\r\nCreate
Index Page:\r\n<img width=\"1320\"
alt=\"image\"\r\nsrc=\"https://github.com/user-attachments/assets/0d095eb6-fda3-4783-83ab-20449b5b31f1\">\r\n\r\n###
Checklist\r\n\r\n- [x] Any text added follows [EUI's
writing\r\nguidelines](https://elastic.github.io/eui/#/guidelines/writing),
uses\r\nsentence case text and includes
[i18n\r\nsupport](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)\r\n-
[
]\r\n[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)\r\nwas
added for features that require explanation or tutorials\r\n- [x] [Unit
or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n- [x] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [x] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [x] Any UI
touched in this PR does not create any new axe failures\r\n(run axe in
browser:\r\n[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),\r\n[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>\r\nCo-authored-by:
Elastic Machine
<[email protected]>","sha":"e03e59b6d482a05435d86a612d92028f264df893"}},{"branch":"8.x","label":"v8.17.0","labelRegex":"^v8.17.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

---------

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
TattdCodeMonkey and elasticmachine authored Nov 12, 2024
1 parent f157662 commit 8c95788
Show file tree
Hide file tree
Showing 51 changed files with 1,460 additions and 624 deletions.
1 change: 1 addition & 0 deletions packages/deeplinks/search/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export const SEARCH_ELASTICSEARCH = 'enterpriseSearchElasticsearch';
export const SEARCH_VECTOR_SEARCH = 'enterpriseSearchVectorSearch';
export const SEARCH_SEMANTIC_SEARCH = 'enterpriseSearchSemanticSearch';
export const SEARCH_AI_SEARCH = 'enterpriseSearchAISearch';
export const SEARCH_INDICES_CREATE_INDEX = 'createIndex';
6 changes: 5 additions & 1 deletion packages/deeplinks/search/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
SEARCH_HOMEPAGE,
SEARCH_INDICES_START,
SEARCH_INDICES,
SEARCH_INDICES_CREATE_INDEX,
SEARCH_ELASTICSEARCH,
SEARCH_VECTOR_SEARCH,
SEARCH_SEMANTIC_SEARCH,
Expand Down Expand Up @@ -55,6 +56,8 @@ export type AppsearchLinkId = 'engines';

export type RelevanceLinkId = 'inferenceEndpoints';

export type SearchIndicesLinkId = typeof SEARCH_INDICES_CREATE_INDEX;

export type DeepLinkId =
| EnterpriseSearchApp
| EnterpriseSearchContentApp
Expand All @@ -77,4 +80,5 @@ export type DeepLinkId =
| SearchElasticsearch
| SearchVectorSearch
| SearchSemanticSearch
| SearchAISearch;
| SearchAISearch
| `${SearchIndices}:${SearchIndicesLinkId}`;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import React from 'react';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import type { SharePluginStart } from '@kbn/share-plugin/public';
import { CreateIndexButton } from '../../sections/home/index_list/create_index/create_index_button';
import { ExtensionsService } from '../../../services/extensions_service';

Expand All @@ -16,11 +17,13 @@ export const NoMatch = ({
filter,
resetFilter,
extensionsService,
share,
}: {
loadIndices: () => void;
filter: string;
resetFilter: () => void;
extensionsService: ExtensionsService;
share?: SharePluginStart;
}) => {
if (filter) {
return (
Expand Down Expand Up @@ -62,7 +65,7 @@ export const NoMatch = ({

if (extensionsService.emptyListContent) {
return extensionsService.emptyListContent.renderContent({
createIndexButton: <CreateIndexButton loadIndices={loadIndices} />,
createIndexButton: <CreateIndexButton loadIndices={loadIndices} share={share} />,
});
}

Expand All @@ -85,7 +88,7 @@ export const NoMatch = ({
/>
</p>
}
actions={<CreateIndexButton loadIndices={loadIndices} />}
actions={<CreateIndexButton loadIndices={loadIndices} share={share} />}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,32 @@

import React, { useState } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import type { SharePluginStart } from '@kbn/share-plugin/public';
import { EuiButton } from '@elastic/eui';

import { CreateIndexModal } from './create_index_modal';

export const CreateIndexButton = ({ loadIndices }: { loadIndices: () => void }) => {
export interface CreateIndexButtonProps {
loadIndices: () => void;
share?: SharePluginStart;
}

export const CreateIndexButton = ({ loadIndices, share }: CreateIndexButtonProps) => {
const [createIndexModalOpen, setCreateIndexModalOpen] = useState<boolean>(false);
const createIndexUrl = share?.url.locators.get('SEARCH_CREATE_INDEX')?.useUrl({});
const actionProp = createIndexUrl
? { href: createIndexUrl }
: { onClick: () => setCreateIndexModalOpen(true) };

return (
<>
<EuiButton
fill
iconType="plusInCircleFilled"
onClick={() => setCreateIndexModalOpen(true)}
key="createIndexButton"
data-test-subj="createIndexButton"
data-telemetry-id="idxMgmt-indexList-createIndexButton"
{...actionProp}
>
<FormattedMessage
id="xpack.idxMgmt.indexTable.createIndexButton"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,10 @@ export class IndexTable extends Component {

return (
<AppContextConsumer>
{({ services, config, core }) => {
{({ services, config, core, plugins }) => {
const { extensionsService } = services;
const { application, http } = core;
const { share } = plugins;
const columnConfigs = getColumnConfigs({
showIndexStats: config.enableIndexStats,
showSizeAndDocCount: config.enableSizeAndDocCount,
Expand Down Expand Up @@ -669,7 +670,7 @@ export class IndexTable extends Component {
</>
)}
<EuiFlexItem grow={false}>
<CreateIndexButton loadIndices={loadIndices} />
<CreateIndexButton loadIndices={loadIndices} share={share} />
</EuiFlexItem>
</EuiFlexGroup>

Expand Down Expand Up @@ -714,6 +715,7 @@ export class IndexTable extends Component {
<EuiTableRowCell align="center" colSpan={columnsCount}>
<NoMatch
loadIndices={loadIndices}
share={share}
filter={filter}
resetFilter={() => filterChanged('')}
extensionsService={extensionsService}
Expand Down
13 changes: 12 additions & 1 deletion x-pack/plugins/search_indices/public/analytics/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export enum AnalyticsEvents {
startCreateIndexPageModifyIndexName = 'start_modify_index_name',
startCreateIndexClick = 'start_create_index',
startCreateIndexLanguageSelect = 'start_code_lang_select',
startCreateIndexRunInConsole = 'start_cta_run_in_console',
startCreateIndexCodeCopyInstall = 'start_code_copy_install',
startCreateIndexCodeCopy = 'start_code_copy',
startCreateIndexRunInConsole = 'start_cta_run_in_console',
startCreateIndexCreatedRedirect = 'start_index_created_api',
startFileUploadClick = 'start_file_upload',
indexDetailsInstallCodeCopy = 'index_details_code_copy_install',
Expand All @@ -23,4 +23,15 @@ export enum AnalyticsEvents {
indexDetailsNavDataTab = 'index_details_nav_data_tab',
indexDetailsNavSettingsTab = 'index_details_nav_settings_tab',
indexDetailsNavMappingsTab = 'index_details_nav_mappings_tab',
createIndexPageOpened = 'create_index_page_opened',
createIndexShowCodeClick = 'create_index_show_code',
createIndexShowUIClick = 'create_index_show_create_index_ui',
createIndexPageModifyIndexName = 'create_index_modify_index_name',
createIndexCreateIndexClick = 'create_index_click_create',
createIndexLanguageSelect = 'create_index_code_lang_select',
createIndexRunInConsole = 'create_index_run_in_console',
createIndexCodeCopyInstall = 'create_index_copy_install',
createIndexCodeCopy = 'create_index_code_copy',
createIndexFileUploadClick = 'create_index_file_upload',
createIndexIndexCreatedRedirect = 'create_index_created_api',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* 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, { useCallback, useState } from 'react';

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

import { AnalyticsEvents } from '../../analytics/constants';
import { AvailableLanguages } from '../../code_examples';
import { useKibana } from '../../hooks/use_kibana';
import { useUsageTracker } from '../../hooks/use_usage_tracker';
import { CreateIndexFormState } from '../../types';
import { generateRandomIndexName } from '../../utils/indices';
import { getDefaultCodingLanguage } from '../../utils/language';

import { CreateIndexPanel } from '../shared/create_index_panel';

import { CreateIndexCodeView } from './create_index_code_view';
import { CreateIndexUIView } from './create_index_ui_view';

function initCreateIndexState() {
const defaultIndexName = generateRandomIndexName();
return {
indexName: defaultIndexName,
defaultIndexName,
codingLanguage: getDefaultCodingLanguage(),
};
}

export interface CreateIndexProps {
indicesData?: IndicesStatusResponse;
userPrivileges?: UserStartPrivilegesResponse;
}

enum CreateIndexViewMode {
UI = 'ui',
Code = 'code',
}

export const CreateIndex = ({ indicesData, userPrivileges }: CreateIndexProps) => {
const { application } = useKibana().services;
const [createIndexView, setCreateIndexView] = useState<CreateIndexViewMode>(
userPrivileges?.privileges.canCreateIndex === false
? CreateIndexViewMode.Code
: CreateIndexViewMode.UI
);
const [formState, setFormState] = useState<CreateIndexFormState>(initCreateIndexState);
const usageTracker = useUsageTracker();
const onChangeView = useCallback(
(id: string) => {
switch (id) {
case CreateIndexViewMode.UI:
usageTracker.click(AnalyticsEvents.createIndexShowUIClick);
setCreateIndexView(CreateIndexViewMode.UI);
return;
case CreateIndexViewMode.Code:
usageTracker.click(AnalyticsEvents.createIndexShowCodeClick);
setCreateIndexView(CreateIndexViewMode.Code);
return;
}
},
[usageTracker]
);
const onChangeCodingLanguage = useCallback(
(language: AvailableLanguages) => {
setFormState({
...formState,
codingLanguage: language,
});
usageTracker.count([
AnalyticsEvents.createIndexLanguageSelect,
`${AnalyticsEvents.createIndexLanguageSelect}_${language}`,
]);
},
[usageTracker, formState, setFormState]
);
const onClose = useCallback(() => {
application.navigateToApp('management', { deepLinkId: 'index_management' });
}, [application]);

return (
<CreateIndexPanel
createIndexView={createIndexView}
onChangeView={onChangeView}
onClose={onClose}
>
{createIndexView === CreateIndexViewMode.UI && (
<CreateIndexUIView
formState={formState}
setFormState={setFormState}
userPrivileges={userPrivileges}
/>
)}
{createIndexView === CreateIndexViewMode.Code && (
<CreateIndexCodeView
indicesData={indicesData}
selectedLanguage={formState.codingLanguage}
indexName={formState.indexName}
changeCodingLanguage={onChangeCodingLanguage}
canCreateApiKey={userPrivileges?.privileges.canCreateApiKeys}
analyticsEvents={{
runInConsole: AnalyticsEvents.createIndexRunInConsole,
installCommands: AnalyticsEvents.createIndexCodeCopyInstall,
createIndex: AnalyticsEvents.createIndexCodeCopy,
}}
/>
)}
</CreateIndexPanel>
);
};
Original file line number Diff line number Diff line change
@@ -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 type { IndicesStatusResponse } from '../../../common';
import {
CreateIndexCodeView as SharedCreateIndexCodeView,
CreateIndexCodeViewProps as SharedCreateIndexCodeViewProps,
} from '../shared/create_index_code_view';

import { useIndicesRedirect } from './hooks/use_indices_redirect';

export interface CreateIndexCodeViewProps extends SharedCreateIndexCodeViewProps {
indicesData?: IndicesStatusResponse;
}

export const CreateIndexCodeView = ({ indicesData, ...props }: CreateIndexCodeViewProps) => {
useIndicesRedirect(indicesData);

return <SharedCreateIndexCodeView {...props} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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 { i18n } from '@kbn/i18n';

import { EuiLoadingLogo, EuiPageTemplate } from '@elastic/eui';
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';

import { useKibana } from '../../hooks/use_kibana';
import { useIndicesStatusQuery } from '../../hooks/api/use_indices_status';
import { useUserPrivilegesQuery } from '../../hooks/api/use_user_permissions';
import { LoadIndicesStatusError } from '../shared/load_indices_status_error';

import { CreateIndex } from './create_index';
import { usePageChrome } from '../../hooks/use_page_chrome';
import { IndexManagementBreadcrumbs } from '../shared/breadcrumbs';

const CreateIndexLabel = i18n.translate('xpack.searchIndices.createIndex.docTitle', {
defaultMessage: 'Create Index',
});

export const CreateIndexPage = () => {
const { console: consolePlugin } = useKibana().services;
const {
data: indicesData,
isInitialLoading,
isError: hasIndicesStatusFetchError,
error: indicesFetchError,
} = useIndicesStatusQuery();
const { data: userPrivileges } = useUserPrivilegesQuery();

const embeddableConsole = useMemo(
() => (consolePlugin?.EmbeddableConsole ? <consolePlugin.EmbeddableConsole /> : null),
[consolePlugin]
);
usePageChrome(CreateIndexLabel, [...IndexManagementBreadcrumbs, { text: CreateIndexLabel }]);

return (
<EuiPageTemplate
offset={0}
restrictWidth={false}
data-test-subj="elasticsearchCreateIndexPage"
grow={false}
>
<KibanaPageTemplate.Section alignment="center" restrictWidth={false} grow>
{isInitialLoading && <EuiLoadingLogo />}
{hasIndicesStatusFetchError && <LoadIndicesStatusError error={indicesFetchError} />}
{!isInitialLoading && !hasIndicesStatusFetchError && (
<CreateIndex indicesData={indicesData} userPrivileges={userPrivileges} />
)}
</KibanaPageTemplate.Section>
{embeddableConsole}
</EuiPageTemplate>
);
};
Loading

0 comments on commit 8c95788

Please sign in to comment.