Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Onboarding] Expose settings component in index_management to reuse in search_indices #193492

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
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export interface IndexManagementPluginStart {
getIndexMappingComponent: (deps: {
history: ScopedHistory<unknown>;
}) => React.FC<IndexMappingProps>;
getIndexSettingsComponent: (deps: {
history: ScopedHistory<unknown>;
}) => React.FC<IndexSettingProps>;
}

export interface Index {
Expand Down Expand Up @@ -56,7 +59,9 @@ export interface IndexMappingProps {
index?: Index;
showAboutMappings?: boolean;
}

export interface IndexSettingProps {
indexName: string;
}
export interface SendRequestResponse<D = any, E = any> {
data: D | null;
error: E | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
*/

import React from 'react';
import { documentationService } from '../../../../services';
import { UIM_APP_NAME } from '../../../../../../common/constants/ui_metric';
import { httpService } from '../../../../services/http';
import { notificationService } from '../../../../services/notification';
import { UiMetricService } from '../../../../services/ui_metric';
import { AppDependencies, IndexManagementAppContext } from '../../../..';
import { documentationService } from '../../../../../services';
import { UIM_APP_NAME } from '../../../../../../../common/constants/ui_metric';
import { httpService } from '../../../../../services/http';
import { notificationService } from '../../../../../services/notification';
import { UiMetricService } from '../../../../../services/ui_metric';
import { AppDependencies, IndexManagementAppContext } from '../../../../..';
import { IndexMappingWithContextProps } from './index_mapping_with_context_types';
import { DetailsPageMappings } from './details_page_mappings';
import { DetailsPageMappings } from '../details_page_mappings';

export const IndexMappingWithContext: React.FC<IndexMappingWithContextProps> = ({
core,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import { CoreStart } from '@kbn/core/public';
import { IndexMappingProps } from '@kbn/index-management-shared-types';
import { AppDependencies } from '../../../../app_context';
import { ExtensionsService } from '../../../../../services/extensions_service';
import { AppDependencies } from '../../../../../app_context';
import { ExtensionsService } from '../../../../../../services/extensions_service';

export type IndexMappingWithContextProps = {
core: CoreStart;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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.
*/

/* 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 { EuiLoadingSpinner } from '@elastic/eui';
import { dynamic } from '@kbn/shared-ux-utility';
import React, { Suspense, ComponentType } from 'react';
import { IndexSettingWithContextProps } from './index_settings_with_context_types';

const IndexSettingsWithContext = dynamic<ComponentType<IndexSettingWithContextProps>>(() =>
import('./index_settings_with_context').then((mod) => ({ default: mod.IndexSettingsWithContext }))
);

export const IndexSettings: React.FC<IndexSettingWithContextProps> = (props) => {
return (
<Suspense fallback={<EuiLoadingSpinner />}>
<IndexSettingsWithContext {...props} />
</Suspense>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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 { documentationService } from '../../../../../services';
import { UIM_APP_NAME } from '../../../../../../../common/constants/ui_metric';
import { httpService } from '../../../../../services/http';
import { notificationService } from '../../../../../services/notification';
import { UiMetricService } from '../../../../../services/ui_metric';
import { AppDependencies, IndexManagementAppContext } from '../../../../..';
import { DetailsPageSettings } from '../details_page_settings';
import { IndexSettingWithContextProps } from './index_settings_with_context_types';
import { setUiMetricService } from '../../../../../services/api';

export const IndexSettingsWithContext: React.FC<IndexSettingWithContextProps> = ({
core,
dependencies,
indexName,
usageCollection,
}) => {
// this normally happens when the index management app is rendered
// but if components are embedded elsewhere that setup is skipped, so we have to do it here
// would do it in plugin.ts but that blows up the bundle size
// can't do it in an effect because then the first http call fails as the instantiation happens after first render
if (!httpService.httpClient) {
httpService.setup(core.http);
notificationService.setup(core.notifications);
}
documentationService.setup(core.docLinks);

const uiMetricService = new UiMetricService(UIM_APP_NAME);
setUiMetricService(uiMetricService);
uiMetricService.setup(usageCollection);

const newDependencies: AppDependencies = {
...dependencies,
services: {
...(dependencies.services || {}),
httpService,
notificationService,
uiMetricService,
},
};
return (
<IndexManagementAppContext core={core} dependencies={newDependencies}>
<DetailsPageSettings indexName={indexName} />
</IndexManagementAppContext>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 { CoreStart } from '@kbn/core/public';
import type { IndexSettingProps } from '@kbn/index-management-shared-types';
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
import { AppDependencies } from '../../../../../app_context';
import { ExtensionsService } from '../../../../../../services/extensions_service';

export type IndexSettingWithContextProps = {
core: CoreStart;
// omitting services here to constitute them inside the component
// this helps reduce bundle size significantly
dependencies: Omit<AppDependencies, 'services'> & {
services: { extensionsService: ExtensionsService };
};
usageCollection: UsageCollectionSetup;
} & IndexSettingProps;
41 changes: 40 additions & 1 deletion x-pack/plugins/index_management/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ import { ClientConfigType, SetupDependencies, StartDependencies } from './types'

// avoid import from index files in plugin.ts, use specific import paths
import { PLUGIN } from '../common/constants/plugin';
import { IndexMapping } from './application/sections/home/index_list/details_page/index_mappings_embeddable';
import { IndexMapping } from './application/sections/home/index_list/details_page/with_context_components/index_mappings_embeddable';
import { PublicApiService } from './services/public_api_service';
import { IndexSettings } from './application/sections/home/index_list/details_page/with_context_components/index_settings_embeddable';

export class IndexMgmtUIPlugin
implements
Expand Down Expand Up @@ -159,6 +160,44 @@ export class IndexMgmtUIPlugin
return IndexMapping({ dependencies: appDependencies, core: coreStart, ...props });
};
},
getIndexSettingsComponent: (deps: { history: ScopedHistory<unknown> }) => {
const { docLinks, fatalErrors, application, uiSettings, executionContext, settings, http } =
coreStart;
const { url } = share;
const appDependencies = {
core: {
fatalErrors,
getUrlForApp: application.getUrlForApp,
executionContext,
application,
http,
},
plugins: {
usageCollection,
isFleetEnabled: Boolean(fleet),
share,
cloud,
console,
ml,
licensing,
},
services: {
extensionsService: this.extensionsService,
},
config: this.config,
history: deps.history,
setBreadcrumbs: undefined as any, // breadcrumbService.setBreadcrumbs,
uiSettings,
settings,
url,
docLinks,
kibanaVersion: this.kibanaVersion,
theme$: coreStart.theme.theme$,
};
return (props: any) => {
return IndexSettings({ dependencies: appDependencies, core: coreStart, ...props });
};
},
};
}
public stop() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ 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';
import { SearchIndicesDetailsMappingsTabs } from '../../routes';
import { SearchIndexDetailsTabs } from '../../routes';
import { SearchIndexDetailsMappings } from './details_page_mappings';
import { SearchIndexDetailsSettings } from './details_page_settings';

export const SearchIndexDetailsPage = () => {
const indexName = decodeURIComponent(useParams<{ indexName: string }>().indexName);
Expand All @@ -49,33 +50,40 @@ export const SearchIndexDetailsPage = () => {
isInitialLoading: isMappingsInitialLoading,
} = useIndexMapping(indexName);

const SearchIndexDetailsTabs: EuiTabbedContentTab[] = useMemo(() => {
const detailsPageTabs: EuiTabbedContentTab[] = useMemo(() => {
saarikabhasi marked this conversation as resolved.
Show resolved Hide resolved
return [
{
id: SearchIndicesDetailsMappingsTabs.DATA,
id: SearchIndexDetailsTabs.DATA,
saarikabhasi marked this conversation as resolved.
Show resolved Hide resolved
name: i18n.translate('xpack.searchIndices.documentsTabLabel', {
defaultMessage: 'Data',
}),
content: <IndexDocuments indexName={indexName} />,
'data-test-subj': `${SearchIndicesDetailsMappingsTabs.DATA}Tab`,
'data-test-subj': `${SearchIndexDetailsTabs.DATA}Tab`,
},
{
id: SearchIndicesDetailsMappingsTabs.MAPPINGS,
id: SearchIndexDetailsTabs.MAPPINGS,
name: i18n.translate('xpack.searchIndices.mappingsTabLabel', {
defaultMessage: 'Mappings',
}),
content: <SearchIndexDetailsMappings index={index} />,
'data-test-subj': `${SearchIndicesDetailsMappingsTabs.MAPPINGS}Tab`,
'data-test-subj': `${SearchIndexDetailsTabs.MAPPINGS}Tab`,
},
{
id: SearchIndexDetailsTabs.SETTINGS,
name: i18n.translate('xpack.searchIndices.settingsTabLabel', {
defaultMessage: 'Settings',
}),
content: <SearchIndexDetailsSettings indexName={indexName} />,
'data-test-subj': `${SearchIndexDetailsTabs.SETTINGS}Tab`,
},
];
}, [index, indexName]);

const [selectedTab, setSelectedTab] = useState(SearchIndexDetailsTabs[0]);
const [selectedTab, setSelectedTab] = useState(detailsPageTabs[0]);

useEffect(() => {
const newTab = SearchIndexDetailsTabs.find((tab) => tab.id === tabId);
const newTab = detailsPageTabs.find((tab) => tab.id === tabId);
if (newTab) setSelectedTab(newTab);
}, [SearchIndexDetailsTabs, tabId]);
}, [detailsPageTabs, tabId]);

const handleTabClick = useCallback(
(tab) => {
Expand Down Expand Up @@ -215,7 +223,7 @@ export const SearchIndexDetailsPage = () => {
<EuiFlexItem>
<EuiFlexItem>
<EuiTabbedContent
tabs={SearchIndexDetailsTabs}
tabs={detailsPageTabs}
onTabClick={handleTabClick}
selectedTab={selectedTab}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 { useMemo } from 'react';
import { useKibana } from '../../hooks/use_kibana';

interface SearchIndexDetailsSettingsProps {
indexName: string;
}
export const SearchIndexDetailsSettings = ({ indexName }: SearchIndexDetailsSettingsProps) => {
const { indexManagement, history } = useKibana().services;

const IndexSettingsComponent = useMemo(
() => indexManagement.getIndexSettingsComponent({ history }),
[indexManagement, history]
);

return <IndexSettingsComponent indexName={indexName} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Route, Router, Routes } from '@kbn/shared-ux-router';
import { Redirect } from 'react-router-dom';
import { useKibana } from '../../hooks/use_kibana';
import {
SearchIndicesDetailsMappingsTabs,
SearchIndexDetailsTabs,
SEARCH_INDICES_DETAILS_PATH,
SEARCH_INDICES_DETAILS_TABS_PATH,
} from '../../routes';
Expand All @@ -25,7 +25,7 @@ export const SearchIndicesRouter: React.FC = () => {
<Redirect
exact
from={`${SEARCH_INDICES_DETAILS_PATH}/`}
to={`${SEARCH_INDICES_DETAILS_PATH}/${SearchIndicesDetailsMappingsTabs.DATA}`}
to={`${SEARCH_INDICES_DETAILS_PATH}/${SearchIndexDetailsTabs.DATA}`}
/>
</Routes>
</Route>
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/search_indices/public/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
export const ROOT_PATH = '/';
export const SEARCH_INDICES_DETAILS_PATH = `${ROOT_PATH}index_details/:indexName`;
export const SEARCH_INDICES_DETAILS_TABS_PATH = `${SEARCH_INDICES_DETAILS_PATH}/:tabId`;
export enum SearchIndicesDetailsMappingsTabs {
export enum SearchIndexDetailsTabs {
DATA = 'data',
MAPPINGS = 'mappings',
SETTINGS = 'settings',
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,17 @@ export function SvlSearchIndexDetailPageProvider({ getService }: FtrProviderCont
async expectShouldDefaultToDataTab() {
expect(await browser.getCurrentUrl()).contain('/data');
},
async withDataChangeTabs(tab: 'dataTab' | 'mappingsTab') {
async withDataChangeTabs(tab: 'dataTab' | 'mappingsTab' | 'settingsTab') {
await testSubjects.click(tab);
},
async expectUrlShouldChangeTo(tab: 'data' | 'mappings') {
async expectUrlShouldChangeTo(tab: 'data' | 'mappings' | 'settings') {
expect(await browser.getCurrentUrl()).contain(`/${tab}`);
},
async expectMappingsComponentIsVisible() {
await testSubjects.existOrFail('indexDetailsMappingsToggleViewButton', { timeout: 2000 });
},
async expectSettingsComponentIsVisible() {
await testSubjects.existOrFail('indexDetailsSettingsEditModeSwitch', { timeout: 2000 });
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await pageObjects.svlSearchIndexDetailPage.expectWithDataTabsExists();
await pageObjects.svlSearchIndexDetailPage.expectShouldDefaultToDataTab();
});
it('should be able to change tabs', async () => {
it('should be able to change tabs to mappings and mappings is shown', async () => {
await pageObjects.svlSearchIndexDetailPage.withDataChangeTabs('mappingsTab');
await pageObjects.svlSearchIndexDetailPage.expectUrlShouldChangeTo('mappings');
await pageObjects.svlSearchIndexDetailPage.expectMappingsComponentIsVisible();
saarikabhasi marked this conversation as resolved.
Show resolved Hide resolved
});
it('should be able to change tabs to settings and settings is shown', async () => {
await pageObjects.svlSearchIndexDetailPage.withDataChangeTabs('settingsTab');
await pageObjects.svlSearchIndexDetailPage.expectUrlShouldChangeTo('settings');
await pageObjects.svlSearchIndexDetailPage.expectSettingsComponentIsVisible();
});
});

Expand Down