mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Enterprise Search] Engines list UI page - part 1 (#147399)
## Summary Engine list UI page - part 1 This PR includes, 1. Initial layout for Engine list UI page 2. Search bar to search via engine names or indices 3. Initial support for pagination 4. Test cases 5. Fetch engines list from mocked values <img width="1706" alt="Screen Shot 2022-12-12 at 5 35 04 PM" src="https://user-images.githubusercontent.com/55930906/207169828-6713f836-0ed2-47ad-952e-9bbab6ac8f31.png"> TODO(s) (as per most recent UI [design](https://github.com/elastic/enterprise-search-team/issues/3446#issuecomment-1341890967) ) Will create separate PR to handle below scenarios. - Incorporate Flyout panel to list all the indices - Change to actual Backend API call to fetch engine list - Add Fully functional Paginations - Add index health, Documents count, Last updated date when backend API is ready - Update test cases ### 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) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### 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
1b3769c86b
commit
8be155d295
8 changed files with 595 additions and 3 deletions
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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 { createApiLogic } from '../../../shared/api_logic/create_api_logic';
|
||||
|
||||
import { EngineListDetails, Meta } from '../../components/engines/types';
|
||||
|
||||
export interface EnginesListAPIResponse {
|
||||
results: EngineListDetails[];
|
||||
meta: Meta;
|
||||
searchQuery?: string;
|
||||
}
|
||||
export interface EnginesListAPIArguments {
|
||||
meta: Meta;
|
||||
searchQuery?: string;
|
||||
}
|
||||
|
||||
const metaValue: Meta = {
|
||||
from: 1,
|
||||
size: 3,
|
||||
total: 5,
|
||||
};
|
||||
// These are mocked values. To be changed as per the latest requirement when Backend API is ready
|
||||
export const mockedEngines: EnginesListAPIResponse[] = [
|
||||
{
|
||||
meta: metaValue,
|
||||
results: [
|
||||
{
|
||||
name: 'engine-name-1',
|
||||
indices: ['index-18', 'index-23'],
|
||||
last_updated: '21 March 2021',
|
||||
document_count: 18,
|
||||
},
|
||||
{
|
||||
name: 'engine-name-2',
|
||||
indices: ['index-180', 'index-230', 'index-8', 'index-2'],
|
||||
last_updated: '10 Jul 2018',
|
||||
document_count: 10,
|
||||
},
|
||||
|
||||
{
|
||||
name: 'engine-name-3',
|
||||
indices: ['index-2', 'index-3'],
|
||||
last_updated: '21 December 2022',
|
||||
document_count: 8,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
export const fetchEngines = async () => {
|
||||
// TODO replace with http call when backend is ready
|
||||
return mockedEngines[0];
|
||||
};
|
||||
|
||||
export const FetchEnginesAPILogic = createApiLogic(['content', 'engines_api_logic'], fetchEngines);
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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 { CriteriaWithPagination, EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedNumber } from '@kbn/i18n-react';
|
||||
|
||||
import { DELETE_BUTTON_LABEL, MANAGE_BUTTON_LABEL } from '../../../../../shared/constants';
|
||||
|
||||
import { convertMetaToPagination, EngineListDetails, Meta } from '../../types';
|
||||
|
||||
// add health status
|
||||
interface EnginesListTableProps {
|
||||
enginesList: EngineListDetails[];
|
||||
loading: boolean;
|
||||
meta: Meta;
|
||||
isLoading?: boolean;
|
||||
onChange: (criteria: CriteriaWithPagination<EngineListDetails>) => void;
|
||||
}
|
||||
export const EnginesListTable: React.FC<EnginesListTableProps> = ({
|
||||
enginesList,
|
||||
meta,
|
||||
isLoading,
|
||||
onChange,
|
||||
}) => {
|
||||
const columns: Array<EuiBasicTableColumn<EngineListDetails>> = [
|
||||
{
|
||||
field: 'name',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.name', {
|
||||
defaultMessage: 'Engine Name',
|
||||
}),
|
||||
width: '30%',
|
||||
truncateText: true,
|
||||
mobileOptions: {
|
||||
header: true,
|
||||
enlarge: true,
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'document_count',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.documents', {
|
||||
defaultMessage: 'Documents',
|
||||
}),
|
||||
dataType: 'number',
|
||||
render: (number: number) => <FormattedNumber value={number} />,
|
||||
},
|
||||
{
|
||||
field: 'last_updated',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.lastUpdated', {
|
||||
defaultMessage: 'Last updated',
|
||||
}),
|
||||
dataType: 'string',
|
||||
},
|
||||
{
|
||||
field: 'indices.length',
|
||||
datatype: 'number',
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.indices', {
|
||||
defaultMessage: 'Indices',
|
||||
}),
|
||||
},
|
||||
|
||||
{
|
||||
name: i18n.translate('xpack.enterpriseSearch.content.enginesList.table.column.actions', {
|
||||
defaultMessage: 'Actions',
|
||||
}),
|
||||
actions: [
|
||||
{
|
||||
name: MANAGE_BUTTON_LABEL,
|
||||
description: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.enginesList.table.column.action.manage.buttonDescription',
|
||||
{
|
||||
defaultMessage: 'Manage this engine',
|
||||
}
|
||||
),
|
||||
type: 'icon',
|
||||
icon: 'eye',
|
||||
onClick: () => {},
|
||||
},
|
||||
{
|
||||
name: DELETE_BUTTON_LABEL,
|
||||
description: i18n.translate(
|
||||
'xpack.enterpriseSearch.content.enginesList.table.column.action.delete.buttonDescription',
|
||||
{
|
||||
defaultMessage: 'Delete this engine',
|
||||
}
|
||||
),
|
||||
type: 'icon',
|
||||
icon: 'trash',
|
||||
color: 'danger',
|
||||
onClick: () => {},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiBasicTable
|
||||
items={enginesList}
|
||||
columns={columns}
|
||||
pagination={{ ...convertMetaToPagination(meta), showPerPageOptions: false }}
|
||||
onChange={onChange}
|
||||
loading={isLoading}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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 { LogicMounter, mockFlashMessageHelpers } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import { nextTick } from '@kbn/test-jest-helpers';
|
||||
|
||||
import { HttpError, Status } from '../../../../../common/types/api';
|
||||
|
||||
import { FetchEnginesAPILogic } from '../../api/engines/fetch_engines_api_logic';
|
||||
|
||||
import { EnginesListLogic } from './engines_list_logic';
|
||||
import { DEFAULT_META, EngineListDetails } from './types';
|
||||
|
||||
const DEFAULT_VALUES = {
|
||||
data: undefined,
|
||||
results: [],
|
||||
meta: DEFAULT_META,
|
||||
parameters: { meta: DEFAULT_META },
|
||||
status: Status.IDLE,
|
||||
};
|
||||
|
||||
// sample engines list
|
||||
|
||||
const results: EngineListDetails[] = [
|
||||
{
|
||||
name: 'engine-name-1',
|
||||
indices: ['index-18', 'index-23'],
|
||||
last_updated: '21 March 2021',
|
||||
document_count: 18,
|
||||
},
|
||||
{
|
||||
name: 'engine-name-2',
|
||||
indices: ['index-180', 'index-230', 'index-8', 'index-2'],
|
||||
last_updated: '10 Jul 2018',
|
||||
document_count: 10,
|
||||
},
|
||||
|
||||
{
|
||||
name: 'engine-name-3',
|
||||
indices: ['index-2', 'index-3'],
|
||||
last_updated: '21 December 2022',
|
||||
document_count: 8,
|
||||
},
|
||||
];
|
||||
|
||||
describe('EnginesListLogic', () => {
|
||||
const { mount: apiLogicMount } = new LogicMounter(FetchEnginesAPILogic);
|
||||
const { mount } = new LogicMounter(EnginesListLogic);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.useRealTimers();
|
||||
apiLogicMount();
|
||||
mount();
|
||||
});
|
||||
it('has expected default values', () => {
|
||||
expect(EnginesListLogic.values).toEqual(DEFAULT_VALUES);
|
||||
});
|
||||
describe('actions', () => {
|
||||
describe('onPaginate', () => {
|
||||
it('updates meta with newPageIndex', () => {
|
||||
expect(EnginesListLogic.values).toEqual(DEFAULT_VALUES);
|
||||
// This test does not work for now, test below code when Kibana GET API for pagination is ready
|
||||
// EnginesListLogic.actions.onPaginate(2);
|
||||
// expect(EnginesListLogic.values).toEqual({
|
||||
// ...DEFAULT_VALUES,
|
||||
// meta: {
|
||||
// ...DEFAULT_META,
|
||||
// from: 2,
|
||||
// },
|
||||
// });
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('reducers', () => {
|
||||
describe('meta', () => {
|
||||
it('updates when apiSuccess', () => {
|
||||
const newPageMeta = {
|
||||
from: 2,
|
||||
size: 3,
|
||||
total: 6,
|
||||
};
|
||||
expect(EnginesListLogic.values).toEqual(DEFAULT_VALUES);
|
||||
EnginesListLogic.actions.apiSuccess({
|
||||
meta: newPageMeta,
|
||||
results,
|
||||
searchQuery: 'k',
|
||||
});
|
||||
expect(EnginesListLogic.values).toEqual({
|
||||
...DEFAULT_VALUES,
|
||||
data: {
|
||||
results,
|
||||
meta: newPageMeta,
|
||||
searchQuery: 'k',
|
||||
},
|
||||
meta: newPageMeta,
|
||||
parameters: {
|
||||
meta: newPageMeta,
|
||||
searchQuery: 'k',
|
||||
},
|
||||
results,
|
||||
status: Status.SUCCESS,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('listeners', () => {
|
||||
it('call flashAPIErrors on apiError', () => {
|
||||
EnginesListLogic.actions.apiError({} as HttpError);
|
||||
expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1);
|
||||
expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({});
|
||||
});
|
||||
|
||||
it('call makeRequest on fetchEngines', async () => {
|
||||
jest.useFakeTimers({ legacyFakeTimers: true });
|
||||
EnginesListLogic.actions.makeRequest = jest.fn();
|
||||
EnginesListLogic.actions.fetchEngines({ meta: DEFAULT_META });
|
||||
await nextTick();
|
||||
expect(EnginesListLogic.actions.makeRequest).toHaveBeenCalledWith({
|
||||
meta: DEFAULT_META,
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('selectors', () => {
|
||||
describe('enginesList', () => {
|
||||
it('updates when apiSuccess', () => {
|
||||
expect(EnginesListLogic.values).toEqual(DEFAULT_VALUES);
|
||||
EnginesListLogic.actions.apiSuccess({
|
||||
results,
|
||||
meta: DEFAULT_META,
|
||||
});
|
||||
expect(EnginesListLogic.values).toEqual({
|
||||
...DEFAULT_VALUES,
|
||||
data: {
|
||||
results,
|
||||
meta: DEFAULT_META,
|
||||
},
|
||||
meta: DEFAULT_META,
|
||||
parameters: {
|
||||
meta: DEFAULT_META,
|
||||
},
|
||||
results,
|
||||
status: Status.SUCCESS,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { mockedEngines } from '../../api/engines/fetch_engines_api_logic';
|
||||
|
||||
import { EnginesListTable } from './components/tables/engines_table';
|
||||
import { EnginesList } from './engines_list';
|
||||
import { DEFAULT_META } from './types';
|
||||
|
||||
const mockValues = {
|
||||
enginesList: mockedEngines,
|
||||
meta: DEFAULT_META,
|
||||
};
|
||||
const mockActions = {
|
||||
fetchEngines: jest.fn(),
|
||||
onPaginate: jest.fn(),
|
||||
};
|
||||
|
||||
describe('EnginesList', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
global.localStorage.clear();
|
||||
});
|
||||
describe('Empty state', () => {});
|
||||
|
||||
it('renders with Engines data ', async () => {
|
||||
setMockValues(mockValues);
|
||||
setMockActions(mockActions);
|
||||
|
||||
const wrapper = shallow(<EnginesList />);
|
||||
|
||||
expect(wrapper.find(EnginesListTable)).toHaveLength(1);
|
||||
});
|
||||
});
|
|
@ -5,13 +5,35 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import { EuiButton, EuiFieldSearch, EuiLink, EuiSpacer, EuiText } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage, FormattedNumber } from '@kbn/i18n-react';
|
||||
|
||||
import { DataPanel } from '../../../shared/data_panel/data_panel';
|
||||
|
||||
import { handlePageChange } from '../../../shared/table_pagination';
|
||||
import { EnterpriseSearchContentPageTemplate } from '../layout/page_template';
|
||||
|
||||
export const EnginesList = () => {
|
||||
import { EnginesListTable } from './components/tables/engines_table';
|
||||
import { EnginesListLogic } from './engines_list_logic';
|
||||
|
||||
export const EnginesList: React.FC = () => {
|
||||
const { fetchEngines, onPaginate } = useActions(EnginesListLogic);
|
||||
const { meta, results } = useValues(EnginesListLogic);
|
||||
const [searchQuery, setSearchValue] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
fetchEngines({
|
||||
meta,
|
||||
searchQuery,
|
||||
});
|
||||
}, [meta, searchQuery]);
|
||||
|
||||
return (
|
||||
<EnterpriseSearchContentPageTemplate
|
||||
pageChrome={[
|
||||
|
@ -20,13 +42,98 @@ export const EnginesList = () => {
|
|||
}),
|
||||
]}
|
||||
pageHeader={{
|
||||
pageTitle: i18n.translate('xpack.enterpriseSearch.content.engines.headerTitle', {
|
||||
pageTitle: i18n.translate('xpack.enterpriseSearch.content.engines.title', {
|
||||
defaultMessage: 'Engines',
|
||||
}),
|
||||
rightSideItems: [
|
||||
<EuiButton
|
||||
fill
|
||||
iconType="plusInCircle"
|
||||
data-test-subj="enterpriseSearchContentEnginesCreationButton"
|
||||
href={'TODO'}
|
||||
>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.engines.createEngineButtonLabel', {
|
||||
defaultMessage: 'Create engine',
|
||||
})}
|
||||
</EuiButton>,
|
||||
],
|
||||
}}
|
||||
pageViewTelemetry="Engines"
|
||||
isLoading={false}
|
||||
>
|
||||
<EuiText>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.engines.description', {
|
||||
defaultMessage:
|
||||
'Engines allow you to query indexed data with a complete set of relevance, analytics and personalization tools. To learn more about how engines work in Enterprise search ',
|
||||
})}
|
||||
|
||||
<EuiLink data-test-subj="documentationLink" href="TODO" target="_blank">
|
||||
{i18n.translate('xpack.enterpriseSearch.content.engines.documentation', {
|
||||
defaultMessage: 'explore our Engines documentation',
|
||||
})}
|
||||
</EuiLink>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
<div>
|
||||
<EuiFieldSearch
|
||||
value={searchQuery}
|
||||
placeholder={i18n.translate('xpack.enterpriseSearch.content.engines.searchPlaceholder', {
|
||||
defaultMessage: 'Search engines',
|
||||
})}
|
||||
aria-label={i18n.translate('xpack.enterpriseSearch.content.engines.searchBar.ariaLabel', {
|
||||
defaultMessage: 'Search engines',
|
||||
})}
|
||||
fullWidth
|
||||
onChange={(event) => {
|
||||
setSearchValue(event.currentTarget.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText color="subdued" size="s">
|
||||
{i18n.translate('xpack.enterpriseSearch.content.engines.searchPlaceholder.description', {
|
||||
defaultMessage: 'Locate an engine via name or indices',
|
||||
})}
|
||||
</EuiText>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
<EuiText size="s">
|
||||
<FormattedMessage
|
||||
id="xpack.enterpriseSearch.content.engines.enginesList.description"
|
||||
defaultMessage="Showing {currentPage}-{size} of {total}"
|
||||
values={{
|
||||
currentPage: (
|
||||
<strong>
|
||||
<FormattedNumber value={meta.from} />
|
||||
</strong>
|
||||
),
|
||||
size: (
|
||||
<strong>
|
||||
<FormattedNumber value={meta.size} />
|
||||
</strong>
|
||||
),
|
||||
total: <FormattedNumber value={meta.total} />,
|
||||
}}
|
||||
/>
|
||||
</EuiText>
|
||||
<DataPanel
|
||||
title={
|
||||
<h2>
|
||||
{i18n.translate('xpack.enterpriseSearch.content.engines.title', {
|
||||
defaultMessage: 'Engines',
|
||||
})}
|
||||
</h2>
|
||||
}
|
||||
>
|
||||
<EnginesListTable
|
||||
enginesList={results}
|
||||
meta={meta}
|
||||
onChange={handlePageChange(onPaginate)}
|
||||
loading={false}
|
||||
/>
|
||||
</DataPanel>
|
||||
|
||||
<EuiSpacer size="xxl" />
|
||||
<div />
|
||||
</EnterpriseSearchContentPageTemplate>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 { kea, MakeLogicType } from 'kea';
|
||||
|
||||
import { Actions } from '../../../shared/api_logic/create_api_logic';
|
||||
|
||||
import { flashAPIErrors } from '../../../shared/flash_messages';
|
||||
|
||||
import {
|
||||
EnginesListAPIArguments,
|
||||
EnginesListAPIResponse,
|
||||
FetchEnginesAPILogic,
|
||||
} from '../../api/engines/fetch_engines_api_logic';
|
||||
|
||||
import { DEFAULT_META, EngineListDetails, Meta, updateMetaPageIndex } from './types';
|
||||
|
||||
type EnginesListActions = Pick<
|
||||
Actions<EnginesListAPIArguments, EnginesListAPIResponse>,
|
||||
'apiError' | 'apiSuccess' | 'makeRequest'
|
||||
> & {
|
||||
fetchEngines({ meta, searchQuery }: { meta: Meta; searchQuery?: string }): {
|
||||
meta: Meta;
|
||||
searchQuery?: string;
|
||||
};
|
||||
onPaginate(pageNumber: number): { pageNumber: number };
|
||||
};
|
||||
interface EngineListValues {
|
||||
data: typeof FetchEnginesAPILogic.values.data;
|
||||
meta: Meta;
|
||||
results: EngineListDetails[]; // stores engine list value from data
|
||||
parameters: { meta: Meta; searchQuery?: string }; // Added this variable to store to the search Query value as well
|
||||
status: typeof FetchEnginesAPILogic.values.status;
|
||||
}
|
||||
|
||||
export const EnginesListLogic = kea<MakeLogicType<EngineListValues, EnginesListActions>>({
|
||||
connect: {
|
||||
actions: [FetchEnginesAPILogic, ['makeRequest', 'apiSuccess', 'apiError']],
|
||||
values: [FetchEnginesAPILogic, ['data', 'status']],
|
||||
},
|
||||
path: ['enterprise_search', 'content', 'engine_list_logic'],
|
||||
actions: {
|
||||
fetchEngines: ({ meta, searchQuery }) => ({
|
||||
meta,
|
||||
searchQuery,
|
||||
}),
|
||||
|
||||
onPaginate: (pageNumber) => ({ pageNumber }),
|
||||
},
|
||||
reducers: ({}) => ({
|
||||
parameters: [
|
||||
{ meta: DEFAULT_META },
|
||||
{
|
||||
apiSuccess: (_, { meta, searchQuery }) => ({
|
||||
meta,
|
||||
searchQuery,
|
||||
}),
|
||||
onPaginate: (state, { pageNumber }) => ({
|
||||
...state,
|
||||
meta: updateMetaPageIndex(state.meta, pageNumber),
|
||||
}),
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
||||
selectors: ({ selectors }) => ({
|
||||
results: [() => [selectors.data], (data) => data?.results ?? []],
|
||||
meta: [() => [selectors.parameters], (parameters) => parameters.meta],
|
||||
}),
|
||||
listeners: ({ actions }) => ({
|
||||
apiError: (e) => {
|
||||
flashAPIErrors(e);
|
||||
},
|
||||
fetchEngines: async (input) => {
|
||||
actions.makeRequest(input);
|
||||
},
|
||||
}),
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export interface Meta {
|
||||
from: number;
|
||||
size: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface EngineListDetails {
|
||||
name: string;
|
||||
indices: string[];
|
||||
last_updated: string;
|
||||
document_count: number;
|
||||
}
|
||||
export const DEFAULT_META = {
|
||||
from: 1,
|
||||
size: 3,
|
||||
total: 0,
|
||||
};
|
||||
|
||||
export const convertMetaToPagination = (meta: Meta) => ({
|
||||
pageIndex: meta.from - 1,
|
||||
pageSize: meta.size,
|
||||
totalItemCount: meta.total,
|
||||
});
|
||||
export const updateMetaPageIndex = (oldState: Meta, newPageIndex: number) => {
|
||||
return { ...oldState, from: newPageIndex };
|
||||
};
|
|
@ -23,5 +23,6 @@ export const SEARCH_INDEX_CRAWLER_DOMAIN_DETAIL_PATH = `${SEARCH_INDEX_PATH}/cra
|
|||
export const SEARCH_INDEX_SELECT_CONNECTOR_PATH = `${SEARCH_INDEX_PATH}/select_connector`;
|
||||
|
||||
export const ENGINES_PATH = `${ROOT_PATH}engines`;
|
||||
export const ENGINE_CREATION_PATH = `${ENGINES_PATH}/new`;
|
||||
|
||||
export const ML_MANAGE_TRAINED_MODELS_PATH = '/app/ml/trained_models';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue