Gracefully handle 404s for documents and mappings (#167101)

## Summary

![Screenshot 2023-09-25 at 17 09
34](eb040d9c-6521-4a05-a57f-3e9d15b2db0a)
![Screenshot 2023-09-25 at 17 09
42](cbc41a65-697b-4011-968b-fb6660835d28)


### Checklist


- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ] [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] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Liam Thompson <32779855+leemthompo@users.noreply.github.com>
This commit is contained in:
Efe Gürkan YALAMAN 2023-09-26 18:22:00 +02:00 committed by GitHub
parent df3dd04707
commit 6cf246b505
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 7 deletions

View file

@ -10,6 +10,7 @@ import React, { useEffect, useState, ChangeEvent } from 'react';
import { useActions, useValues } from 'kea'; import { useActions, useValues } from 'kea';
import { import {
EuiCallOut,
EuiFieldSearch, EuiFieldSearch,
EuiFlexGroup, EuiFlexGroup,
EuiFlexItem, EuiFlexItem,
@ -74,7 +75,7 @@ export const SearchIndexDocuments: React.FC = () => {
const { makeRequest: getDocuments } = useActions(documentLogic); const { makeRequest: getDocuments } = useActions(documentLogic);
const { makeRequest: getMappings } = useActions(mappingLogic); const { makeRequest: getMappings } = useActions(mappingLogic);
const { data, status } = useValues(documentLogic); const { data, status, error } = useValues(documentLogic);
const { data: mappingData, status: mappingStatus } = useValues(mappingLogic); const { data: mappingData, status: mappingStatus } = useValues(mappingLogic);
const docs = data?.results?.hits.hits ?? []; const docs = data?.results?.hits.hits ?? [];
@ -84,6 +85,8 @@ export const SearchIndexDocuments: React.FC = () => {
const shouldShowAccessControlSwitcher = const shouldShowAccessControlSwitcher =
hasDocumentLevelSecurityFeature && productFeatures.hasDocumentLevelSecurityEnabled; hasDocumentLevelSecurityFeature && productFeatures.hasDocumentLevelSecurityEnabled;
const isAccessControlIndexNotFound =
shouldShowAccessControlSwitcher && error?.body?.statusCode === 404;
useEffect(() => { useEffect(() => {
getDocuments({ getDocuments({
@ -141,11 +144,29 @@ export const SearchIndexDocuments: React.FC = () => {
</EuiFlexGroup> </EuiFlexGroup>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem>
{docs.length === 0 && {isAccessControlIndexNotFound && (
<EuiCallOut
size="m"
title={i18n.translate(
'xpack.enterpriseSearch.content.searchIndex.documents.noIndex.title',
{ defaultMessage: 'Access Control Index not found' }
)}
iconType="iInCircle"
>
<p>
{i18n.translate('xpack.enterpriseSearch.content.searchIndex.documents.noIndex', {
defaultMessage:
"An Access Control Index won't be created until you enable document-level security and run your first access control sync.",
})}
</p>
</EuiCallOut>
)}
{!isAccessControlIndexNotFound &&
docs.length === 0 &&
i18n.translate('xpack.enterpriseSearch.content.searchIndex.documents.noMappings', { i18n.translate('xpack.enterpriseSearch.content.searchIndex.documents.noMappings', {
defaultMessage: 'No documents found for index', defaultMessage: 'No documents found for index',
})} })}
{docs.length > 0 && ( {!isAccessControlIndexNotFound && docs.length > 0 && (
<DocumentList <DocumentList
docs={docs} docs={docs}
docsPerPage={pagination.pageSize} docsPerPage={pagination.pageSize}

View file

@ -10,6 +10,7 @@ import React, { useEffect, useState } from 'react';
import { useActions, useValues } from 'kea'; import { useActions, useValues } from 'kea';
import { import {
EuiCallOut,
EuiCode, EuiCode,
EuiCodeBlock, EuiCodeBlock,
EuiFlexGroup, EuiFlexGroup,
@ -55,9 +56,12 @@ export const SearchIndexIndexMappings: React.FC = () => {
? indexName ? indexName
: stripSearchPrefix(indexName, CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX); : stripSearchPrefix(indexName, CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX);
const { makeRequest: makeMappingRequest } = useActions(mappingsWithPropsApiLogic(indexToShow)); const { makeRequest: makeMappingRequest } = useActions(mappingsWithPropsApiLogic(indexToShow));
const { data: mappingData } = useValues(mappingsWithPropsApiLogic(indexToShow)); const { data: mappingData, error } = useValues(mappingsWithPropsApiLogic(indexToShow));
const shouldShowAccessControlSwitch = const shouldShowAccessControlSwitch =
hasDocumentLevelSecurityFeature && productFeatures.hasDocumentLevelSecurityEnabled; hasDocumentLevelSecurityFeature && productFeatures.hasDocumentLevelSecurityEnabled;
const isAccessControlIndexNotFound =
shouldShowAccessControlSwitch && error?.body?.statusCode === 404;
useEffect(() => { useEffect(() => {
makeMappingRequest({ indexName: indexToShow }); makeMappingRequest({ indexName: indexToShow });
}, [indexToShow, indexName]); }, [indexToShow, indexName]);
@ -77,9 +81,27 @@ export const SearchIndexIndexMappings: React.FC = () => {
</EuiFlexItem> </EuiFlexItem>
)} )}
<EuiFlexItem grow> <EuiFlexItem grow>
<EuiCodeBlock language="json" isCopyable> {isAccessControlIndexNotFound ? (
{JSON.stringify(mappingData, null, 2)} <EuiCallOut
</EuiCodeBlock> size="m"
title={i18n.translate(
'xpack.enterpriseSearch.content.searchIndex.mappings.noIndex.title',
{ defaultMessage: 'Access Control Index not found' }
)}
iconType="iInCircle"
>
<p>
{i18n.translate('xpack.enterpriseSearch.content.searchIndex.mappings.noIndex', {
defaultMessage:
"An Access Control Index won't be created until you enable document-level security and run your first access control sync.",
})}
</p>
</EuiCallOut>
) : (
<EuiCodeBlock language="json" isCopyable>
{JSON.stringify(mappingData, null, 2)}
</EuiCodeBlock>
)}
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
</EuiFlexItem> </EuiFlexItem>