diff --git a/CHANGELOG.md b/CHANGELOG.md index cf7b7738f408..ae72c4fa7361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,7 +107,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Multiple Datasource] Extract the button component for datasource picker to avoid duplicate code ([#6559](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6559)) - [Workspace] Add workspaces filter to saved objects page. ([#6458](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6458)) - [Multiple Datasource] Support multi data source in Region map ([#6654](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6654)) -- Introduce `registerRightNavigation` in chrome service to register standard top right navigation and add dev tool to top right navigation. ([#6553](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6553)) +- Add `rightNavigationButton` component in chrome service for applications to register and add dev tool to top right navigation. ([#6553](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6553)) ### 🐛 Bug Fixes diff --git a/src/core/public/chrome/README.md b/src/core/public/chrome/README.md index 5911f165f15c..6ec765a3bb0b 100644 --- a/src/core/public/chrome/README.md +++ b/src/core/public/chrome/README.md @@ -41,19 +41,6 @@ chrome.navControls.registerLeft({ } }) ``` - -Register a top right navigation. - -```jsx -chrome.navControls.registerRightNavigation({ - order: '1', - appId: 'app_id', - iconType: 'consoleApp', - title: 'app_title, -}) -``` -In this case, a circle icon navigation will be registered to top right header.It will navigate to app after clicked. - ### NavLinksService : - Interface : ChromeNavLinks - **Signature** - `navLinks: ChromeNavLinks` diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 74ee7474bbf7..b6ce429528a7 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -69,7 +69,6 @@ const createStartContractMock = () => { getLeft$: jest.fn(), getCenter$: jest.fn(), getRight$: jest.fn(), - registerRightNavigation: jest.fn(), }, setAppTitle: jest.fn(), setIsVisible: jest.fn(), diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index bba8a3bbf257..2660b4768839 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -182,7 +182,7 @@ export class ChromeService { const isNavDrawerLocked$ = new BehaviorSubject(localStorage.getItem(IS_LOCKED_KEY) === 'true'); const sidecarConfig$ = overlays.sidecar.getSidecarConfig$(); - const navControls = this.navControls.start({ application, http }); + const navControls = this.navControls.start(); const navLinks = this.navLinks.start({ application, http }); const recentlyAccessed = await this.recentlyAccessed.start({ http }); const docTitle = this.docTitle.start({ document: window.document }); diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts index 341801379c23..eb92ccdc6ba3 100644 --- a/src/core/public/chrome/index.ts +++ b/src/core/public/chrome/index.ts @@ -44,7 +44,7 @@ export { ChromeHelpExtensionMenuDocumentationLink, ChromeHelpExtensionMenuGitHubLink, } from './ui/header/header_help_menu'; -export { NavType } from './ui'; +export { NavType, RightNavigationButton, RightNavigationButtonProps } from './ui'; export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './nav_links'; export { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem } from './recently_accessed'; export { ChromeNavControl, ChromeNavControls } from './nav_controls'; diff --git a/src/core/public/chrome/nav_controls/nav_controls_service.test.ts b/src/core/public/chrome/nav_controls/nav_controls_service.test.ts index a7ef559a8e4f..6e2a71537e17 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.test.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.test.ts @@ -30,19 +30,10 @@ import { NavControlsService } from './nav_controls_service'; import { take } from 'rxjs/operators'; -import { applicationServiceMock, httpServiceMock } from '../../../../core/public/mocks'; - -const mockMountReactNode = jest.fn().mockReturnValue('mock mount point'); -jest.mock('../../utils', () => ({ - mountReactNode: () => mockMountReactNode(), -})); describe('RecentlyAccessed#start()', () => { const getStart = () => { - return new NavControlsService().start({ - application: applicationServiceMock.createInternalStartContract(), - http: httpServiceMock.createStartContract(), - }); + return new NavControlsService().start(); }; describe('left contorols', () => { @@ -85,45 +76,6 @@ describe('RecentlyAccessed#start()', () => { }); }); - describe('top right navigation', () => { - const mockProps = { - application: applicationServiceMock.createStartContract(), - http: httpServiceMock.createStartContract(), - appId: 'app_id', - iconType: 'icon', - title: 'title', - order: 1, - }; - it('allows registration', async () => { - const navControls = getStart(); - navControls.registerRightNavigation(mockProps); - expect(await navControls.getRight$().pipe(take(1)).toPromise()).toEqual([ - { - mount: 'mock mount point', - order: 1, - }, - ]); - }); - - it('sorts controls by order property', async () => { - const navControls = getStart(); - const props1 = { ...mockProps, order: 10 }; - const props2 = { ...mockProps, order: 0 }; - navControls.registerRightNavigation(props1); - navControls.registerRightNavigation(props2); - expect(await navControls.getRight$().pipe(take(1)).toPromise()).toEqual([ - { - mount: 'mock mount point', - order: 0, - }, - { - mount: 'mock mount point', - order: 10, - }, - ]); - }); - }); - describe('center controls', () => { it('allows registration', async () => { const navControls = getStart(); 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 ede33106ed2c..57298dac39ff 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.ts @@ -28,18 +28,10 @@ * 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'; -import { InternalApplicationStart } from '../../application'; -import { HttpStart } from '../../http'; /** @public */ export interface ChromeNavControl { @@ -47,15 +39,6 @@ export interface ChromeNavControl { mount: MountPoint; } -interface StartDeps { - application: InternalApplicationStart; - http: HttpStart; -} - -interface RightNavigationProps extends Omit { - order: number; -} - /** * {@link ChromeNavControls | APIs} for registering new controls to be displayed in the navigation bar. * @@ -79,8 +62,6 @@ 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 uniformly maintained in chrome */ - registerRightNavigation(props: RightNavigationProps): void; /** @internal */ getLeft$(): Observable; /** @internal */ @@ -93,7 +74,7 @@ export interface ChromeNavControls { export class NavControlsService { private readonly stop$ = new ReplaySubject(1); - public start({ application, http }: StartDeps) { + public start() { const navControlsLeft$ = new BehaviorSubject>(new Set()); const navControlsRight$ = new BehaviorSubject>(new Set()); const navControlsCenter$ = new BehaviorSubject>(new Set()); @@ -102,16 +83,15 @@ export class NavControlsService { new Set() ); - const registerRight = (navControl: ChromeNavControl) => - navControlsRight$.next(new Set([...navControlsRight$.value.values(), navControl])); - return { // In the future, registration should be moved to the setup phase. This // is not possible until the legacy nav controls are no longer supported. registerLeft: (navControl: ChromeNavControl) => navControlsLeft$.next(new Set([...navControlsLeft$.value.values(), navControl])), - registerRight, + registerRight: (navControl: ChromeNavControl) => + navControlsRight$.next(new Set([...navControlsRight$.value.values(), navControl])), + registerCenter: (navControl: ChromeNavControl) => navControlsCenter$.next(new Set([...navControlsCenter$.value.values(), navControl])), @@ -124,19 +104,7 @@ 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, - http, - application, - }) - ), - }; - return registerRight(nav); - }, + getLeft$: () => navControlsLeft$.pipe( map((controls) => sortBy([...controls.values()], 'order')), diff --git a/src/core/public/chrome/ui/header/index.ts b/src/core/public/chrome/ui/header/index.ts index 0bde1cef241a..811eca0cad84 100644 --- a/src/core/public/chrome/ui/header/index.ts +++ b/src/core/public/chrome/ui/header/index.ts @@ -37,3 +37,4 @@ export { ChromeHelpExtensionMenuDocumentationLink, ChromeHelpExtensionMenuGitHubLink, } from './header_help_menu'; +export { RightNavigationButton, RightNavigationButtonProps } from './right_navigation_button'; diff --git a/src/core/public/chrome/ui/header/right_navigation_button.tsx b/src/core/public/chrome/ui/header/right_navigation_button.tsx index 0c1333cbfffc..c70386325b30 100644 --- a/src/core/public/chrome/ui/header/right_navigation_button.tsx +++ b/src/core/public/chrome/ui/header/right_navigation_button.tsx @@ -5,12 +5,12 @@ import { EuiHeaderSectionItemButton, EuiIcon } from '@elastic/eui'; import React, { useMemo } from 'react'; -import { InternalApplicationStart } from '../../../application'; -import { HttpStart } from '../../../http'; +import { CoreStart } from '../../..'; + import { isModifiedOrPrevented } from './nav_link'; export interface RightNavigationButtonProps { - application: InternalApplicationStart; - http: HttpStart; + application: CoreStart['application']; + http: CoreStart['http']; appId: string; iconType: string; title: string; diff --git a/src/core/public/chrome/ui/index.ts b/src/core/public/chrome/ui/index.ts index 93e3371b2892..11f0c0302df5 100644 --- a/src/core/public/chrome/ui/index.ts +++ b/src/core/public/chrome/ui/index.ts @@ -37,4 +37,6 @@ export { ChromeHelpExtensionMenuDocumentationLink, ChromeHelpExtensionMenuGitHubLink, NavType, + RightNavigationButton, + RightNavigationButtonProps, } from './header'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 418021aa4c09..10d1928d6cf2 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -69,6 +69,8 @@ import { ChromeRecentlyAccessedHistoryItem, NavType, RightNavigationOrder, + RightNavigationButton, + RightNavigationButtonProps, } from './chrome'; import { FatalErrorsSetup, FatalErrorsStart, FatalErrorInfo } from './fatal_errors'; import { HttpSetup, HttpStart } from './http'; @@ -362,6 +364,8 @@ export { NavType, Branding, RightNavigationOrder, + RightNavigationButton, + RightNavigationButtonProps, }; export { __osdBootstrap__ } from './osd_bootstrap'; diff --git a/src/plugins/dashboard/public/application/components/dashboard_listing/__snapshots__/dashboard_listing.test.tsx.snap b/src/plugins/dashboard/public/application/components/dashboard_listing/__snapshots__/dashboard_listing.test.tsx.snap index 2015746a2a3b..b0ee4d34705f 100644 --- a/src/plugins/dashboard/public/application/components/dashboard_listing/__snapshots__/dashboard_listing.test.tsx.snap +++ b/src/plugins/dashboard/public/application/components/dashboard_listing/__snapshots__/dashboard_listing.test.tsx.snap @@ -218,7 +218,6 @@ exports[`dashboard listing hideWriteControls 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -1364,7 +1363,6 @@ exports[`dashboard listing render table listing with initial filters from URL 1` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -2571,7 +2569,6 @@ exports[`dashboard listing renders call to action when no dashboards exist 1`] = "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -3778,7 +3775,6 @@ exports[`dashboard listing renders table rows 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -4985,7 +4981,6 @@ exports[`dashboard listing renders warning when listingLimit is exceeded 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -5972,4 +5967,4 @@ exports[`dashboard listing renders warning when listingLimit is exceeded 1`] = ` -`; +`; \ No newline at end of file diff --git a/src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap b/src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap index eddaf7bb899e..3649379ec583 100644 --- a/src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap +++ b/src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap @@ -206,7 +206,6 @@ exports[`Dashboard top nav render in embed mode 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -1178,7 +1177,6 @@ exports[`Dashboard top nav render in embed mode, and force hide filter bar 1`] = "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -2150,7 +2148,6 @@ exports[`Dashboard top nav render in embed mode, components can be forced show b "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -3122,7 +3119,6 @@ exports[`Dashboard top nav render in full screen mode with appended URL param bu "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -4094,7 +4090,6 @@ exports[`Dashboard top nav render in full screen mode, no componenets should be "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -5066,7 +5061,6 @@ exports[`Dashboard top nav render with all components 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], - "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -5829,4 +5823,4 @@ exports[`Dashboard top nav render with all components 1`] = ` -`; +`; \ No newline at end of file diff --git a/src/plugins/dev_tools/opensearch_dashboards.json b/src/plugins/dev_tools/opensearch_dashboards.json index c8f4ccc88439..9b4a419c9ff4 100644 --- a/src/plugins/dev_tools/opensearch_dashboards.json +++ b/src/plugins/dev_tools/opensearch_dashboards.json @@ -4,5 +4,6 @@ "server": false, "ui": true, "optionalPlugins": ["dataSource", "managementOverview", "dataSourceManagement"], - "requiredPlugins": ["urlForwarding"] + "requiredPlugins": ["urlForwarding"], + "requiredBundles": ["opensearchDashboardsReact"] } diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index 2c650569993a..45f07f8d651e 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -28,6 +28,7 @@ * under the License. */ +import React from 'react'; import { BehaviorSubject } from 'rxjs'; import { Plugin, CoreSetup, AppMountParameters, CoreStart } from 'src/core/public'; import { AppUpdater } from 'opensearch-dashboards/public'; @@ -39,12 +40,14 @@ import { AppNavLinkStatus, DEFAULT_APP_CATEGORIES, RightNavigationOrder, + RightNavigationButton, } 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'; +import { toMountPoint } from '../../opensearch_dashboards_react/public'; export interface DevToolsSetupDependencies { urlForwarding: UrlForwardingSetup; @@ -135,11 +138,17 @@ export class DevToolsPlugin implements Plugin { if (this.getSortedDevTools().length === 0) { this.appStateUpdater.next(() => ({ navLinkStatus: AppNavLinkStatus.hidden })); } - core.chrome.navControls.registerRightNavigation({ + core.chrome.navControls.registerRight({ order: RightNavigationOrder.DevTool, - appId: this.id, - iconType: 'consoleApp', - title: this.title, + mount: toMountPoint( + React.createElement(RightNavigationButton, { + appId: this.id, + iconType: 'consoleApp', + title: this.title, + application: core.application, + http: core.http, + }) + ), }); }