Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ enabled:
- x-pack/test/functional/apps/home/config.ts
- x-pack/test/functional/apps/index_lifecycle_management/config.ts
- x-pack/test/functional/apps/index_management/config.ts
- x-pack/test/functional/apps/index_management/index_details_page/config.ts
- x-pack/test/functional/apps/infra/config.ts
- x-pack/test/functional/apps/ingest_pipelines/config.ts
- x-pack/test/functional/apps/lens/group1/config.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.index_management.ui.enabled (boolean)',
'xpack.index_management.enableIndexActions (any)',
'xpack.index_management.enableLegacyTemplates (any)',
'xpack.index_management.dev.enableIndexDetailsPage (boolean)',
'xpack.infra.sources.default.fields.message (array)',
/**
* xpack.infra.logs is conditional and will resolve to an object of properties
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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 { AsyncTestBedConfig, registerTestBed, TestBed } from '@kbn/test-jest-helpers';
import { HttpSetup } from '@kbn/core/public';
import { act } from 'react-dom/test-utils';
import {
IndexDetailsPage,
IndexDetailsSection,
} from '../../../public/application/sections/home/index_list/details_page';
import { WithAppDependencies } from '../helpers';

const testBedConfig: AsyncTestBedConfig = {
memoryRouter: {
initialEntries: [`/indices/test_index`],
componentRoutePath: `/indices/:indexName/:indexDetailsSection?`,
},
doMountAsync: true,
};

export interface IndexDetailsPageTestBed extends TestBed {
actions: {
getHeader: () => string;
clickIndexDetailsTab: (tab: IndexDetailsSection) => Promise<void>;
getActiveTabContent: () => string;
};
}

export const setup = async (
httpSetup: HttpSetup,
overridingDependencies: any = {}
): Promise<IndexDetailsPageTestBed> => {
const initTestBed = registerTestBed(
WithAppDependencies(IndexDetailsPage, httpSetup, overridingDependencies),
testBedConfig
);
const testBed = await initTestBed();

const getHeader = () => {
return testBed.component.find('[data-test-subj="indexDetailsHeader"] h1').text();
};

const clickIndexDetailsTab = async (tab: IndexDetailsSection) => {
const { find, component } = testBed;

await act(async () => {
find(`indexDetailsTab-${tab}`).simulate('click');
});
component.update();
};

const getActiveTabContent = () => {
return testBed.find('indexDetailsContent').text();
};

return {
...testBed,
actions: {
getHeader,
clickIndexDetailsTab,
getActiveTabContent,
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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 { setupEnvironment } from '../helpers';
import { IndexDetailsPageTestBed, setup } from './index_details_page.helpers';
import { act } from 'react-dom/test-utils';
import { httpServiceMock } from '@kbn/core/public/mocks';
import { IndexDetailsSection } from '../../../public/application/sections/home/index_list/details_page';

describe('<IndexDetailsPage />', () => {
let testBed: IndexDetailsPageTestBed;
let httpSetup: ReturnType<typeof setupEnvironment>['httpSetup'];

beforeEach(async () => {
httpSetup = httpServiceMock.createSetupContract();

await act(async () => {
testBed = await setup(httpSetup);
});
testBed.component.update();
});

it('displays index name in the header', () => {
const header = testBed.actions.getHeader();
// test_index is configured in initialEntries of the memory router
expect(header).toEqual('test_index');
});

it('defaults to overview tab', () => {
const tabContent = testBed.actions.getActiveTabContent();
expect(tabContent).toEqual('Overview');
});

it('documents tab', async () => {
await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Documents);
const tabContent = testBed.actions.getActiveTabContent();
expect(tabContent).toEqual('Documents');
});

it('mappings tab', async () => {
await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Mappings);
const tabContent = testBed.actions.getActiveTabContent();
expect(tabContent).toEqual('Mappings');
});

it('settings tab', async () => {
await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Settings);
const tabContent = testBed.actions.getActiveTabContent();
expect(tabContent).toEqual('Settings');
});

it('pipelines tab', async () => {
await testBed.actions.clickIndexDetailsTab(IndexDetailsSection.Pipelines);
const tabContent = testBed.actions.getActiveTabContent();
expect(tabContent).toEqual('Pipelines');
});
});
4 changes: 2 additions & 2 deletions x-pack/plugins/index_management/public/application/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Router, Routes, Route } from '@kbn/shared-ux-router';
import { ScopedHistory } from '@kbn/core/public';

import { UIM_APP_LOAD } from '../../common/constants';
import { IndexManagementHome, homeSections } from './sections/home';
import { IndexManagementHome, homeSections, Section } from './sections/home';
import { TemplateCreate } from './sections/template_create';
import { TemplateClone } from './sections/template_clone';
import { TemplateEdit } from './sections/template_edit';
Expand Down Expand Up @@ -52,6 +52,6 @@ export const AppWithoutRouter = () => (
/>
<Route exact path="/edit_component_template/:name*" component={ComponentTemplateEdit} />
<Route path={`/:section(${homeSections.join('|')})`} component={IndexManagementHome} />
<Redirect from={`/`} to={`/indices`} />
<Redirect from={`/`} to={`/${Section.Indices}`} />
</Routes>
);
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface AppDependencies {
config: {
enableIndexActions: boolean;
enableLegacyTemplates: boolean;
enableIndexDetailsPage: boolean;
};
history: ScopedHistory;
setBreadcrumbs: ManagementAppMountParams['setBreadcrumbs'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,27 @@ function initSetup({
return { uiMetricService };
}

export async function mountManagementSection(
coreSetup: CoreSetup<StartDependencies>,
usageCollection: UsageCollectionSetup,
params: ManagementAppMountParams,
extensionsService: ExtensionsService,
isFleetEnabled: boolean,
kibanaVersion: SemVer,
enableIndexActions: boolean = true,
enableLegacyTemplates: boolean = true
) {
export async function mountManagementSection({
coreSetup,
usageCollection,
params,
extensionsService,
isFleetEnabled,
kibanaVersion,
enableIndexActions = true,
enableLegacyTemplates = true,
enableIndexDetailsPage = false,
}: {
coreSetup: CoreSetup<StartDependencies>;
usageCollection: UsageCollectionSetup;
params: ManagementAppMountParams;
extensionsService: ExtensionsService;
isFleetEnabled: boolean;
kibanaVersion: SemVer;
enableIndexActions?: boolean;
enableLegacyTemplates?: boolean;
enableIndexDetailsPage?: boolean;
}) {
const { element, setBreadcrumbs, history, theme$ } = params;
const [core, startDependencies] = await coreSetup.getStartServices();
const {
Expand Down Expand Up @@ -99,6 +110,7 @@ export async function mountManagementSection(
config: {
enableIndexActions,
enableLegacyTemplates,
enableIndexDetailsPage,
},
history,
setBreadcrumbs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import { RouteComponentProps } from 'react-router-dom';
import { Routes, Route } from '@kbn/shared-ux-router';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiButtonEmpty, EuiPageHeader, EuiSpacer } from '@elastic/eui';
import { breadcrumbService } from '../../services/breadcrumbs';
import { documentationService } from '../../services/documentation';
import { DataStreamList } from './data_stream_list';
import { useAppContext } from '../../app_context';
import { ComponentTemplateList } from '../../components/component_templates';
import { IndexList } from './index_list';
import { IndexDetailsPage } from './index_list/details_page';
import { DataStreamList } from './data_stream_list';
import { TemplateList } from './template_list';
import { ComponentTemplateList } from '../../components/component_templates';
import { breadcrumbService } from '../../services/breadcrumbs';

export enum Section {
Indices = 'indices',
Expand All @@ -41,6 +43,9 @@ export const IndexManagementHome: React.FunctionComponent<RouteComponentProps<Ma
},
history,
}) => {
const {
config: { enableIndexDetailsPage },
} = useAppContext();
const tabs = [
{
id: Section.Indices,
Expand Down Expand Up @@ -83,7 +88,7 @@ export const IndexManagementHome: React.FunctionComponent<RouteComponentProps<Ma
breadcrumbService.setBreadcrumbs('home');
}, []);

return (
const indexManagementTabs = (
<>
<EuiPageHeader
data-test-subj="indexManagementHeaderContent"
Expand Down Expand Up @@ -140,4 +145,18 @@ export const IndexManagementHome: React.FunctionComponent<RouteComponentProps<Ma
</Routes>
</>
);
if (enableIndexDetailsPage) {
return (
<>
<Routes>
<Route
path={`/${Section.Indices}/:indexName/:indexDetailsSection?`}
component={IndexDetailsPage}
/>
<Route render={() => indexManagementTabs} />
</Routes>
</>
);
}
return indexManagementTabs;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* 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, { useCallback, useMemo } from 'react';
import { Redirect, RouteComponentProps } from 'react-router-dom';
import { Route, Routes } from '@kbn/shared-ux-router';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiPageHeader, EuiSpacer, EuiPageHeaderProps } from '@elastic/eui';
import { Section } from '../../home';

export enum IndexDetailsSection {
Overview = 'overview',
Documents = 'documents',
Mappings = 'mappings',
Settings = 'settings',
Pipelines = 'pipelines',
}
const tabs = [
{
id: IndexDetailsSection.Overview,
name: (
<FormattedMessage id="xpack.idxMgmt.indexDetails.overviewTitle" defaultMessage="Overview" />
),
},
{
id: IndexDetailsSection.Documents,
name: (
<FormattedMessage id="xpack.idxMgmt.indexDetails.documentsTitle" defaultMessage="Documents" />
),
},
{
id: IndexDetailsSection.Mappings,
name: (
<FormattedMessage id="xpack.idxMgmt.indexDetails.mappingsTitle" defaultMessage="Mappings" />
),
},
{
id: IndexDetailsSection.Settings,
name: (
<FormattedMessage id="xpack.idxMgmt.indexDetails.settingsTitle" defaultMessage="Settings" />
),
},
{
id: IndexDetailsSection.Pipelines,
name: (
<FormattedMessage id="xpack.idxMgmt.indexDetails.pipelinesTitle" defaultMessage="Pipelines" />
),
},
];
export const DetailsPage: React.FunctionComponent<
RouteComponentProps<{ indexName: string; indexDetailsSection: IndexDetailsSection }>
> = ({
match: {
params: { indexName, indexDetailsSection },
},
history,
}) => {
const onSectionChange = useCallback(
(newSection: IndexDetailsSection) => {
return history.push(encodeURI(`/indices/${indexName}/${newSection}`));
},
[history, indexName]
);

const headerTabs = useMemo<EuiPageHeaderProps['tabs']>(() => {
return tabs.map((tab) => ({
onClick: () => onSectionChange(tab.id),
isSelected: tab.id === indexDetailsSection,
key: tab.id,
'data-test-subj': `indexDetailsTab-${tab.id}`,
label: tab.name,
}));
}, [indexDetailsSection, onSectionChange]);

return (
<>
<EuiPageHeader
data-test-subj="indexDetailsHeader"
pageTitle={indexName}
bottomBorder
rightSideItems={[]}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed at all?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll be adding action buttons on the right side in the next iteration

tabs={headerTabs}
/>

<EuiSpacer size="l" />

<div data-test-subj={`indexDetailsContent`}>
<Routes>
<Route
path={`/${Section.Indices}/${indexName}/${IndexDetailsSection.Overview}`}
render={() => <div>Overview</div>}
/>
<Route
path={`/${Section.Indices}/${indexName}/${IndexDetailsSection.Documents}`}
render={() => <div>Documents</div>}
/>
<Route
path={`/${Section.Indices}/${indexName}/${IndexDetailsSection.Mappings}`}
render={() => <div>Mappings</div>}
/>
<Route
path={`/${Section.Indices}/${indexName}/${IndexDetailsSection.Settings}`}
render={() => <div>Settings</div>}
/>
<Route
path={`/${Section.Indices}/${indexName}/${IndexDetailsSection.Pipelines}`}
render={() => <div>Pipelines</div>}
/>
<Redirect
from={`/${Section.Indices}/${indexName}`}
to={`/${Section.Indices}/${indexName}/${IndexDetailsSection.Overview}`}
/>
</Routes>
</div>
</>
);
};
Loading