Skip to content

Commit

Permalink
[8.x] [Search] [Onboarding] With Data View (#193121) (#193469)
Browse files Browse the repository at this point in the history
# Backport

This will backport the following commits from `main` to `8.x`:
- [[Search] [Onboarding] With Data View
(#193121)](#193121)

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

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

<!--BACKPORT [{"author":{"name":"Joe
McElroy","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-09-17T18:49:05Z","message":"[Search]
[Onboarding] With Data View (#193121)\n\n## Summary\r\n\r\nAdds the
document view tab when the index has
documents\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/37efbd78-9fae-465b-a3ab-2803a8858285)\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] 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- [ ] [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- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] 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-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"2d78f23ddec9d6d5c71e65537d516ac36d1251c4","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport
missing","v9.0.0","Team:EnterpriseSearch","backport:prev-minor"],"number":193121,"url":"https://github.com/elastic/kibana/pull/193121","mergeCommit":{"message":"[Search]
[Onboarding] With Data View (#193121)\n\n## Summary\r\n\r\nAdds the
document view tab when the index has
documents\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/37efbd78-9fae-465b-a3ab-2803a8858285)\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] 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- [ ] [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- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] 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-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"2d78f23ddec9d6d5c71e65537d516ac36d1251c4"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/193121","number":193121,"mergeCommit":{"message":"[Search]
[Onboarding] With Data View (#193121)\n\n## Summary\r\n\r\nAdds the
document view tab when the index has
documents\r\n\r\n\r\n![image](https://github.com/user-attachments/assets/37efbd78-9fae-465b-a3ab-2803a8858285)\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [ ] 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- [ ] [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- [ ] [Flaky
Test\r\nRunner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1)
was\r\nused on any tests changed\r\n- [ ] Any UI touched in this PR is
usable by keyboard only (learn more\r\nabout [keyboard
accessibility](https://webaim.org/techniques/keyboard/))\r\n- [ ] 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-
[ ] If a plugin configuration key changed, check if it needs to
be\r\nallowlisted in the cloud and added to the
[docker\r\nlist](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)\r\n-
[ ] This renders correctly on smaller devices using a
responsive\r\nlayout. (You can test this [in
your\r\nbrowser](https://www.browserstack.com/guide/responsive-testing-on-local-server))\r\n-
[ ] This was checked for
[cross-browser\r\ncompatibility](https://www.elastic.co/support/matrix#matrix_browsers)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"2d78f23ddec9d6d5c71e65537d516ac36d1251c4"}}]}]
BACKPORT-->

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
joemcelroy and elasticmachine authored Sep 20, 2024
1 parent 2209cf0 commit d188b65
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 38 deletions.
18 changes: 2 additions & 16 deletions packages/kbn-search-index-documents/components/document_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { i18n } from '@kbn/i18n';

import { FormattedMessage, FormattedNumber } from '@kbn/i18n-react';

import { resultMetaData } from './result/result_metadata';
import { resultMetaData, resultToField } from './result/result_metadata';

import { Result } from '..';
interface DocumentListProps {
Expand All @@ -55,20 +55,6 @@ export const DocumentList: React.FC<DocumentListProps> = ({
setDocsPerPage,
}) => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const resultToField = (result: SearchHit) => {
if (mappings && result._source && !Array.isArray(result._source)) {
if (typeof result._source === 'object') {
return Object.entries(result._source).map(([key, value]) => {
return {
fieldName: key,
fieldType: mappings[key]?.type ?? 'object',
fieldValue: JSON.stringify(value, null, 2),
};
});
}
}
return [];
};

const getIconType = (size: number) => {
return size === docsPerPage ? 'check' : 'empty';
Expand Down Expand Up @@ -113,7 +99,7 @@ export const DocumentList: React.FC<DocumentListProps> = ({
{docs.map((doc) => {
return (
<React.Fragment key={doc._id}>
<Result fields={resultToField(doc)} metaData={resultMetaData(doc)} />
<Result fields={resultToField(doc, mappings)} metaData={resultMetaData(doc)} />
<EuiSpacer size="s" />
</React.Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export { Result } from './result';
export { resultMetaData, resultToField } from './result_metadata';
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { SearchHit } from '@elastic/elasticsearch/lib/api/types';
import { MetaDataProps } from './result_types';
import type { MappingProperty, SearchHit } from '@elastic/elasticsearch/lib/api/types';
import type { MetaDataProps } from './result_types';

const TITLE_KEYS = ['title', 'name'];

Expand Down Expand Up @@ -38,3 +38,18 @@ export const resultMetaData = (result: SearchHit): MetaDataProps => ({
id: result._id!,
title: resultTitle(result),
});

export const resultToField = (result: SearchHit, mappings?: Record<string, MappingProperty>) => {
if (mappings && result._source && !Array.isArray(result._source)) {
if (typeof result._source === 'object') {
return Object.entries(result._source).map(([key, value]) => {
return {
fieldName: key,
fieldType: mappings[key]?.type ?? 'object',
fieldValue: JSON.stringify(value, null, 2),
};
});
}
}
return [];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 { EuiPanel } from '@elastic/eui';

export const AddDocumentsCodeExample: React.FC = () => {
return (
<EuiPanel
hasBorder={false}
hasShadow={false}
paddingSize="none"
data-test-subj="SearchIndicesAddDocumentsCode"
>
TODO: WITHOUT DATA TICKET
</EuiPanel>
);
};
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 from 'react';

import { Result, resultToField, resultMetaData } from '@kbn/search-index-documents';

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

interface IndexDocumentsProps {
indexName: string;
}

interface RecentDocsActionMessageProps {
indexName: string;
}

const DEFAULT_PAGE_SIZE = 50;

const RecentDocsActionMessage: React.FC<RecentDocsActionMessageProps> = ({ indexName }) => {
const {
services: { share },
} = useKibana();

const discoverLocator = share.url.locators.get('DISCOVER_APP_LOCATOR');

const onClick = async () => {
await discoverLocator?.navigate({ dataViewSpec: { title: indexName } });
};

return (
<EuiPanel hasBorder={false} hasShadow={false} color="subdued" borderRadius="none">
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiIcon type="calendar" />
</EuiFlexItem>
<EuiFlexItem>
<p>
{i18n.translate('xpack.searchIndices.indexDocuments.recentDocsActionMessage', {
defaultMessage:
'You are viewing the {pageSize} most recently ingested documents in this index. To see all documents, view in',
values: {
pageSize: DEFAULT_PAGE_SIZE,
},
})}{' '}
<EuiLink onClick={onClick}>
{i18n.translate('xpack.searchIndices.indexDocuments.recentDocsActionMessageLink', {
defaultMessage: 'Discover.',
})}
</EuiLink>
</p>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
};

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

const { data: mappingData } = useIndexMapping(indexName);

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

return (
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="none">
<EuiSpacer />
<EuiFlexGroup direction="column">
<EuiFlexItem>
{isInitialLoading && <EuiProgress size="xs" color="primary" />}
{docs.length === 0 && <AddDocumentsCodeExample />}
{docs.length > 0 && (
<>
<RecentDocsActionMessage indexName={indexName} />
<EuiSpacer size="m" />
{docs.map((doc) => {
return (
<React.Fragment key={doc._id}>
<Result
fields={resultToField(doc, mappingProperties)}
metaData={resultMetaData(doc)}
/>
<EuiSpacer size="s" />
</React.Fragment>
);
})}
</>
)}
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import {
EuiPageSection,
EuiSpacer,
EuiButton,
EuiPageTemplate,
EuiFlexItem,
EuiTabbedContent,
EuiFlexGroup,
EuiPopover,
EuiButtonIcon,
Expand All @@ -30,6 +30,7 @@ import { useKibana } from '../../hooks/use_kibana';
import { ConnectionDetails } from '../connection_details/connection_details';
import { QuickStats } from '../quick_stats/quick_stats';
import { useIndexMapping } from '../../hooks/api/use_index_mappings';
import { IndexDocuments } from '../index_documents/index_documents';
import { DeleteIndexModal } from './delete_index_modal';
import { IndexloadingError } from './details_page_loading_error';

Expand Down Expand Up @@ -157,31 +158,47 @@ export const SearchIndexDetailsPage = () => {
</EuiFlexGroup>,
]}
/>
<EuiSpacer size="l" />

{isShowingDeleteModal && (
<DeleteIndexModal
onCancel={() => setShowDeleteIndexModal(!isShowingDeleteModal)}
indexName={indexName}
navigateToIndexListPage={navigateToIndexListPage}
/>
)}
<EuiPageTemplate.Section grow={false}>
<EuiFlexGroup>
<EuiFlexGroup direction="column">
<EuiFlexItem>
<ConnectionDetails />
<EuiFlexGroup>
<EuiFlexItem>
<ConnectionDetails />
</EuiFlexItem>
<EuiFlexItem>{/* TODO: API KEY */}</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup>
<QuickStats index={index} mappings={mappings} />
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexItem>
<EuiTabbedContent
tabs={[
{
id: 'data',
name: i18n.translate('xpack.searchIndices.documentsTabLabel', {
defaultMessage: 'Data',
}),
content: <IndexDocuments indexName={indexName} />,
},
]}
/>
</EuiFlexItem>
</EuiFlexItem>
<EuiFlexItem>{/* TODO: API KEY */}</EuiFlexItem>
</EuiFlexGroup>

<EuiSpacer size="l" />

<EuiFlexGroup>
<QuickStats index={index} mappings={mappings} />
</EuiFlexGroup>
</EuiPageTemplate.Section>
</>
)}
{isShowingDeleteModal && (
<DeleteIndexModal
onCancel={() => setShowDeleteIndexModal(!isShowingDeleteModal)}
indexName={indexName}
navigateToIndexListPage={navigateToIndexListPage}
/>
)}
{embeddableConsole}
</EuiPageTemplate>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* 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 { Pagination } from '@elastic/eui';
import { SearchHit } from '@kbn/es-types';
import { pageToPagination, Paginate } from '@kbn/search-index-documents';
import { useQuery } from '@tanstack/react-query';
import { useKibana } from '../use_kibana';

interface IndexDocuments {
meta: Pagination;
results: Paginate<SearchHit>;
}
const DEFAULT_PAGINATION = {
from: 0,
has_more_hits_than_total: false,
size: 10,
total: 0,
};
const pollingInterval = 5 * 1000;
export const useIndexDocumentSearch = (
indexName: string,
pagination: Omit<Pagination, 'totalItemCount'>,
searchQuery?: string
) => {
const {
services: { http },
} = useKibana();
const response = useQuery({
queryKey: ['fetchIndexDocuments', pagination, searchQuery],
refetchInterval: pollingInterval,
refetchIntervalInBackground: true,
refetchOnWindowFocus: 'always',
queryFn: async () =>
http.post<IndexDocuments>(`/internal/serverless_search/indices/${indexName}/search`, {
body: JSON.stringify({
searchQuery,
}),
query: {
page: pagination.pageIndex,
size: pagination.pageSize,
},
}),
});
return {
...response,
meta: pageToPagination(response?.data?.results?._meta?.page ?? DEFAULT_PAGINATION),
};
};
2 changes: 2 additions & 0 deletions x-pack/plugins/search_indices/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"@kbn/index-management-shared-types",
"@kbn/try-in-console",
"@kbn/cloud-plugin",
"@kbn/search-index-documents",
"@kbn/es-types",
],
"exclude": [
"target/**/*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ export function SvlSearchIndexDetailPageProvider({ getService }: FtrProviderCont
await testSubjects.missingOrFail('setupAISearchButton', { timeout: 2000 });
},

async expectAddDocumentCodeExamples() {
await testSubjects.existOrFail('SearchIndicesAddDocumentsCode', { timeout: 2000 });
},

async expectHasIndexDocuments() {
await retry.try(async () => {
await testSubjects.existOrFail('search-index-documents-result', { timeout: 2000 });
});
},

async expectMoreOptionsActionButtonExists() {
await testSubjects.existOrFail('moreOptionsActionButton');
},
Expand Down
Loading

0 comments on commit d188b65

Please sign in to comment.