Skip to content

Commit

Permalink
[Onboarding] Expose settings component in index_management to reuse i…
Browse files Browse the repository at this point in the history
…n search_indices (#193492)

## Summary
This PR exposes `index_management` index details [settings component
](https://github.com/elastic/kibana/blob/main/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_settings.tsx#L16)during
`index_management` plugin start. This would enable `search_indices`
plugin to reuse.

With this change, in new search index details page user can :

- Can View settings 
- Update settings & save 
- Reset changes

<img width="1719" alt="Screenshot 2024-09-19 at 5 48 28 PM"
src="https://github.com/user-attachments/assets/a6179fb6-c180-434e-bdb1-3c784006069f">

**How to test:** 
1. Enable searchIndices plugin in `kibana.dev.yml` as this plugin is
behind Feature flag
```
xpack.searchIndices.enabled: true

```
2. [Create new
index](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html)
3. Navigate to
`/app/elasticsearch/indices/index_details/${indexName}/settings`

 

### 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)
- [x] [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] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 24, 2024
1 parent 92f1320 commit d925391
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 28 deletions.
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(() => {
return [
{
id: SearchIndicesDetailsMappingsTabs.DATA,
id: SearchIndexDetailsTabs.DATA,
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();
});
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

0 comments on commit d925391

Please sign in to comment.