mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Enterprise Search] Show warnings when an index in an engine has unknown
health (#150627)
## Summary - Alert icon and warning colors for indices count on overview page - Warning callout on indices page - Unknown index row rendering changes - `N/A` document count - No view index action - Disabled link for view index Open question: Is there a good way to render a row as "disabled?" <img width="1194" alt="Screenshot 2023-02-08 at 2 30 57 PM" src="https://user-images.githubusercontent.com/1699281/217632438-249d77b3-5cbe-492c-af2c-d7f9a66b298b.png"> <img width="1000" alt="image" src="https://user-images.githubusercontent.com/1699281/217635524-4465a062-3fee-491c-b201-d87ab5ed5160.png"> ### Checklist Delete any items that are not applicable to this PR. - [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) - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [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) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
parent
7d3b0c369b
commit
6ad4a44917
4 changed files with 492 additions and 41 deletions
|
@ -10,13 +10,16 @@ import React, { useState } from 'react';
|
|||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import {
|
||||
EuiTableActionsColumnType,
|
||||
EuiBasicTableColumn,
|
||||
EuiButton,
|
||||
EuiCallOut,
|
||||
EuiConfirmModal,
|
||||
EuiIcon,
|
||||
EuiInMemoryTable,
|
||||
EuiSpacer,
|
||||
EuiTableActionsColumnType,
|
||||
EuiText,
|
||||
useEuiBackgroundColor,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
|
@ -39,6 +42,7 @@ import { AddIndicesFlyout } from './add_indices_flyout';
|
|||
import { EngineIndicesLogic } from './engine_indices_logic';
|
||||
|
||||
export const EngineIndices: React.FC = () => {
|
||||
const subduedBackground = useEuiBackgroundColor('subdued');
|
||||
const { sendEnterpriseSearchTelemetry } = useActions(TelemetryLogic);
|
||||
const { engineData, engineName, isLoadingEngine, addIndicesFlyoutOpen } =
|
||||
useValues(EngineIndicesLogic);
|
||||
|
@ -50,6 +54,8 @@ export const EngineIndices: React.FC = () => {
|
|||
if (!engineData) return null;
|
||||
const { indices } = engineData;
|
||||
|
||||
const hasUnknownIndices = indices.some(({ health }) => health === 'unknown');
|
||||
|
||||
const removeIndexAction: EuiTableActionsColumnType<EnterpriseSearchEngineIndex>['actions'][0] = {
|
||||
color: 'danger',
|
||||
'data-test-subj': 'engine-remove-index-btn',
|
||||
|
@ -77,21 +83,24 @@ export const EngineIndices: React.FC = () => {
|
|||
},
|
||||
type: 'icon',
|
||||
};
|
||||
|
||||
const columns: Array<EuiBasicTableColumn<EnterpriseSearchEngineIndex>> = [
|
||||
{
|
||||
field: 'name',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.engine.indices.name.columnTitle', {
|
||||
defaultMessage: 'Index name',
|
||||
}),
|
||||
render: (name: string) => (
|
||||
<EuiLinkTo
|
||||
data-test-subj="engine-index-link"
|
||||
to={generateEncodedPath(SEARCH_INDEX_PATH, { indexName: name })}
|
||||
>
|
||||
{name}
|
||||
</EuiLinkTo>
|
||||
),
|
||||
sortable: true,
|
||||
render: ({ health, name }: EnterpriseSearchEngineIndex) =>
|
||||
health === 'unknown' ? (
|
||||
name
|
||||
) : (
|
||||
<EuiLinkTo
|
||||
data-test-subj="engine-index-link"
|
||||
to={generateEncodedPath(SEARCH_INDEX_PATH, { indexName: name })}
|
||||
>
|
||||
{name}
|
||||
</EuiLinkTo>
|
||||
),
|
||||
sortable: ({ name }: EnterpriseSearchEngineIndex) => name,
|
||||
truncateText: true,
|
||||
width: '40%',
|
||||
},
|
||||
|
@ -115,6 +124,13 @@ export const EngineIndices: React.FC = () => {
|
|||
name: i18n.translate('xpack.enterpriseSearch.content.engine.indices.docsCount.columnTitle', {
|
||||
defaultMessage: 'Docs count',
|
||||
}),
|
||||
render: (count: number | null) =>
|
||||
count === null
|
||||
? i18n.translate(
|
||||
'xpack.enterpriseSearch.content.engine.indices.docsCount.notAvailableLabel',
|
||||
{ defaultMessage: 'N/A' }
|
||||
)
|
||||
: count,
|
||||
sortable: true,
|
||||
truncateText: true,
|
||||
width: '15%',
|
||||
|
@ -136,6 +152,7 @@ export const EngineIndices: React.FC = () => {
|
|||
{
|
||||
actions: [
|
||||
{
|
||||
available: (index) => index.health !== 'unknown',
|
||||
'data-test-subj': 'engine-view-index-btn',
|
||||
description: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.engine.indices.actions.viewIndex.title',
|
||||
|
@ -197,9 +214,39 @@ export const EngineIndices: React.FC = () => {
|
|||
engineName={engineName}
|
||||
>
|
||||
<>
|
||||
{hasUnknownIndices && (
|
||||
<>
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
iconType="alert"
|
||||
title={i18n.translate(
|
||||
'xpack.enterpriseSearch.content.engine.indices.unknownIndicesCallout.title',
|
||||
{ defaultMessage: 'Some of your indices are unavailable.' }
|
||||
)}
|
||||
>
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.engine.indices.unknownIndicesCallout.description',
|
||||
{
|
||||
defaultMessage:
|
||||
'Some data might be unreachable from this engine. Check for any pending operations or errors on affected indices, or remove those that should no longer be used by this engine.',
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer />
|
||||
</>
|
||||
)}
|
||||
<EuiInMemoryTable
|
||||
items={indices}
|
||||
columns={columns}
|
||||
rowProps={(index: EnterpriseSearchEngineIndex) => {
|
||||
if (index.health === 'unknown') {
|
||||
return { style: { backgroundColor: subduedBackground } };
|
||||
}
|
||||
|
||||
return {};
|
||||
}}
|
||||
search={{
|
||||
box: {
|
||||
incremental: true,
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from 'react';
|
|||
|
||||
import { useValues } from 'kea';
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPanel, EuiStat } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPanel, EuiStat, useEuiTheme } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { generateEncodedPath } from '../../../shared/encode_path_params';
|
||||
|
@ -21,8 +21,17 @@ import { EngineOverviewLogic } from './engine_overview_logic';
|
|||
import { EngineViewHeaderActions } from './engine_view_header_actions';
|
||||
|
||||
export const EngineOverview: React.FC = () => {
|
||||
const { engineName, indicesCount, documentsCount, fieldsCount, isLoadingEngine } =
|
||||
useValues(EngineOverviewLogic);
|
||||
const {
|
||||
euiTheme: { colors: colors },
|
||||
} = useEuiTheme();
|
||||
const {
|
||||
documentsCount,
|
||||
engineName,
|
||||
fieldsCount,
|
||||
hasUnknownIndices,
|
||||
indicesCount,
|
||||
isLoadingEngine,
|
||||
} = useValues(EngineOverviewLogic);
|
||||
|
||||
return (
|
||||
<EnterpriseSearchEnginesPageTemplate
|
||||
|
@ -49,7 +58,11 @@ export const EngineOverview: React.FC = () => {
|
|||
color="text"
|
||||
>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiIcon size="xxl" type="visTable" color="#98A2B3" />
|
||||
{hasUnknownIndices ? (
|
||||
<EuiIcon size="xxl" type="alert" color={colors.warning} />
|
||||
) : (
|
||||
<EuiIcon size="xxl" type="visTable" color={colors.mediumShade} />
|
||||
)}
|
||||
<EuiStat
|
||||
titleSize="l"
|
||||
isLoading={isLoadingEngine}
|
||||
|
@ -58,14 +71,14 @@ export const EngineOverview: React.FC = () => {
|
|||
'xpack.enterpriseSearch.content.engine.overview.indicesDescription',
|
||||
{ defaultMessage: 'Indices' }
|
||||
)}
|
||||
titleColor="primary"
|
||||
titleColor={hasUnknownIndices ? colors.warningText : 'primary'}
|
||||
/>
|
||||
</EuiFlexGroup>
|
||||
</EuiLinkTo>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiIcon size="xxl" type="documents" color="#98A2B3" />
|
||||
<EuiIcon size="xxl" type="documents" color={colors.mediumShade} />
|
||||
<EuiStat
|
||||
titleSize="l"
|
||||
isLoading={isLoadingEngine}
|
||||
|
@ -87,7 +100,7 @@ export const EngineOverview: React.FC = () => {
|
|||
color="text"
|
||||
>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiIcon size="xxl" type="documents" color="#98A2B3" />
|
||||
<EuiIcon size="xxl" type="documents" color={colors.mediumShade} />
|
||||
<EuiStat
|
||||
titleSize="l"
|
||||
isLoading={false}
|
||||
|
|
|
@ -8,8 +8,17 @@
|
|||
import { LogicMounter } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import { Status } from '../../../../../common/types/api';
|
||||
import { EnterpriseSearchEngineIndex } from '../../../../../common/types/engines';
|
||||
|
||||
import { EngineOverviewLogic, EngineOverviewValues } from './engine_overview_logic';
|
||||
import {
|
||||
EngineOverviewLogic,
|
||||
EngineOverviewValues,
|
||||
selectDocumentsCount,
|
||||
selectFieldsCount,
|
||||
selectHasUnknownIndices,
|
||||
selectIndices,
|
||||
selectIndicesCount,
|
||||
} from './engine_overview_logic';
|
||||
|
||||
const DEFAULT_VALUES: EngineOverviewValues = {
|
||||
documentsCount: 0,
|
||||
|
@ -18,6 +27,7 @@ const DEFAULT_VALUES: EngineOverviewValues = {
|
|||
engineFieldCapabilitiesData: undefined,
|
||||
engineName: '',
|
||||
fieldsCount: 0,
|
||||
hasUnknownIndices: false,
|
||||
indices: [],
|
||||
indicesCount: 0,
|
||||
isLoadingEngine: true,
|
||||
|
@ -36,4 +46,379 @@ describe('EngineOverviewLogic', () => {
|
|||
it('has expected default values', () => {
|
||||
expect(EngineOverviewLogic.values).toEqual(DEFAULT_VALUES);
|
||||
});
|
||||
|
||||
describe('listeners', () => {
|
||||
describe('setEngineName', () => {
|
||||
it('refetches the engine field capabilities', () => {
|
||||
jest.spyOn(EngineOverviewLogic.actions, 'fetchEngineFieldCapabilities');
|
||||
|
||||
EngineOverviewLogic.actions.setEngineName('foobar');
|
||||
|
||||
expect(EngineOverviewLogic.actions.fetchEngineFieldCapabilities).toHaveBeenCalledTimes(1);
|
||||
expect(EngineOverviewLogic.actions.fetchEngineFieldCapabilities).toHaveBeenCalledWith({
|
||||
engineName: 'foobar',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectors', () => {
|
||||
describe('indices', () => {
|
||||
it('is defined', () => {
|
||||
expect(selectIndices).toBeDefined();
|
||||
});
|
||||
it('returns an empty array before engineData is loaded', () => {
|
||||
expect(selectIndices(undefined)).toEqual([]);
|
||||
});
|
||||
it('returns the array of indices', () => {
|
||||
const indices = [
|
||||
{
|
||||
count: 10,
|
||||
health: 'green',
|
||||
name: 'index-001',
|
||||
source: 'api',
|
||||
},
|
||||
{
|
||||
count: 10,
|
||||
health: 'green',
|
||||
name: 'index-002',
|
||||
source: 'api',
|
||||
},
|
||||
];
|
||||
const engineData = {
|
||||
created: '2023-02-07T19:16:43Z',
|
||||
indices,
|
||||
name: 'foo-engine',
|
||||
updated: '2023-02-07T19:16:43Z',
|
||||
} as EngineOverviewValues['engineData'];
|
||||
expect(selectIndices(engineData)).toBe(indices);
|
||||
});
|
||||
});
|
||||
describe('indicesCount', () => {
|
||||
it('is defined', () => {
|
||||
expect(selectIndicesCount).toBeDefined();
|
||||
});
|
||||
it('returns the number of indices', () => {
|
||||
const noIndices: EnterpriseSearchEngineIndex[] = [];
|
||||
const oneIndex = [
|
||||
{ count: 23, health: 'unknown', name: 'index-001', source: 'api' },
|
||||
] as EnterpriseSearchEngineIndex[];
|
||||
const twoIndices = [
|
||||
{ count: 23, health: 'unknown', name: 'index-001', source: 'api' },
|
||||
{ count: 92, health: 'unknown', name: 'index-002', source: 'api' },
|
||||
] as EnterpriseSearchEngineIndex[];
|
||||
|
||||
expect(selectIndicesCount(noIndices)).toBe(0);
|
||||
expect(selectIndicesCount(oneIndex)).toBe(1);
|
||||
expect(selectIndicesCount(twoIndices)).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasUnknownIndices', () => {
|
||||
it('is defined', () => {
|
||||
expect(selectHasUnknownIndices).toBeDefined();
|
||||
});
|
||||
describe('no indices', () => {
|
||||
const indices: EnterpriseSearchEngineIndex[] = [];
|
||||
it('returns false', () => {
|
||||
expect(selectHasUnknownIndices(indices)).toBe(false);
|
||||
});
|
||||
});
|
||||
describe('all indices unknown', () => {
|
||||
const indices = [
|
||||
{
|
||||
count: 12,
|
||||
health: 'unknown',
|
||||
name: 'index-001',
|
||||
source: 'api',
|
||||
},
|
||||
{
|
||||
count: 34,
|
||||
health: 'unknown',
|
||||
name: 'index-002',
|
||||
source: 'crawler',
|
||||
},
|
||||
{
|
||||
count: 56,
|
||||
health: 'unknown',
|
||||
name: 'index-003',
|
||||
source: 'api',
|
||||
},
|
||||
] as EnterpriseSearchEngineIndex[];
|
||||
it('returns true', () => {
|
||||
expect(selectHasUnknownIndices(indices)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('one index unknown', () => {
|
||||
const indices = [
|
||||
{
|
||||
count: 12,
|
||||
health: 'unknown',
|
||||
name: 'index-001',
|
||||
source: 'api',
|
||||
},
|
||||
{
|
||||
count: 34,
|
||||
health: 'yellow',
|
||||
name: 'index-002',
|
||||
source: 'crawler',
|
||||
},
|
||||
{
|
||||
count: 56,
|
||||
health: 'green',
|
||||
name: 'index-003',
|
||||
source: 'api',
|
||||
},
|
||||
] as EnterpriseSearchEngineIndex[];
|
||||
it('returns true', () => {
|
||||
expect(selectHasUnknownIndices(indices)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('multiple but not all indices unknown', () => {
|
||||
const indices = [
|
||||
{
|
||||
count: 12,
|
||||
health: 'unknown',
|
||||
name: 'index-001',
|
||||
source: 'api',
|
||||
},
|
||||
{
|
||||
count: 34,
|
||||
health: 'yellow',
|
||||
name: 'index-002',
|
||||
source: 'crawler',
|
||||
},
|
||||
{
|
||||
count: 56,
|
||||
health: 'unknown',
|
||||
name: 'index-003',
|
||||
source: 'api',
|
||||
},
|
||||
] as EnterpriseSearchEngineIndex[];
|
||||
it('returns true', () => {
|
||||
expect(selectHasUnknownIndices(indices)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('no indices unknown', () => {
|
||||
const indices = [
|
||||
{
|
||||
count: 12,
|
||||
health: 'green',
|
||||
name: 'index-001',
|
||||
source: 'api',
|
||||
},
|
||||
{
|
||||
count: 34,
|
||||
health: 'yellow',
|
||||
name: 'index-002',
|
||||
source: 'crawler',
|
||||
},
|
||||
{
|
||||
count: 56,
|
||||
health: 'green',
|
||||
name: 'index-003',
|
||||
source: 'api',
|
||||
},
|
||||
] as EnterpriseSearchEngineIndex[];
|
||||
it('returns false', () => {
|
||||
expect(selectHasUnknownIndices(indices)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('documentsCount', () => {
|
||||
it('is defined', () => {
|
||||
expect(selectDocumentsCount).toBeDefined();
|
||||
});
|
||||
|
||||
it('returns 0 for no indices', () => {
|
||||
expect(selectDocumentsCount([])).toBe(0);
|
||||
});
|
||||
|
||||
it('returns the `count` for a single index', () => {
|
||||
expect(
|
||||
selectDocumentsCount([
|
||||
{
|
||||
count: 23,
|
||||
health: 'green',
|
||||
name: 'index-001',
|
||||
source: 'crawler',
|
||||
},
|
||||
] as EnterpriseSearchEngineIndex[])
|
||||
).toBe(23);
|
||||
});
|
||||
|
||||
it('returns the sum of all `count`', () => {
|
||||
expect(
|
||||
selectDocumentsCount([
|
||||
{
|
||||
count: 23,
|
||||
health: 'green',
|
||||
name: 'index-001',
|
||||
source: 'crawler',
|
||||
},
|
||||
{
|
||||
count: 45,
|
||||
health: 'green',
|
||||
name: 'index-002',
|
||||
source: 'crawler',
|
||||
},
|
||||
] as EnterpriseSearchEngineIndex[])
|
||||
).toBe(68);
|
||||
});
|
||||
|
||||
it('does not count indices without a `count`', () => {
|
||||
expect(
|
||||
selectDocumentsCount([
|
||||
{
|
||||
count: 23,
|
||||
health: 'green',
|
||||
name: 'index-001',
|
||||
source: 'crawler',
|
||||
},
|
||||
{
|
||||
count: null,
|
||||
health: 'unknown',
|
||||
name: 'index-002',
|
||||
source: 'crawler',
|
||||
},
|
||||
{
|
||||
count: 45,
|
||||
health: 'green',
|
||||
name: 'index-002',
|
||||
source: 'crawler',
|
||||
},
|
||||
] as EnterpriseSearchEngineIndex[])
|
||||
).toBe(68);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fieldsCount', () => {
|
||||
it('is defined', () => {
|
||||
expect(selectFieldsCount).toBeDefined();
|
||||
});
|
||||
it('counts the fields from the field capabilities', () => {
|
||||
const fieldCapabilities = {
|
||||
created: '2023-02-07T19:16:43Z',
|
||||
field_capabilities: {
|
||||
fields: {
|
||||
age: {
|
||||
integer: {
|
||||
aggregatable: true,
|
||||
metadata_field: false,
|
||||
searchable: true,
|
||||
type: 'integer',
|
||||
},
|
||||
},
|
||||
color: {
|
||||
keyword: {
|
||||
aggregatable: true,
|
||||
metadata_field: false,
|
||||
searchable: true,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
name: {
|
||||
text: {
|
||||
aggregatable: false,
|
||||
metadata_field: false,
|
||||
searchable: true,
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
indices: ['index-001', 'index-002'],
|
||||
},
|
||||
name: 'engine-001',
|
||||
updated: '2023-02-07T19:16:43Z',
|
||||
};
|
||||
expect(selectFieldsCount(fieldCapabilities)).toBe(3);
|
||||
});
|
||||
|
||||
it('excludes metadata fields from the count', () => {
|
||||
const fieldCapabilities = {
|
||||
created: '2023-02-07T19:16:43Z',
|
||||
field_capabilities: {
|
||||
fields: {
|
||||
_doc_count: {
|
||||
integer: {
|
||||
aggregatable: false,
|
||||
metadata_field: true,
|
||||
searchable: false,
|
||||
type: 'integer',
|
||||
},
|
||||
},
|
||||
_id: {
|
||||
_id: {
|
||||
aggregatable: false,
|
||||
metadata_field: true,
|
||||
searchable: true,
|
||||
type: '_id',
|
||||
},
|
||||
},
|
||||
_index: {
|
||||
_index: {
|
||||
aggregatable: true,
|
||||
metadata_field: true,
|
||||
searchable: true,
|
||||
type: '_index',
|
||||
},
|
||||
},
|
||||
_source: {
|
||||
_source: {
|
||||
aggregatable: false,
|
||||
metadata_field: true,
|
||||
searchable: false,
|
||||
type: '_source',
|
||||
},
|
||||
},
|
||||
_version: {
|
||||
_version: {
|
||||
aggregatable: true,
|
||||
metadata_field: true,
|
||||
searchable: false,
|
||||
type: '_version',
|
||||
},
|
||||
},
|
||||
age: {
|
||||
integer: {
|
||||
aggregatable: true,
|
||||
metadata_field: false,
|
||||
searchable: true,
|
||||
type: 'integer',
|
||||
},
|
||||
},
|
||||
color: {
|
||||
keyword: {
|
||||
aggregatable: true,
|
||||
metadata_field: false,
|
||||
searchable: true,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
name: {
|
||||
text: {
|
||||
aggregatable: false,
|
||||
metadata_field: false,
|
||||
searchable: true,
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
indices: ['index-001', 'index-002'],
|
||||
},
|
||||
name: 'foo-engine',
|
||||
updated: '2023-02-07T19:16:43Z',
|
||||
};
|
||||
expect(selectFieldsCount(fieldCapabilities)).toBe(3);
|
||||
});
|
||||
|
||||
it('returns 0 when field capability data is not available', () => {
|
||||
expect(selectFieldsCount(undefined)).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import { EngineViewLogic } from './engine_view_logic';
|
|||
|
||||
export interface EngineOverviewActions {
|
||||
fetchEngineFieldCapabilities: typeof FetchEngineFieldCapabilitiesApiLogic.actions.makeRequest;
|
||||
setEngineName: typeof EngineNameLogic.actions.setEngineName;
|
||||
}
|
||||
export interface EngineOverviewValues {
|
||||
documentsCount: number;
|
||||
|
@ -25,11 +26,30 @@ export interface EngineOverviewValues {
|
|||
engineFieldCapabilitiesData: typeof FetchEngineFieldCapabilitiesApiLogic.values.data;
|
||||
engineName: typeof EngineNameLogic.values.engineName;
|
||||
fieldsCount: number;
|
||||
hasUnknownIndices: boolean;
|
||||
indices: EnterpriseSearchEngineIndex[];
|
||||
indicesCount: number;
|
||||
isLoadingEngine: typeof EngineViewLogic.values.isLoadingEngine;
|
||||
}
|
||||
|
||||
export const selectIndices = (engineData: EngineOverviewValues['engineData']) =>
|
||||
engineData?.indices ?? [];
|
||||
|
||||
export const selectIndicesCount = (indices: EngineOverviewValues['indices']) => indices.length;
|
||||
|
||||
export const selectHasUnknownIndices = (indices: EngineOverviewValues['indices']) =>
|
||||
indices.some(({ health }) => health === 'unknown');
|
||||
|
||||
export const selectDocumentsCount = (indices: EngineOverviewValues['indices']) =>
|
||||
indices.reduce((sum, { count }) => sum + count, 0);
|
||||
|
||||
export const selectFieldsCount = (
|
||||
engineFieldCapabilitiesData: EngineOverviewValues['engineFieldCapabilitiesData']
|
||||
) =>
|
||||
Object.values(engineFieldCapabilitiesData?.field_capabilities?.fields ?? {}).filter(
|
||||
(value) => !Object.values(value).some((field) => !!field.metadata_field)
|
||||
).length;
|
||||
|
||||
export const EngineOverviewLogic = kea<MakeLogicType<EngineOverviewValues, EngineOverviewActions>>({
|
||||
actions: {},
|
||||
connect: {
|
||||
|
@ -57,33 +77,19 @@ export const EngineOverviewLogic = kea<MakeLogicType<EngineOverviewValues, Engin
|
|||
}
|
||||
},
|
||||
}),
|
||||
listeners: ({ actions }) => ({
|
||||
setEngineName: ({ engineName }) => {
|
||||
listeners: ({ actions, values }) => ({
|
||||
setEngineName: () => {
|
||||
const { engineName } = values;
|
||||
actions.fetchEngineFieldCapabilities({ engineName });
|
||||
},
|
||||
}),
|
||||
path: ['enterprise_search', 'content', 'engine_overview_logic'],
|
||||
reducers: {},
|
||||
selectors: ({ selectors }) => ({
|
||||
documentsCount: [
|
||||
() => [selectors.indices],
|
||||
(indices: EngineOverviewValues['indices']) =>
|
||||
indices.reduce((sum, { count }) => sum + count, 0),
|
||||
],
|
||||
fieldsCount: [
|
||||
() => [selectors.engineFieldCapabilitiesData],
|
||||
(engineFieldCapabilitiesData: EngineOverviewValues['engineFieldCapabilitiesData']) =>
|
||||
Object.values(engineFieldCapabilitiesData?.field_capabilities?.fields ?? {}).filter(
|
||||
(value) => !Object.values(value).some((field) => !!field.metadata_field)
|
||||
).length,
|
||||
],
|
||||
indices: [
|
||||
() => [selectors.engineData],
|
||||
(engineData: EngineOverviewValues['engineData']) => engineData?.indices ?? [],
|
||||
],
|
||||
indicesCount: [
|
||||
() => [selectors.indices],
|
||||
(indices: EngineOverviewValues['indices']) => indices.length,
|
||||
],
|
||||
documentsCount: [() => [selectors.indices], selectDocumentsCount],
|
||||
fieldsCount: [() => [selectors.engineFieldCapabilitiesData], selectFieldsCount],
|
||||
hasUnknownIndices: [() => [selectors.indices], selectHasUnknownIndices],
|
||||
indices: [() => [selectors.engineData], selectIndices],
|
||||
indicesCount: [() => [selectors.indices], selectIndicesCount],
|
||||
}),
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue