diff --git a/src/core/public/chrome/nav_controls/nav_controls_service.ts b/src/core/public/chrome/nav_controls/nav_controls_service.ts index 57298dac39ff..68fad1429373 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.ts @@ -28,10 +28,16 @@ * under the License. */ +import React from 'react'; import { sortBy } from 'lodash'; import { BehaviorSubject, ReplaySubject, Observable } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; import { MountPoint } from '../../types'; +import { + RightNavigationButton, + RightNavigationButtonProps, +} from '../ui/header/right_navigation_button'; +import { mountReactNode } from '../../utils'; /** @public */ export interface ChromeNavControl { @@ -39,6 +45,10 @@ export interface ChromeNavControl { mount: MountPoint; } +interface RightNavigationProps extends RightNavigationButtonProps { + order: number; +} + /** * {@link ChromeNavControls | APIs} for registering new controls to be displayed in the navigation bar. * @@ -62,6 +72,8 @@ export interface ChromeNavControls { registerRight(navControl: ChromeNavControl): void; /** Register a nav control to be presented on the top-center side of the chrome header. */ registerCenter(navControl: ChromeNavControl): void; + /** Register a nav control to be presented on the top-right side of the chrome header. The component and style will be maintained in chrome */ + registerRightNavigation(props: RightNavigationProps): void; /** @internal */ getLeft$(): Observable; /** @internal */ @@ -104,6 +116,17 @@ export class NavControlsService { navControlsExpandedCenter$.next( new Set([...navControlsExpandedCenter$.value.values(), navControl]) ), + registerRightNavigation: (props: RightNavigationProps) => { + const nav = { + order: props.order, + mount: mountReactNode( + React.createElement(RightNavigationButton, { + ...props, + }) + ), + }; + return navControlsRight$.next(new Set([...navControlsRight$.value.values(), nav])); + }, getLeft$: () => navControlsLeft$.pipe( diff --git a/src/core/public/chrome/ui/header/right_navigation_button.tsx b/src/core/public/chrome/ui/header/right_navigation_button.tsx new file mode 100644 index 000000000000..5efd9d90269c --- /dev/null +++ b/src/core/public/chrome/ui/header/right_navigation_button.tsx @@ -0,0 +1,49 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiButtonIcon } from '@elastic/eui'; +import React from 'react'; +import { CoreStart } from 'src/core/public'; + +export interface RightNavigationButtonProps { + application: CoreStart['application']; + http: CoreStart['http']; + appId: string; + iconType: string; + title: string; +} + +export const RightNavigationButton = ({ + application, + http, + appId, + iconType, + title, +}: RightNavigationButtonProps) => { + const navigateToApp = () => { + const appUrl = application.getUrlForApp(appId, { + path: '/', + absolute: false, + }); + // Remove prefix in Url including workspace and other prefix + const targetUrl = http.basePath.prepend(http.basePath.remove(appUrl), { + withoutClientBasePath: true, + }); + application.navigateToUrl(targetUrl); + }; + + return ( + + ); +}; diff --git a/src/plugins/advanced_settings/public/plugin.ts b/src/plugins/advanced_settings/public/plugin.ts index 608bfc6a25e7..0db39ed23772 100644 --- a/src/plugins/advanced_settings/public/plugin.ts +++ b/src/plugins/advanced_settings/public/plugin.ts @@ -29,10 +29,10 @@ */ import { i18n } from '@osd/i18n'; -import { CoreSetup, Plugin } from 'opensearch-dashboards/public'; import { FeatureCatalogueCategory } from '../../home/public'; import { ComponentRegistry } from './component_registry'; import { AdvancedSettingsSetup, AdvancedSettingsStart, AdvancedSettingsPluginSetup } from './types'; +import { CoreSetup, Plugin, CoreStart } from '../../../core/public'; const component = new ComponentRegistry(); @@ -77,7 +77,15 @@ export class AdvancedSettingsPlugin }; } - public start() { + public start(core: CoreStart) { + core.chrome.navControls.registerRightNavigation({ + order: 1, + appId: 'management/opensearch-dashboards/settings', + http: core.http, + application: core.application, + iconType: 'gear', + title, + }); return { component: component.start, }; diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index bb0b6ee1d981..59f68beb4b8b 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -29,7 +29,7 @@ */ import { BehaviorSubject } from 'rxjs'; -import { Plugin, CoreSetup, AppMountParameters } from 'src/core/public'; +import { Plugin, CoreSetup, AppMountParameters, CoreStart } from 'src/core/public'; import { AppUpdater } from 'opensearch-dashboards/public'; import { i18n } from '@osd/i18n'; import { sortBy } from 'lodash'; @@ -74,12 +74,14 @@ export class DevToolsPlugin implements Plugin { defaultMessage: 'Dev Tools', }); + private id = 'dev_tools'; + public setup(coreSetup: CoreSetup, deps: DevToolsSetupDependencies) { const { application: applicationSetup, getStartServices } = coreSetup; const { urlForwarding, managementOverview } = deps; applicationSetup.register({ - id: 'dev_tools', + id: this.id, title: this.title, updater$: this.appStateUpdater, icon: '/ui/logos/opensearch_mark.svg', @@ -98,7 +100,7 @@ export class DevToolsPlugin implements Plugin { }); managementOverview?.register({ - id: 'dev_tools', + id: this.id, title: this.title, description: i18n.translate('devTools.devToolsDescription', { defaultMessage: @@ -124,10 +126,19 @@ export class DevToolsPlugin implements Plugin { }; } - public start() { + public start(core: CoreStart) { if (this.getSortedDevTools().length === 0) { this.appStateUpdater.next(() => ({ navLinkStatus: AppNavLinkStatus.hidden })); } + core.chrome.navControls.registerRightNavigation({ + // order of dev tool should be after advance settings + order: 2, + appId: this.id, + http: core.http, + application: core.application, + iconType: 'consoleApp', + title: this.title, + }); } public stop() {}