diff --git a/CHANGELOG.md b/CHANGELOG.md index c75496ab3569..ac8bcd585e4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Add category option within groups for context menus ([#4144](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4144)) - [Saved Object Service] Add Repository Factory Provider ([#4149](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4149)) - Enable plugins to augment visualizations with additional data and context ([#4361](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4361)) +- New management overview page and rename stack management to dashboard management ([#4287](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/4287)) + ### 🐛 Bug Fixes diff --git a/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx b/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx index a8e4595b2cff..7fa0b9ddd2c0 100644 --- a/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx +++ b/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx @@ -43,7 +43,7 @@ import { ComponentRegistry } from '../types'; import './index.scss'; const title = i18n.translate('advancedSettings.advancedSettingsLabel', { - defaultMessage: 'Advanced Settings', + defaultMessage: 'Advanced settings', }); const crumb = [{ text: title }]; diff --git a/src/plugins/advanced_settings/public/plugin.ts b/src/plugins/advanced_settings/public/plugin.ts index 43e959e88557..608bfc6a25e7 100644 --- a/src/plugins/advanced_settings/public/plugin.ts +++ b/src/plugins/advanced_settings/public/plugin.ts @@ -37,7 +37,7 @@ import { AdvancedSettingsSetup, AdvancedSettingsStart, AdvancedSettingsPluginSet const component = new ComponentRegistry(); const title = i18n.translate('advancedSettings.advancedSettingsLabel', { - defaultMessage: 'Advanced Settings', + defaultMessage: 'Advanced settings', }); export class AdvancedSettingsPlugin diff --git a/src/plugins/data_source_management/common/index.ts b/src/plugins/data_source_management/common/index.ts index e42b0c3fc514..3ba84084699a 100644 --- a/src/plugins/data_source_management/common/index.ts +++ b/src/plugins/data_source_management/common/index.ts @@ -4,4 +4,4 @@ */ export const PLUGIN_ID = 'dataSourceManagement'; -export const PLUGIN_NAME = 'Data Sources'; +export const PLUGIN_NAME = 'Data sources'; diff --git a/src/plugins/data_source_management/public/components/breadcrumbs.test.ts b/src/plugins/data_source_management/public/components/breadcrumbs.test.ts index a99cabc4596d..fbf1c62bb7dc 100644 --- a/src/plugins/data_source_management/public/components/breadcrumbs.test.ts +++ b/src/plugins/data_source_management/public/components/breadcrumbs.test.ts @@ -9,7 +9,7 @@ import { mockDataSourceAttributesWithAuth } from '../mocks'; describe('DataSourceManagement: breadcrumbs.ts', () => { test('get listing breadcrumb', () => { const bc = getListBreadcrumbs(); - expect(bc[0].text).toBe('Data Sources'); + expect(bc[0].text).toBe('Data sources'); expect(bc[0].href).toBe('/'); }); diff --git a/src/plugins/data_source_management/public/components/breadcrumbs.ts b/src/plugins/data_source_management/public/components/breadcrumbs.ts index 8287ea1e7384..ad1b470c89d4 100644 --- a/src/plugins/data_source_management/public/components/breadcrumbs.ts +++ b/src/plugins/data_source_management/public/components/breadcrumbs.ts @@ -10,7 +10,7 @@ export function getListBreadcrumbs() { return [ { text: i18n.translate('dataSourcesManagement.dataSources.listBreadcrumb', { - defaultMessage: 'Data Sources', + defaultMessage: 'Data sources', }), href: `/`, }, diff --git a/src/plugins/dev_tools/opensearch_dashboards.json b/src/plugins/dev_tools/opensearch_dashboards.json index 11fd6c3b62c7..97dbe29f3001 100644 --- a/src/plugins/dev_tools/opensearch_dashboards.json +++ b/src/plugins/dev_tools/opensearch_dashboards.json @@ -3,7 +3,7 @@ "version": "opensearchDashboards", "server": false, "ui": true, - "optionalPlugins": ["dataSource"], + "optionalPlugins": ["dataSource", "managementOverview"], "requiredPlugins": ["urlForwarding"], "requiredBundles": ["dataSourceManagement"] } diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index 0c0b3b07f5c1..2374f7e1315b 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -34,16 +34,20 @@ import { AppUpdater } from 'opensearch-dashboards/public'; import { i18n } from '@osd/i18n'; import { sortBy } from 'lodash'; -import { DataSourcePluginStart } from 'src/plugins/data_source/public'; +import { DataSourcePluginSetup } from 'src/plugins/data_source/public'; import { AppNavLinkStatus, DEFAULT_APP_CATEGORIES } from '../../../core/public'; import { UrlForwardingSetup } from '../../url_forwarding/public'; import { CreateDevToolArgs, DevToolApp, createDevToolApp } from './dev_tool'; import './index.scss'; +import { ManagementOverViewPluginSetup } from '../../management_overview/public'; export interface DevToolsSetupDependencies { - dataSource?: DataSourcePluginStart; + dataSource?: DataSourcePluginSetup; + urlForwarding: UrlForwardingSetup; + managementOverview?: ManagementOverViewPluginSetup; } + export interface DevToolsSetup { /** * Register a developer tool. It will be available @@ -58,7 +62,7 @@ export interface DevToolsSetup { register: (devTool: CreateDevToolArgs) => DevToolApp; } -export class DevToolsPlugin implements Plugin { +export class DevToolsPlugin implements Plugin { private readonly devTools = new Map(); private appStateUpdater = new BehaviorSubject(() => ({})); @@ -66,32 +70,43 @@ export class DevToolsPlugin implements Plugin { return sortBy([...this.devTools.values()], 'order'); } - public setup( - coreSetup: CoreSetup, - { urlForwarding }: { urlForwarding: UrlForwardingSetup } - ) { + private title = i18n.translate('devTools.devToolsTitle', { + defaultMessage: 'Dev Tools', + }); + + public setup(coreSetup: CoreSetup, deps: DevToolsSetupDependencies) { const { application: applicationSetup, getStartServices } = coreSetup; + const { urlForwarding, managementOverview } = deps; applicationSetup.register({ id: 'dev_tools', - title: i18n.translate('devTools.devToolsTitle', { - defaultMessage: 'Dev Tools', - }), + title: this.title, updater$: this.appStateUpdater, euiIconType: '/plugins/home/assets/logos/opensearch_mark_default.svg', - order: 9010, + /* the order of dev tools, it shows as last item of management section */ + order: 9070, category: DEFAULT_APP_CATEGORIES.management, mount: async (params: AppMountParameters) => { const { element, history } = params; element.classList.add('devAppWrapper'); - const [core, devSetup] = await getStartServices(); + const [core] = await getStartServices(); const { renderApp } = await import('./application'); - return renderApp(core, element, history, this.getSortedDevTools(), devSetup); + return renderApp(core, element, history, this.getSortedDevTools(), deps); }, }); + managementOverview?.register({ + id: 'dev_tools', + title: this.title, + description: i18n.translate('devTools.devToolsDescription', { + defaultMessage: + 'Use the console to set up and troubleshoot your OpenSearch environment with the REST API.', + }), + order: 9070, + }); + urlForwarding.forwardApp('dev_tools', 'dev_tools'); return { diff --git a/src/plugins/index_pattern_management/public/plugin.ts b/src/plugins/index_pattern_management/public/plugin.ts index c1fbeab54f26..cf68e043b76c 100644 --- a/src/plugins/index_pattern_management/public/plugin.ts +++ b/src/plugins/index_pattern_management/public/plugin.ts @@ -56,7 +56,7 @@ export type IndexPatternManagementSetup = IndexPatternManagementServiceSetup; export type IndexPatternManagementStart = IndexPatternManagementServiceStart; const sectionsHeader = i18n.translate('indexPatternManagement.indexPattern.sectionsHeader', { - defaultMessage: 'Index Patterns', + defaultMessage: 'Index patterns', }); const IPM_APP_ID = 'indexPatterns'; diff --git a/src/plugins/management/opensearch_dashboards.json b/src/plugins/management/opensearch_dashboards.json index 5f08e79223ec..cf7d7d781f16 100644 --- a/src/plugins/management/opensearch_dashboards.json +++ b/src/plugins/management/opensearch_dashboards.json @@ -3,6 +3,6 @@ "version": "opensearchDashboards", "server": true, "ui": true, - "optionalPlugins": ["home"], - "requiredBundles": ["opensearchDashboardsReact", "opensearchDashboardsUtils", "home"] + "optionalPlugins": ["home", "managementOverview"], + "requiredBundles": ["opensearchDashboardsReact", "opensearchDashboardsUtils"] } diff --git a/src/plugins/management/public/components/landing/landing.tsx b/src/plugins/management/public/components/landing/landing.tsx index 8c44f014d8e8..5557eb7e9019 100644 --- a/src/plugins/management/public/components/landing/landing.tsx +++ b/src/plugins/management/public/components/landing/landing.tsx @@ -46,7 +46,7 @@ interface ManagementLandingPageProps { setBreadcrumbs: () => void; } -export const ManagementLandingPage = ({ version, setBreadcrumbs }: ManagementLandingPageProps) => { +export const ManagementLandingPage = ({ setBreadcrumbs }: ManagementLandingPageProps) => { useMount(() => { setBreadcrumbs(); }); @@ -61,15 +61,14 @@ export const ManagementLandingPage = ({ version, setBreadcrumbs }: ManagementLan

diff --git a/src/plugins/management/public/components/management_sections.tsx b/src/plugins/management/public/components/management_sections.tsx index 8360c4be8902..0e2c7a7975bd 100644 --- a/src/plugins/management/public/components/management_sections.tsx +++ b/src/plugins/management/public/components/management_sections.tsx @@ -64,7 +64,7 @@ const sectionTip = i18n.translate('management.sections.section.tip', { }); const opensearchDashboardsTitle = i18n.translate('management.sections.opensearchDashboardsTitle', { - defaultMessage: 'OpenSearch Dashboards', + defaultMessage: 'Dashboards Management', }); const opensearchDashboardsTip = i18n.translate('management.sections.opensearchDashboardsTip', { diff --git a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.scss b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.scss index f9e5a74d4f35..9303dbbf4c30 100644 --- a/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.scss +++ b/src/plugins/management/public/components/management_sidebar_nav/management_sidebar_nav.scss @@ -1,5 +1,5 @@ .mgtSideBarNav { - width: 210px; + width: 220px; margin-right: $euiSize; } diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index b50b2dba2477..4cc1c4aa7f8f 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -31,7 +31,7 @@ import { i18n } from '@osd/i18n'; import { BehaviorSubject } from 'rxjs'; import { ManagementSetup, ManagementStart } from './types'; -import { FeatureCatalogueCategory, HomePublicPluginSetup } from '../../home/public'; +import { HomePublicPluginSetup } from '../../home/public'; import { CoreSetup, CoreStart, @@ -49,9 +49,11 @@ import { ManagementSectionsService, getSectionsServiceStartPrivate, } from './management_sections_service'; +import { ManagementOverViewPluginSetup } from '../../management_overview/public'; interface ManagementSetupDependencies { home?: HomePublicPluginSetup; + managementOverview?: ManagementOverViewPluginSetup; } export class ManagementPlugin implements Plugin { @@ -63,32 +65,17 @@ export class ManagementPlugin implements Plugin this.hasAnyEnabledApps, - }); - } + public setup(core: CoreSetup, { home, managementOverview }: ManagementSetupDependencies) { + const opensearchDashboardsVersion = this.initializerContext.env.packageInfo.version; core.application.register({ id: MANAGEMENT_APP_ID, - title: i18n.translate('management.stackManagement.title', { - defaultMessage: 'Stack Management', - }), - order: 9040, + title: this.title, + order: 9030, icon: '/plugins/home/assets/logos/opensearch_mark_default.svg', category: DEFAULT_APP_CATEGORIES.management, updater$: this.appUpdater, @@ -104,6 +91,16 @@ export class ManagementPlugin implements Plugin link.hidden) + .map((link) => link.id) || []; + + const availableApps = overviewApps?.filter((app) => hiddenAppIds.indexOf(app.id) === -1); + + return ( + + + +

+ +

+
+ + + {availableApps?.map((app) => ( + + { + application.navigateToApp(app.id); + }} + /> + + ))} + +
+
+ ); +} + +export function renderApp( + { application, chrome }: CoreStart, + overviewApps: OverviewApp[], + element: HTMLElement +) { + ReactDOM.render( + + + , + element + ); + + return () => { + chrome.docTitle.reset(); + ReactDOM.unmountComponentAtNode(element); + }; +} diff --git a/src/plugins/management_overview/public/components/overview_card/__snapshots__/overview_card.test.tsx.snap b/src/plugins/management_overview/public/components/overview_card/__snapshots__/overview_card.test.tsx.snap new file mode 100644 index 000000000000..ed6b9eb5dc11 --- /dev/null +++ b/src/plugins/management_overview/public/components/overview_card/__snapshots__/overview_card.test.tsx.snap @@ -0,0 +1,32 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`OverviewCard should render normally 1`] = ` +
+
+

+ +

+
+

+ Dev tools description +

+
+
+
+`; diff --git a/src/plugins/management_overview/public/components/overview_card/index.ts b/src/plugins/management_overview/public/components/overview_card/index.ts new file mode 100644 index 000000000000..d56e99bdac96 --- /dev/null +++ b/src/plugins/management_overview/public/components/overview_card/index.ts @@ -0,0 +1,6 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export { OverviewCard, OverviewCardProps } from './overview_card'; diff --git a/src/plugins/management_overview/public/components/overview_card/overview_card.test.tsx b/src/plugins/management_overview/public/components/overview_card/overview_card.test.tsx new file mode 100644 index 000000000000..6534fbca85f5 --- /dev/null +++ b/src/plugins/management_overview/public/components/overview_card/overview_card.test.tsx @@ -0,0 +1,27 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { render } from '@testing-library/react'; +import { OverviewCard } from './overview_card'; +import React from 'react'; + +function renderOverviewCard() { + return render( + + ); +} + +describe('OverviewCard', () => { + it('should render normally', () => { + const { container, queryByText } = renderOverviewCard(); + expect(container.firstChild).toMatchSnapshot(); + expect(queryByText('Dev Tools')).not.toBeNull(); + }); +}); diff --git a/src/plugins/management_overview/public/components/overview_card/overview_card.tsx b/src/plugins/management_overview/public/components/overview_card/overview_card.tsx new file mode 100644 index 000000000000..dad91bc1e79b --- /dev/null +++ b/src/plugins/management_overview/public/components/overview_card/overview_card.tsx @@ -0,0 +1,30 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiCard } from '@elastic/eui'; +import React from 'react'; + +export interface OverviewCardProps { + id: string; + title: string; + description: string; + onClick: () => void; +} + +export function OverviewCard(props: OverviewCardProps) { + const { id, title, description, onClick } = props; + + return ( + + ); +} diff --git a/src/plugins/management_overview/public/index.ts b/src/plugins/management_overview/public/index.ts new file mode 100644 index 000000000000..28eadd8c2f33 --- /dev/null +++ b/src/plugins/management_overview/public/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ManagementOverViewPlugin } from './plugin'; + +export { OverviewApp } from './overview_app'; +export { ManagementOverViewPluginSetup, ManagementOverViewPluginStart } from './plugin'; + +export const plugin = () => new ManagementOverViewPlugin(); diff --git a/src/plugins/management_overview/public/overview_app.ts b/src/plugins/management_overview/public/overview_app.ts new file mode 100644 index 000000000000..dfb85e8c3275 --- /dev/null +++ b/src/plugins/management_overview/public/overview_app.ts @@ -0,0 +1,14 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export interface OverviewApp { + /** id of plugin app */ + id: string; + /** Title of plugin displayed to the user. */ + title: string; + /** One-line description of feature displayed to the user. */ + description: string; + order: number; +} diff --git a/src/plugins/management_overview/public/plugin.ts b/src/plugins/management_overview/public/plugin.ts new file mode 100644 index 000000000000..b588d50e23da --- /dev/null +++ b/src/plugins/management_overview/public/plugin.ts @@ -0,0 +1,86 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { i18n } from '@osd/i18n'; +import { + AppMountParameters, + CoreSetup, + Plugin, + DEFAULT_APP_CATEGORIES, + CoreStart, +} from '../../../core/public'; +import { FeatureCatalogueCategory, HomePublicPluginSetup } from '../../home/public'; +import { MANAGEMENT_OVERVIEW_PLUGIN_ID } from '../common/constants'; +import { OverviewApp } from './overview_app'; + +interface ManagementOverviewSetupDeps { + home?: HomePublicPluginSetup; +} + +export interface ManagementOverViewPluginSetup { + register: (overviewApp: OverviewApp) => void; +} +/** @public */ +export class ManagementOverViewPlugin implements Plugin { + private readonly overviewApps = new Map(); + + private getSortedOverviewApps(): OverviewApp[] { + return [...this.overviewApps.values()].sort((a, b) => a.order - b.order); + } + + public setup( + coreSetup: CoreSetup, + { home }: ManagementOverviewSetupDeps + ): ManagementOverViewPluginSetup { + const { application, getStartServices } = coreSetup; + + if (home) { + home.featureCatalogue.register({ + id: MANAGEMENT_OVERVIEW_PLUGIN_ID, + title: i18n.translate('management.stackManagement.managementLabel', { + defaultMessage: 'Management', + }), + description: i18n.translate('management.stackManagement.managementDescription', { + defaultMessage: 'Your center location for managing the OpenSearch Stack.', + }), + icon: 'managementApp', + path: `/app/${MANAGEMENT_OVERVIEW_PLUGIN_ID}`, + showOnHomePage: false, + category: FeatureCatalogueCategory.ADMIN, + }); + } + + application.register({ + id: MANAGEMENT_OVERVIEW_PLUGIN_ID, + title: i18n.translate('management.overview.overviewTitle', { + defaultMessage: 'Overview', + }), + icon: '/plugins/home/public/assets/logos/opensearch_mark_default.svg', + order: 9000, + category: DEFAULT_APP_CATEGORIES.management, + mount: async (params: AppMountParameters) => { + const { element } = params; + const [core] = await getStartServices(); + const overviewApps = this.getSortedOverviewApps(); + + const { renderApp } = await import('./application'); + return renderApp(core, overviewApps, element); + }, + }); + + return { + register: (app: OverviewApp) => { + if (this.overviewApps.has(app.id)) { + throw new Error( + `Management overview App tool with id [${app.id}] has already been registered. Use a unique id.` + ); + } + this.overviewApps.set(app.id, app); + }, + }; + } + + public start(core: CoreStart): void {} +} diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts index 43356eb8f9e5..14beb73386a8 100644 --- a/src/plugins/saved_objects_management/public/plugin.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -127,7 +127,7 @@ export class SavedObjectsManagementPlugin opensearchDashboardsSection.registerApp({ id: 'objects', title: i18n.translate('savedObjectsManagement.managementSectionLabel', { - defaultMessage: 'Saved Objects', + defaultMessage: 'Saved objects', }), order: 1, mount: async (mountParams) => { diff --git a/test/functional/page_objects/header_page.ts b/test/functional/page_objects/header_page.ts index aa05dd12d8dc..f9a873c49ced 100644 --- a/test/functional/page_objects/header_page.ts +++ b/test/functional/page_objects/header_page.ts @@ -73,7 +73,7 @@ export function HeaderPageProvider({ getService, getPageObjects }: FtrProviderCo } public async clickStackManagement() { - await appsMenu.clickLink('Stack Management', { category: 'management' }); + await appsMenu.clickLink('Dashboards Management', { category: 'management' }); await this.awaitGlobalLoadingIndicatorHidden(); }