Skip to content

Commit

Permalink
[8.x] [Onboarding][Index detail] Update right side menu items (#194604)…
Browse files Browse the repository at this point in the history
… (#194761)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Onboarding][Index detail] Update right side menu items
(#194604)](#194604)

<!--- Backport version: 9.4.3 -->

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

<!--BACKPORT [{"author":{"name":"Saarika
Bhasi","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-02T19:21:59Z","message":"[Onboarding][Index
detail] Update right side menu items (#194604)\n\n## Summary\r\nIn this
PR, updates search index detail page right side menu item. \r\n\r\nThe
drop down menu item is updated to have :\r\n* Api reference doc
link\r\n* Use in playground link which navigates to playground selecting
this\r\nindex name\r\n\r\nWhen documents exists right side header action
is replaced with `Use in\r\nplayground` else `Api reference doc
link`\r\n\r\n### Screenshot\r\n<img width=\"1728\" alt=\"Screenshot
2024-10-01 at 11 07
45 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/026c89f8-08fa-41cf-b47f-73fcc2fb07ef\">\r\n<img
width=\"1728\" alt=\"Screenshot 2024-10-01 at 11 08
20 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/447641e0-8693-466a-a4d7-32764f86bf01\">\r\n\r\n**How
to test:** \r\n1. Enable searchIndices plugin in `kibana.dev.yml` as
this plugin is\r\nbehind Feature
flag\r\n```\r\nxpack.searchIndices.enabled: true\r\n\r\n```\r\n2.
[Create
new\r\nindex](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html)\r\n3.
Navigate
to\r\n`/app/elasticsearch/indices/index_details/${indexName}/data`\r\n4.
Confirm index header action is `Api Reference doc` \r\n5. Add documents
confirm index header action is changed to `Use in\r\nplayground`\r\n6.
Confirm menu item shows delete index, use in playground &
api\r\nreference doc link\r\n\r\n### Checklist\r\n\r\nDelete any items
that are not applicable to this PR.\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-
[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","sha":"d482a0a295cfc55c6635f32741543bde7cb38884","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Search","backport:prev-minor","v8.16.0"],"title":"[Onboarding][Index
detail] Update right side menu items
","number":194604,"url":"https://github.com/elastic/kibana/pull/194604","mergeCommit":{"message":"[Onboarding][Index
detail] Update right side menu items (#194604)\n\n## Summary\r\nIn this
PR, updates search index detail page right side menu item. \r\n\r\nThe
drop down menu item is updated to have :\r\n* Api reference doc
link\r\n* Use in playground link which navigates to playground selecting
this\r\nindex name\r\n\r\nWhen documents exists right side header action
is replaced with `Use in\r\nplayground` else `Api reference doc
link`\r\n\r\n### Screenshot\r\n<img width=\"1728\" alt=\"Screenshot
2024-10-01 at 11 07
45 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/026c89f8-08fa-41cf-b47f-73fcc2fb07ef\">\r\n<img
width=\"1728\" alt=\"Screenshot 2024-10-01 at 11 08
20 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/447641e0-8693-466a-a4d7-32764f86bf01\">\r\n\r\n**How
to test:** \r\n1. Enable searchIndices plugin in `kibana.dev.yml` as
this plugin is\r\nbehind Feature
flag\r\n```\r\nxpack.searchIndices.enabled: true\r\n\r\n```\r\n2.
[Create
new\r\nindex](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html)\r\n3.
Navigate
to\r\n`/app/elasticsearch/indices/index_details/${indexName}/data`\r\n4.
Confirm index header action is `Api Reference doc` \r\n5. Add documents
confirm index header action is changed to `Use in\r\nplayground`\r\n6.
Confirm menu item shows delete index, use in playground &
api\r\nreference doc link\r\n\r\n### Checklist\r\n\r\nDelete any items
that are not applicable to this PR.\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-
[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","sha":"d482a0a295cfc55c6635f32741543bde7cb38884"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/194604","number":194604,"mergeCommit":{"message":"[Onboarding][Index
detail] Update right side menu items (#194604)\n\n## Summary\r\nIn this
PR, updates search index detail page right side menu item. \r\n\r\nThe
drop down menu item is updated to have :\r\n* Api reference doc
link\r\n* Use in playground link which navigates to playground selecting
this\r\nindex name\r\n\r\nWhen documents exists right side header action
is replaced with `Use in\r\nplayground` else `Api reference doc
link`\r\n\r\n### Screenshot\r\n<img width=\"1728\" alt=\"Screenshot
2024-10-01 at 11 07
45 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/026c89f8-08fa-41cf-b47f-73fcc2fb07ef\">\r\n<img
width=\"1728\" alt=\"Screenshot 2024-10-01 at 11 08
20 AM\"\r\nsrc=\"https://github.com/user-attachments/assets/447641e0-8693-466a-a4d7-32764f86bf01\">\r\n\r\n**How
to test:** \r\n1. Enable searchIndices plugin in `kibana.dev.yml` as
this plugin is\r\nbehind Feature
flag\r\n```\r\nxpack.searchIndices.enabled: true\r\n\r\n```\r\n2.
[Create
new\r\nindex](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html)\r\n3.
Navigate
to\r\n`/app/elasticsearch/indices/index_details/${indexName}/data`\r\n4.
Confirm index header action is `Api Reference doc` \r\n5. Add documents
confirm index header action is changed to `Use in\r\nplayground`\r\n6.
Confirm menu item shows delete index, use in playground &
api\r\nreference doc link\r\n\r\n### Checklist\r\n\r\nDelete any items
that are not applicable to this PR.\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-
[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","sha":"d482a0a295cfc55c6635f32741543bde7cb38884"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Saarika Bhasi <[email protected]>
  • Loading branch information
kibanamachine and saarikabhasi authored Oct 2, 2024
1 parent 69f3b54 commit 3692ab0
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,23 @@
import React from 'react';

import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiProgress, EuiSpacer } from '@elastic/eui';
import { useIndexDocumentSearch } from '../../hooks/api/use_document_search';
import { useIndexMapping } from '../../hooks/api/use_index_mappings';
import { AddDocumentsCodeExample } from './add_documents_code_example';

import { DEFAULT_PAGE_SIZE } from './constants';
import { IndexDocuments as IndexDocumentsType } from '../../hooks/api/use_document_search';
import { DocumentList } from './document_list';

interface IndexDocumentsProps {
indexName: string;
indexDocuments?: IndexDocumentsType;
isInitialLoading: boolean;
}

export const IndexDocuments: React.FC<IndexDocumentsProps> = ({ indexName }) => {
const { data: indexDocuments, isInitialLoading } = useIndexDocumentSearch(indexName, {
pageSize: DEFAULT_PAGE_SIZE,
pageIndex: 0,
});

export const IndexDocuments: React.FC<IndexDocumentsProps> = ({
indexName,
indexDocuments,
isInitialLoading,
}) => {
const { data: mappingData } = useIndexMapping(indexName);

const docs = indexDocuments?.results?.data ?? [];
const mappingProperties = mappingData?.mappings?.properties ?? {};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ import {
EuiPageTemplate,
EuiFlexItem,
EuiFlexGroup,
EuiPopover,
EuiButtonIcon,
EuiContextMenuItem,
EuiContextMenuPanel,
EuiText,
EuiIcon,
EuiButtonEmpty,
EuiTabbedContent,
EuiTabbedContentTab,
Expand All @@ -37,12 +31,15 @@ import { IndexloadingError } from './details_page_loading_error';
import { SearchIndexDetailsTabs } from '../../routes';
import { SearchIndexDetailsMappings } from './details_page_mappings';
import { SearchIndexDetailsSettings } from './details_page_settings';
import { SearchIndexDetailsPageMenuItemPopover } from './details_page_menu_item';
import { useIndexDocumentSearch } from '../../hooks/api/use_document_search';
import { DEFAULT_PAGE_SIZE } from '../index_documents/constants';

export const SearchIndexDetailsPage = () => {
const indexName = decodeURIComponent(useParams<{ indexName: string }>().indexName);
const tabId = decodeURIComponent(useParams<{ tabId: string }>().tabId);

const { console: consolePlugin, docLinks, application, history } = useKibana().services;
const { console: consolePlugin, docLinks, application, history, share } = useKibana().services;
const {
data: index,
refetch,
Expand All @@ -56,6 +53,25 @@ export const SearchIndexDetailsPage = () => {
isInitialLoading: isMappingsInitialLoading,
error: mappingsError,
} = useIndexMapping(indexName);
const { data: indexDocuments, isInitialLoading: indexDocumentsIsInitialLoading } =
useIndexDocumentSearch(indexName, {
pageSize: DEFAULT_PAGE_SIZE,
pageIndex: 0,
});

const navigateToPlayground = useCallback(async () => {
const playgroundLocator = share.url.locators.get('PLAYGROUND_LOCATOR_ID');
if (playgroundLocator && index) {
await playgroundLocator.navigate({ 'default-index': index.name });
}
}, [share, index]);

const [isDocumentsExists, setDocumentsExists] = useState<boolean>(false);
const [isDocumentsLoading, setDocumentsLoading] = useState<boolean>(true);
useEffect(() => {
setDocumentsLoading(isInitialLoading);
setDocumentsExists(!(!isInitialLoading && indexDocuments?.results?.data.length === 0));
}, [indexDocuments, isInitialLoading, setDocumentsExists, setDocumentsLoading]);

const detailsPageTabs: EuiTabbedContentTab[] = useMemo(() => {
return [
Expand All @@ -64,7 +80,13 @@ export const SearchIndexDetailsPage = () => {
name: i18n.translate('xpack.searchIndices.documentsTabLabel', {
defaultMessage: 'Data',
}),
content: <IndexDocuments indexName={indexName} />,
content: (
<IndexDocuments
indexName={indexName}
indexDocuments={indexDocuments}
isInitialLoading={indexDocumentsIsInitialLoading}
/>
),
'data-test-subj': `${SearchIndexDetailsTabs.DATA}Tab`,
},
{
Expand All @@ -84,7 +106,7 @@ export const SearchIndexDetailsPage = () => {
'data-test-subj': `${SearchIndexDetailsTabs.SETTINGS}Tab`,
},
];
}, [index, indexName]);
}, [index, indexName, indexDocuments, indexDocumentsIsInitialLoading]);
const [selectedTab, setSelectedTab] = useState(detailsPageTabs[0]);

useEffect(() => {
Expand Down Expand Up @@ -123,47 +145,11 @@ export const SearchIndexDetailsPage = () => {
},
[isIndexError, indexLoadingError, mappingsError]
);
const [showMoreOptions, setShowMoreOptions] = useState<boolean>(false);
const [isShowingDeleteModal, setShowDeleteIndexModal] = useState<boolean>(false);
const moreOptionsPopover = (
<EuiPopover
isOpen={showMoreOptions}
closePopover={() => setShowMoreOptions(!showMoreOptions)}
button={
<EuiButtonIcon
iconType="boxesVertical"
onClick={() => setShowMoreOptions(!showMoreOptions)}
size="m"
data-test-subj="moreOptionsActionButton"
aria-label={i18n.translate('xpack.searchIndices.moreOptions.ariaLabel', {
defaultMessage: 'More options',
})}
/>
}
>
<EuiContextMenuPanel
data-test-subj="moreOptionsContextMenu"
items={[
<EuiContextMenuItem
key="trash"
icon={<EuiIcon type="trash" color="danger" />}
onClick={() => {
setShowDeleteIndexModal(!isShowingDeleteModal);
}}
size="s"
color="danger"
data-test-subj="moreOptionsDeleteIndex"
>
<EuiText size="s" color="danger">
{i18n.translate('xpack.searchIndices.moreOptions.deleteIndexLabel', {
defaultMessage: 'Delete Index',
})}
</EuiText>
</EuiContextMenuItem>,
]}
/>
</EuiPopover>
);
const handleDeleteIndexModal = useCallback(() => {
setShowDeleteIndexModal(!isShowingDeleteModal);
}, [isShowingDeleteModal]);

if (isInitialLoading || isMappingsInitialLoading) {
return (
<SectionLoading>
Expand Down Expand Up @@ -208,20 +194,47 @@ export const SearchIndexDetailsPage = () => {
data-test-subj="searchIndexDetailsHeader"
pageTitle={index?.name}
rightSideItems={[
<EuiFlexGroup>
<EuiFlexGroup gutterSize="none">
<EuiFlexItem>
<EuiButtonEmpty
href={docLinks.links.apiReference}
target="_blank"
iconType="documentation"
data-test-subj="ApiReferenceDoc"
>
{i18n.translate('xpack.searchIndices.indexActionsMenu.apiReference.docLink', {
defaultMessage: 'API Reference',
})}
</EuiButtonEmpty>
{!isDocumentsExists ? (
<EuiButtonEmpty
href={docLinks.links.apiReference}
target="_blank"
isLoading={isDocumentsLoading}
iconType="documentation"
data-test-subj="ApiReferenceDoc"
>
<FormattedMessage
id="xpack.searchIndices.indexAction.ApiReferenceButtonLabel"
defaultMessage="{buttonLabel}"
values={{
buttonLabel: isDocumentsLoading ? 'Loading' : 'API Reference',
}}
/>
</EuiButtonEmpty>
) : (
<EuiButtonEmpty
isLoading={isDocumentsLoading}
iconType="launch"
data-test-subj="useInPlaygroundLink"
onClick={navigateToPlayground}
>
<FormattedMessage
id="xpack.searchIndices.indexAction.useInPlaygroundButtonLabel"
defaultMessage="{buttonLabel}"
values={{
buttonLabel: isDocumentsLoading ? 'Loading' : 'Use in Playground',
}}
/>
</EuiButtonEmpty>
)}
</EuiFlexItem>
<EuiFlexItem>
<SearchIndexDetailsPageMenuItemPopover
handleDeleteIndexModal={handleDeleteIndexModal}
navigateToPlayground={navigateToPlayground}
/>
</EuiFlexItem>
<EuiFlexItem>{moreOptionsPopover}</EuiFlexItem>
</EuiFlexGroup>,
]}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* 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 {
EuiButtonIcon,
EuiContextMenuItem,
EuiContextMenuPanel,
EuiIcon,
EuiPopover,
EuiText,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { MouseEventHandler, ReactElement, useState } from 'react';
import { useKibana } from '../../hooks/use_kibana';

enum MenuItems {
playground = 'playground',
apiReference = 'apiReference',
deleteIndex = 'deleteIndex',
}
interface MenuItemsAction {
href?: string;
onClick?: (() => void) | MouseEventHandler;
}

const SearchIndexDetailsPageMenuItemPopoverItems = [
{
type: MenuItems.playground,
iconType: 'launch',
dataTestSubj: 'moreOptionsPlayground',
iconComponent: <EuiIcon type="launch" />,
target: undefined,
text: (
<EuiText size="s">
{i18n.translate('xpack.searchIndices.moreOptions.playgroundLabel', {
defaultMessage: 'Use in Playground',
})}
</EuiText>
),
color: undefined,
},
{
type: MenuItems.apiReference,
iconType: 'documentation',
dataTestSubj: 'moreOptionsApiReference',
iconComponent: <EuiIcon type="documentation" />,
target: '_blank',
text: (
<EuiText size="s">
{i18n.translate('xpack.searchIndices.moreOptions.apiReferenceLabel', {
defaultMessage: 'API Reference',
})}
</EuiText>
),
color: undefined,
},
{
type: MenuItems.deleteIndex,
iconType: 'trash',
dataTestSubj: 'moreOptionsDeleteIndex',
iconComponent: <EuiIcon color="danger" type="trash" />,
target: undefined,
text: (
<EuiText size="s" color="danger">
{i18n.translate('xpack.searchIndices.moreOptions.deleteIndexLabel', {
defaultMessage: 'Delete Index',
})}
</EuiText>
),
color: 'danger',
},
];
interface SearchIndexDetailsPageMenuItemPopoverProps {
handleDeleteIndexModal: () => void;
navigateToPlayground: () => void;
}

export const SearchIndexDetailsPageMenuItemPopover = ({
handleDeleteIndexModal,
navigateToPlayground,
}: SearchIndexDetailsPageMenuItemPopoverProps) => {
const [showMoreOptions, setShowMoreOptions] = useState<boolean>(false);
const { docLinks } = useKibana().services;
const contextMenuItemsActions: Record<MenuItems, MenuItemsAction> = {
playground: {
href: undefined,
onClick: navigateToPlayground,
},
apiReference: { href: docLinks.links.apiReference, onClick: undefined },
deleteIndex: { href: undefined, onClick: handleDeleteIndexModal },
};
const contextMenuItems: ReactElement[] = SearchIndexDetailsPageMenuItemPopoverItems.map(
(item) => (
<EuiContextMenuItem
key={item.iconType}
icon={item.iconComponent}
href={contextMenuItemsActions[item.type]?.href}
size="s"
onClick={contextMenuItemsActions[item.type]?.onClick}
target={item.target}
data-test-subj={item.dataTestSubj}
color={item.color}
>
{item.text}
</EuiContextMenuItem>
)
);

return (
<EuiPopover
isOpen={showMoreOptions}
closePopover={() => setShowMoreOptions(!showMoreOptions)}
button={
<EuiButtonIcon
iconType="boxesVertical"
onClick={() => setShowMoreOptions(!showMoreOptions)}
size="m"
data-test-subj="moreOptionsActionButton"
aria-label={i18n.translate('xpack.searchIndices.moreOptions.ariaLabel', {
defaultMessage: 'More options',
})}
/>
}
>
<EuiContextMenuPanel data-test-subj="moreOptionsContextMenu" items={contextMenuItems} />
</EuiPopover>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { pageToPagination, Paginate } from '@kbn/search-index-documents';
import { useQuery } from '@tanstack/react-query';
import { useKibana } from '../use_kibana';

interface IndexDocuments {
export interface IndexDocuments {
meta: Pagination;
results: Paginate<SearchHit>;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export function SvlSearchIndexDetailPageProvider({ getService }: FtrProviderCont
async expectAPIReferenceDocLinkExists() {
await testSubjects.existOrFail('ApiReferenceDoc', { timeout: 2000 });
},
async expectUseInPlaygroundLinkExists() {
await testSubjects.existOrFail('useInPlaygroundLink', { timeout: 5000 });
},
async expectBackToIndicesButtonExists() {
await testSubjects.existOrFail('backToIndicesButton', { timeout: 2000 });
},
Expand Down Expand Up @@ -82,7 +85,20 @@ export function SvlSearchIndexDetailPageProvider({ getService }: FtrProviderCont
async expectMoreOptionsOverviewMenuIsShown() {
await testSubjects.existOrFail('moreOptionsContextMenu');
},
async expectDeleteIndexButtonExists() {
async expectPlaygroundButtonExistsInMoreOptions() {
await testSubjects.existOrFail('moreOptionsPlayground');
},
async expectToNavigateToPlayground(indexName: string) {
await testSubjects.click('moreOptionsPlayground');
expect(await browser.getCurrentUrl()).contain(
`/search_playground/chat?default-index=${indexName}`
);
await testSubjects.existOrFail('chatPage');
},
async expectAPIReferenceDocLinkExistsInMoreOptions() {
await testSubjects.existOrFail('moreOptionsApiReference', { timeout: 2000 });
},
async expectDeleteIndexButtonExistsInMoreOptions() {
await testSubjects.existOrFail('moreOptionsDeleteIndex');
},
async clickDeleteIndexButton() {
Expand Down
Loading

0 comments on commit 3692ab0

Please sign in to comment.