From 6669c07784172896d92dd9918b5a8e8e477b11a6 Mon Sep 17 00:00:00 2001 From: tygao Date: Fri, 19 Apr 2024 13:46:51 +0800 Subject: [PATCH 01/16] feat: add dev tool to top right navigation Signed-off-by: tygao --- src/core/public/chrome/chrome_service.mock.ts | 1 + .../nav_controls/nav_controls_service.test.ts | 45 ++++++++++++++++++ .../nav_controls/nav_controls_service.ts | 24 +++++++++- .../right_navigation_button.test.tsx.snap | 32 +++++++++++++ .../header/right_navigation_button.test.tsx | 45 ++++++++++++++++++ .../ui/header/right_navigation_button.tsx | 46 +++++++++++++++++++ src/plugins/dev_tools/public/plugin.ts | 19 ++++++-- 7 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 src/core/public/chrome/ui/header/__snapshots__/right_navigation_button.test.tsx.snap create mode 100644 src/core/public/chrome/ui/header/right_navigation_button.test.tsx create mode 100644 src/core/public/chrome/ui/header/right_navigation_button.tsx diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index b6ce429528a7..74ee7474bbf7 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -69,6 +69,7 @@ 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/nav_controls/nav_controls_service.test.ts b/src/core/public/chrome/nav_controls/nav_controls_service.test.ts index 6e2a71537e17..aa4d9dff2b15 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,6 +30,12 @@ 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 = () => { @@ -76,6 +82,45 @@ 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 57298dac39ff..a7cb7b1fe9ac 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 uniformly maintained in chrome */ + registerRightNavigation(props: RightNavigationProps): void; /** @internal */ getLeft$(): Observable; /** @internal */ @@ -104,7 +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( map((controls) => sortBy([...controls.values()], 'order')), diff --git a/src/core/public/chrome/ui/header/__snapshots__/right_navigation_button.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/right_navigation_button.test.tsx.snap new file mode 100644 index 000000000000..3bd3bc57c9c7 --- /dev/null +++ b/src/core/public/chrome/ui/header/__snapshots__/right_navigation_button.test.tsx.snap @@ -0,0 +1,32 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Right navigation button should render base element normally 1`] = ` + +
+ +
+ +`; diff --git a/src/core/public/chrome/ui/header/right_navigation_button.test.tsx b/src/core/public/chrome/ui/header/right_navigation_button.test.tsx new file mode 100644 index 000000000000..bbc77af24111 --- /dev/null +++ b/src/core/public/chrome/ui/header/right_navigation_button.test.tsx @@ -0,0 +1,45 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React from 'react'; +import { fireEvent, render } from '@testing-library/react'; +import { RightNavigationButton } from './right_navigation_button'; +import { applicationServiceMock, httpServiceMock } from '../../../../../core/public/mocks'; + +const mockProps = { + application: applicationServiceMock.createStartContract(), + http: httpServiceMock.createStartContract(), + appId: 'app_id', + iconType: 'mock_icon', + title: 'title', +}; + +describe('Right navigation button', () => { + it('should render base element normally', () => { + const { baseElement } = render(); + expect(baseElement).toMatchSnapshot(); + }); + + it('should call application getUrlForApp and navigateToUrl after clicked', () => { + const navigateToUrl = jest.fn(); + const getUrlForApp = jest.fn(); + const props = { + ...mockProps, + application: { + ...applicationServiceMock.createStartContract(), + getUrlForApp, + navigateToUrl, + }, + }; + const { getByTestId } = render(); + const icon = getByTestId('rightNavigationButton'); + fireEvent.click(icon); + expect(getUrlForApp).toHaveBeenCalledWith('app_id', { + path: '/', + absolute: false, + }); + expect(navigateToUrl).toHaveBeenCalled(); + }); +}); 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..ff7abe88224e --- /dev/null +++ b/src/core/public/chrome/ui/header/right_navigation_button.tsx @@ -0,0 +1,46 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { EuiHeaderSectionItemButton, EuiIcon } 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/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index 944ea6d96ba3..ba44bb1fb7f1 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'; @@ -75,12 +75,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', @@ -99,7 +101,7 @@ export class DevToolsPlugin implements Plugin { }); managementOverview?.register({ - id: 'dev_tools', + id: this.id, title: this.title, description: i18n.translate('devTools.devToolsDescription', { defaultMessage: @@ -125,10 +127,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() {} From 6d6ece1569a3bf934e7e89344c4d17d6e0c1380b Mon Sep 17 00:00:00 2001 From: tygao Date: Fri, 19 Apr 2024 13:57:40 +0800 Subject: [PATCH 02/16] doc: update changelog Signed-off-by: tygao --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a7101f6342f..82f29d3ecf13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,6 +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)) +- Add dev tool to top right navigation. ([#6553](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6553)) ### 🐛 Bug Fixes From 25c8bc44a568d3a7b11dbf6a5fc2164ed62ed491 Mon Sep 17 00:00:00 2001 From: tygao Date: Fri, 19 Apr 2024 14:12:59 +0800 Subject: [PATCH 03/16] test: update component props snapshot Signed-off-by: tygao --- .../header/__snapshots__/right_navigation_button.test.tsx.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/public/chrome/ui/header/__snapshots__/right_navigation_button.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/right_navigation_button.test.tsx.snap index 3bd3bc57c9c7..27b5748febcf 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/right_navigation_button.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/right_navigation_button.test.tsx.snap @@ -19,7 +19,7 @@ exports[`Right navigation button should render base element normally 1`] = ` class="euiHeaderSectionItemButton__content" > From 0faebef2a35ed5441beffcc8b4628df9856eb51a Mon Sep 17 00:00:00 2001 From: tygao Date: Fri, 19 Apr 2024 15:36:54 +0800 Subject: [PATCH 04/16] update nav_controls_service.ts Co-authored-by: SuZhou-Joe Signed-off-by: tygao --- src/core/public/chrome/nav_controls/nav_controls_service.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 a7cb7b1fe9ac..58bffc1ffaf0 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.ts @@ -120,9 +120,7 @@ export class NavControlsService { const nav = { order: props.order, mount: mountReactNode( - React.createElement(RightNavigationButton, { - ...props, - }) + React.createElement(RightNavigationButton, props) ), }; return navControlsRight$.next(new Set([...navControlsRight$.value.values(), nav])); From c962c9eec7f3d831aa203350c14c61bad1652317 Mon Sep 17 00:00:00 2001 From: tygao Date: Fri, 19 Apr 2024 18:12:09 +0800 Subject: [PATCH 05/16] update dependency props and constants Signed-off-by: tygao --- src/core/public/chrome/chrome_service.tsx | 2 +- src/core/public/chrome/constants.ts | 6 ++++++ src/core/public/chrome/index.ts | 1 + .../chrome/nav_controls/nav_controls_service.ts | 17 ++++++++++++++--- .../ui/header/right_navigation_button.test.tsx | 4 ++-- .../ui/header/right_navigation_button.tsx | 7 ++++--- src/core/public/index.ts | 2 ++ src/plugins/dev_tools/public/plugin.ts | 11 ++++++----- 8 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 2660b4768839..bba8a3bbf257 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(); + const navControls = this.navControls.start({ application, http }); 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/constants.ts b/src/core/public/chrome/constants.ts index 5008f8b4a69a..31aa4fc6675d 100644 --- a/src/core/public/chrome/constants.ts +++ b/src/core/public/chrome/constants.ts @@ -31,3 +31,9 @@ export const OPENSEARCH_DASHBOARDS_ASK_OPENSEARCH_LINK = 'https://forum.opensearch.org/'; export const GITHUB_CREATE_ISSUE_LINK = 'https://github.com/opensearch-project/OpenSearch-Dashboards/issues/new/choose'; + +export enum RightNavigationOrder { + // order of dev tool should be after advance settings + Settings = 1, + DevTool = 2, +} diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts index 4004c2c323f9..341801379c23 100644 --- a/src/core/public/chrome/index.ts +++ b/src/core/public/chrome/index.ts @@ -49,3 +49,4 @@ export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './ export { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem } from './recently_accessed'; export { ChromeNavControl, ChromeNavControls } from './nav_controls'; export { ChromeDocTitle } from './doc_title'; +export { RightNavigationOrder } from './constants'; 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 58bffc1ffaf0..64cd67d089ec 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.ts @@ -38,6 +38,8 @@ import { RightNavigationButtonProps, } from '../ui/header/right_navigation_button'; import { mountReactNode } from '../../utils'; +import { InternalApplicationStart } from '../../application'; +import { HttpStart } from '../../http'; /** @public */ export interface ChromeNavControl { @@ -45,7 +47,12 @@ export interface ChromeNavControl { mount: MountPoint; } -interface RightNavigationProps extends RightNavigationButtonProps { +interface StartDeps { + application: InternalApplicationStart; + http: HttpStart; +} + +interface RightNavigationProps extends Omit { order: number; } @@ -86,7 +93,7 @@ export interface ChromeNavControls { export class NavControlsService { private readonly stop$ = new ReplaySubject(1); - public start() { + public start({ application, http }: StartDeps) { const navControlsLeft$ = new BehaviorSubject>(new Set()); const navControlsRight$ = new BehaviorSubject>(new Set()); const navControlsCenter$ = new BehaviorSubject>(new Set()); @@ -120,7 +127,11 @@ export class NavControlsService { const nav = { order: props.order, mount: mountReactNode( - React.createElement(RightNavigationButton, props) + React.createElement(RightNavigationButton, { + ...props, + http, + application, + }) ), }; return navControlsRight$.next(new Set([...navControlsRight$.value.values(), nav])); diff --git a/src/core/public/chrome/ui/header/right_navigation_button.test.tsx b/src/core/public/chrome/ui/header/right_navigation_button.test.tsx index bbc77af24111..9fdb1d7e4512 100644 --- a/src/core/public/chrome/ui/header/right_navigation_button.test.tsx +++ b/src/core/public/chrome/ui/header/right_navigation_button.test.tsx @@ -9,7 +9,7 @@ import { RightNavigationButton } from './right_navigation_button'; import { applicationServiceMock, httpServiceMock } from '../../../../../core/public/mocks'; const mockProps = { - application: applicationServiceMock.createStartContract(), + application: applicationServiceMock.createInternalStartContract(), http: httpServiceMock.createStartContract(), appId: 'app_id', iconType: 'mock_icon', @@ -28,7 +28,7 @@ describe('Right navigation button', () => { const props = { ...mockProps, application: { - ...applicationServiceMock.createStartContract(), + ...applicationServiceMock.createInternalStartContract(), getUrlForApp, navigateToUrl, }, 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 ff7abe88224e..04338f5fe56a 100644 --- a/src/core/public/chrome/ui/header/right_navigation_button.tsx +++ b/src/core/public/chrome/ui/header/right_navigation_button.tsx @@ -5,11 +5,12 @@ import { EuiHeaderSectionItemButton, EuiIcon } from '@elastic/eui'; import React from 'react'; -import { CoreStart } from 'src/core/public'; +import { InternalApplicationStart } from '../../../application'; +import { HttpStart } from '../../../http'; export interface RightNavigationButtonProps { - application: CoreStart['application']; - http: CoreStart['http']; + application: InternalApplicationStart; + http: HttpStart; appId: string; iconType: string; title: string; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 2107ab668f3e..418021aa4c09 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -68,6 +68,7 @@ import { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, NavType, + RightNavigationOrder, } from './chrome'; import { FatalErrorsSetup, FatalErrorsStart, FatalErrorInfo } from './fatal_errors'; import { HttpSetup, HttpStart } from './http'; @@ -360,6 +361,7 @@ export { UiSettingsState, NavType, Branding, + RightNavigationOrder, }; export { __osdBootstrap__ } from './osd_bootstrap'; diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index ba44bb1fb7f1..2c650569993a 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -35,7 +35,11 @@ import { i18n } from '@osd/i18n'; import { sortBy } from 'lodash'; import { DataSourceManagementPluginSetup } from 'src/plugins/data_source_management/public'; import { DataSourcePluginSetup } from 'src/plugins/data_source/public'; -import { AppNavLinkStatus, DEFAULT_APP_CATEGORIES } from '../../../core/public'; +import { + AppNavLinkStatus, + DEFAULT_APP_CATEGORIES, + RightNavigationOrder, +} from '../../../core/public'; import { UrlForwardingSetup } from '../../url_forwarding/public'; import { CreateDevToolArgs, DevToolApp, createDevToolApp } from './dev_tool'; @@ -132,11 +136,8 @@ export class DevToolsPlugin implements Plugin { this.appStateUpdater.next(() => ({ navLinkStatus: AppNavLinkStatus.hidden })); } core.chrome.navControls.registerRightNavigation({ - // order of dev tool should be after advance settings - order: 2, + order: RightNavigationOrder.DevTool, appId: this.id, - http: core.http, - application: core.application, iconType: 'consoleApp', title: this.title, }); From 943d0fe1a646ff40721774a3771e459a4e00d731 Mon Sep 17 00:00:00 2001 From: tygao Date: Fri, 19 Apr 2024 18:33:01 +0800 Subject: [PATCH 06/16] update nav control test Signed-off-by: tygao --- .../public/chrome/nav_controls/nav_controls_service.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 aa4d9dff2b15..a7ef559a8e4f 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 @@ -39,7 +39,10 @@ jest.mock('../../utils', () => ({ describe('RecentlyAccessed#start()', () => { const getStart = () => { - return new NavControlsService().start(); + return new NavControlsService().start({ + application: applicationServiceMock.createInternalStartContract(), + http: httpServiceMock.createStartContract(), + }); }; describe('left contorols', () => { From 27235698fffb80d645404706e018d942cba1026e Mon Sep 17 00:00:00 2001 From: tygao Date: Fri, 19 Apr 2024 18:12:37 +0800 Subject: [PATCH 07/16] Update CHANGELOG.md Co-authored-by: SuZhou-Joe Signed-off-by: tygao --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82f29d3ecf13..9578e8444a8f 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)) -- Add dev tool to top right navigation. ([#6553](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6553)) +- Introduce `registerRightNavigation` in chrome service to reigster standard top right navigation and add dev tool to top right navigation. ([#6553](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6553)) ### 🐛 Bug Fixes From e737c46e26153e494f13377a2249d0679549be54 Mon Sep 17 00:00:00 2001 From: tygao Date: Mon, 22 Apr 2024 10:40:11 +0800 Subject: [PATCH 08/16] test: update snapshots Signed-off-by: tygao --- .../dashboard_listing.test.tsx.snap | 8208 ++++++++++++++++- .../dashboard_top_nav.test.tsx.snap | 6 + 2 files changed, 8209 insertions(+), 5 deletions(-) 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 db34c4f229bb..f1197ef1f6f5 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,6 +218,7 @@ exports[`dashboard listing hideWriteControls 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], + "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -1129,11 +1130,1481 @@ exports[`dashboard listing hideWriteControls 1`] = ` data-test-subj="dashboardLandingPage" >
+ > + + +
+
+ +
+ +
+ +

+ Dashboards +

+
+
+
+
+
+ +
+ + + } + pagination={ + Object { + "initialPageIndex": 0, + "initialPageSize": 10, + "pageSizeOptions": Array [ + 10, + 20, + 50, + ], + } + } + responsive={true} + search={ + Object { + "box": Object { + "incremental": true, + }, + "defaultQuery": "", + "onChange": [Function], + "toolsLeft": undefined, + } + } + sorting={true} + tableLayout="fixed" + > +
+ + +
+ +
+ + + +
+
+ + + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + } + onChange={[Function]} + pagination={ + Object { + "hidePerPageOptions": undefined, + "pageIndex": 0, + "pageSize": 10, + "pageSizeOptions": Array [ + 10, + 20, + 50, + ], + "totalItemCount": 2, + } + } + responsive={true} + sorting={ + Object { + "allowNeutralSort": true, + "sort": undefined, + } + } + tableLayout="fixed" + > +
+
+ +
+ +
+ +
+ + +
+ +
+ + + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + +
+
+
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + +
+
+ Title +
+
+ + + +
+
+
+ Type +
+
+ + dashboardSavedObjects + +
+
+
+ Description +
+
+ + dashboard0 desc + +
+
+
+ Last updated +
+
+
+
+ Title +
+
+ + + +
+
+
+ Type +
+
+ + dashboardSavedObjects + +
+
+
+ Description +
+
+ + dashboard1 desc + +
+
+
+ Last updated +
+
+
+
+
+ +
+ +
+ + + +
+ +
+ + + : + 10 + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + +
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+ +
+ +
+ +
+
+ + +
@@ -1363,6 +2834,7 @@ exports[`dashboard listing render table listing with initial filters from URL 1` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], + "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -2335,11 +3807,2151 @@ exports[`dashboard listing render table listing with initial filters from URL 1` data-test-subj="dashboardLandingPage" >
+ > + + +
+
+ +
+ +
+ +

+ Dashboards +

+
+
+
+ + +
+ + + + + +
+
+
+
+
+ +
+ + + } + pagination={ + Object { + "initialPageIndex": 0, + "initialPageSize": 10, + "pageSizeOptions": Array [ + 10, + 20, + 50, + ], + } + } + responsive={true} + search={ + Object { + "box": Object { + "incremental": true, + }, + "defaultQuery": "dashboard", + "onChange": [Function], + "toolsLeft": undefined, + } + } + selection={ + Object { + "onSelectionChange": [Function], + } + } + sorting={true} + tableLayout="fixed" + > +
+ + +
+ +
+ + + +
+
+ + + + +
+ + + + + +
+
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + } + onChange={[Function]} + pagination={ + Object { + "hidePerPageOptions": undefined, + "pageIndex": 0, + "pageSize": 10, + "pageSizeOptions": Array [ + 10, + 20, + 50, + ], + "totalItemCount": 2, + } + } + responsive={true} + selection={ + Object { + "onSelectionChange": [Function], + } + } + sorting={ + Object { + "allowNeutralSort": true, + "sort": undefined, + } + } + tableLayout="fixed" + > +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + +
+ + +
+ +
+ + + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + +
+
+
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + +
+ +
+
+ + +
+
+ + + + + + + + + + + + + + Actions + + + + + +
+
+ + +
+ +
+
+ + +
+
+
+ Title +
+
+ + + +
+
+
+ Type +
+
+ + dashboardSavedObjects + +
+
+
+ Description +
+
+ + dashboard0 desc + +
+
+
+ Last updated +
+
+
+
+ + + + + + + + + + Edit + + + + + + +
+
+
+ + +
+ +
+
+ + +
+
+
+ Title +
+
+ + + +
+
+
+ Type +
+
+ + dashboardSavedObjects + +
+
+
+ Description +
+
+ + dashboard1 desc + +
+
+
+ Last updated +
+
+
+
+ + + + + + + + + + Edit + + + + + + +
+
+
+
+ +
+ +
+ + + +
+ +
+ + + : + 10 + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + +
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+ +
+ +
+ +
+
+ + +
@@ -2569,6 +6181,7 @@ exports[`dashboard listing renders call to action when no dashboards exist 1`] = "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], + "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -3541,11 +7154,274 @@ exports[`dashboard listing renders call to action when no dashboards exist 1`] = data-test-subj="dashboardLandingPage" >
+ > + + +
+ + + + } + body={ + +

+ +

+

+ + + , + } + } + /> +

+
+ } + iconType="dashboardApp" + title={ +

+ +

+ } + > +
+ + + + +
+ + +

+ + Create your first dashboard + +

+
+ + + +
+ + +
+

+ + You can combine data views from any OpenSearch Dashboards app into one dashboard and see everything in one place. + +

+

+ + + , + } + } + > + New to OpenSearch Dashboards? + + + + to take a test drive. + +

+
+
+ + + +
+ + + + + + +
+ +
+ + +
@@ -3775,6 +7651,7 @@ exports[`dashboard listing renders table rows 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], + "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -4747,11 +8624,2111 @@ exports[`dashboard listing renders table rows 1`] = ` data-test-subj="dashboardLandingPage" >
+ > + + +
+
+ +
+ +
+ +

+ Dashboards +

+
+
+
+ + +
+ + + + + +
+
+
+
+
+ +
+ + + } + pagination={ + Object { + "initialPageIndex": 0, + "initialPageSize": 10, + "pageSizeOptions": Array [ + 10, + 20, + 50, + ], + } + } + responsive={true} + search={ + Object { + "box": Object { + "incremental": true, + }, + "defaultQuery": "", + "onChange": [Function], + "toolsLeft": undefined, + } + } + selection={ + Object { + "onSelectionChange": [Function], + } + } + sorting={true} + tableLayout="fixed" + > +
+ + +
+ +
+ + + +
+
+ + + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + } + onChange={[Function]} + pagination={ + Object { + "hidePerPageOptions": undefined, + "pageIndex": 0, + "pageSize": 10, + "pageSizeOptions": Array [ + 10, + 20, + 50, + ], + "totalItemCount": 2, + } + } + responsive={true} + selection={ + Object { + "onSelectionChange": [Function], + } + } + sorting={ + Object { + "allowNeutralSort": true, + "sort": undefined, + } + } + tableLayout="fixed" + > +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + +
+ + +
+ +
+ + + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + +
+
+
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + +
+ +
+
+ + +
+
+ + + + + + + + + + + + + + Actions + + + + + +
+
+ + +
+ +
+
+ + +
+
+
+ Title +
+
+ + + +
+
+
+ Type +
+
+ + dashboardSavedObjects + +
+
+
+ Description +
+
+ + dashboard0 desc + +
+
+
+ Last updated +
+
+
+
+ + + + + + + + + + Edit + + + + + + +
+
+
+ + +
+ +
+
+ + +
+
+
+ Title +
+
+ + + +
+
+
+ Type +
+
+ + dashboardSavedObjects + +
+
+
+ Description +
+
+ + dashboard1 desc + +
+
+
+ Last updated +
+
+
+
+ + + + + + + + + + Edit + + + + + + +
+
+
+
+ +
+ +
+ + + +
+ +
+ + + : + 10 + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + +
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+ +
+ +
+ +
+
+ + +
@@ -4981,6 +10958,7 @@ exports[`dashboard listing renders warning when listingLimit is exceeded 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], + "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -5953,11 +11931,2231 @@ exports[`dashboard listing renders warning when listingLimit is exceeded 1`] = ` data-test-subj="dashboardLandingPage" >
+ > + + +
+
+ +
+ +
+ +

+ Dashboards +

+
+
+
+ + +
+ + + + + +
+
+
+
+
+ +
+ + + } + > +
+
+ + + + Listing limit exceeded + + +
+ +
+ +
+

+ + + , + "entityNamePlural": "dashboards", + "listingLimitText": + listingLimit + , + "listingLimitValue": 1, + "totalItems": 2, + } + } + > + You have 2 dashboards, but your + + listingLimit + + setting prevents the table below from displaying more than 1. You can change this setting under + + + + Advanced Settings + + + + . + +

+
+
+
+
+
+
+ +
+ + + } + pagination={ + Object { + "initialPageIndex": 0, + "initialPageSize": 10, + "pageSizeOptions": Array [ + 10, + 20, + 50, + ], + } + } + responsive={true} + search={ + Object { + "box": Object { + "incremental": true, + }, + "defaultQuery": "", + "onChange": [Function], + "toolsLeft": undefined, + } + } + selection={ + Object { + "onSelectionChange": [Function], + } + } + sorting={true} + tableLayout="fixed" + > +
+ + +
+ +
+ + + +
+
+ + + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + } + onChange={[Function]} + pagination={ + Object { + "hidePerPageOptions": undefined, + "pageIndex": 0, + "pageSize": 10, + "pageSizeOptions": Array [ + 10, + 20, + 50, + ], + "totalItemCount": 2, + } + } + responsive={true} + selection={ + Object { + "onSelectionChange": [Function], + } + } + sorting={ + Object { + "allowNeutralSort": true, + "sort": undefined, + } + } + tableLayout="fixed" + > +
+
+ +
+ +
+ +
+ + +
+ +
+ +
+ + +
+ + +
+ +
+ + + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + +
+
+
+
+
+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + +
+ +
+
+ + +
+
+ + + + + + + + + + + + + + Actions + + + + + +
+
+ + +
+ +
+
+ + +
+
+
+ Title +
+
+ + + +
+
+
+ Type +
+
+ + dashboardSavedObjects + +
+
+
+ Description +
+
+ + dashboard0 desc + +
+
+
+ Last updated +
+
+
+
+ + + + + + + + + + Edit + + + + + + +
+
+
+ + +
+ +
+
+ + +
+
+
+ Title +
+
+ + + +
+
+
+ Type +
+
+ + dashboardSavedObjects + +
+
+
+ Description +
+
+ + dashboard1 desc + +
+
+
+ Last updated +
+
+
+
+ + + + + + + + + + Edit + + + + + + +
+
+
+
+ +
+ +
+ + + +
+ +
+ + + : + 10 + + } + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > +
+
+ + + +
+
+
+
+
+ +
+ + + +
+
+
+
+
+
+ +
+ +
+ +
+
+ + +
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 51679fa90b36..eddaf7bb899e 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,6 +206,7 @@ exports[`Dashboard top nav render in embed mode 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], + "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], @@ -1177,6 +1178,7 @@ 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], @@ -2148,6 +2150,7 @@ 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], @@ -3119,6 +3122,7 @@ 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], @@ -4090,6 +4094,7 @@ 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], @@ -5061,6 +5066,7 @@ exports[`Dashboard top nav render with all components 1`] = ` "registerCenter": [MockFunction], "registerLeft": [MockFunction], "registerRight": [MockFunction], + "registerRightNavigation": [MockFunction], }, "navLinks": Object { "enableForcedAppSwitcherNavigation": [MockFunction], From e1663a55299051b4fcc365803c7165f96626982c Mon Sep 17 00:00:00 2001 From: tygao Date: Mon, 22 Apr 2024 12:07:59 +0800 Subject: [PATCH 09/16] doc: update changelog Signed-off-by: tygao --- CHANGELOG.md | 2 +- .../dashboard_listing.test.tsx.snap | 8203 +---------------- 2 files changed, 6 insertions(+), 8199 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9578e8444a8f..cf7b7738f408 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 reigster standard top right navigation and add dev tool to top right navigation. ([#6553](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6553)) +- 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)) ### 🐛 Bug Fixes 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 f1197ef1f6f5..2015746a2a3b 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 @@ -1130,1481 +1130,11 @@ exports[`dashboard listing hideWriteControls 1`] = ` data-test-subj="dashboardLandingPage" >
- - -
-
- -
- -
- -

- Dashboards -

-
-
-
-
-
- -
- - - } - pagination={ - Object { - "initialPageIndex": 0, - "initialPageSize": 10, - "pageSizeOptions": Array [ - 10, - 20, - 50, - ], - } - } - responsive={true} - search={ - Object { - "box": Object { - "incremental": true, - }, - "defaultQuery": "", - "onChange": [Function], - "toolsLeft": undefined, - } - } - sorting={true} - tableLayout="fixed" - > -
- - -
- -
- - - -
-
- - - - -
- - - - - -
-
-
-
-
-
-
-
-
-
-
-
- -
- - - } - onChange={[Function]} - pagination={ - Object { - "hidePerPageOptions": undefined, - "pageIndex": 0, - "pageSize": 10, - "pageSizeOptions": Array [ - 10, - 20, - 50, - ], - "totalItemCount": 2, - } - } - responsive={true} - sorting={ - Object { - "allowNeutralSort": true, - "sort": undefined, - } - } - tableLayout="fixed" - > -
-
- -
- -
- -
- - -
- -
- - - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - -
-
-
-
-
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - - -
-
- Title -
-
- - - -
-
-
- Type -
-
- - dashboardSavedObjects - -
-
-
- Description -
-
- - dashboard0 desc - -
-
-
- Last updated -
-
-
-
- Title -
-
- - - -
-
-
- Type -
-
- - dashboardSavedObjects - -
-
-
- Description -
-
- - dashboard1 desc - -
-
-
- Last updated -
-
-
-
-
- -
- -
- - - -
- -
- - - : - 10 - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - -
-
-
-
-
- -
- - - -
-
-
-
-
-
- -
- -
- -
-
- - -
+ />
@@ -3807,2151 +2337,11 @@ exports[`dashboard listing render table listing with initial filters from URL 1` data-test-subj="dashboardLandingPage" >
- - -
-
- -
- -
- -

- Dashboards -

-
-
-
- - -
- - - - - -
-
-
-
-
- -
- - - } - pagination={ - Object { - "initialPageIndex": 0, - "initialPageSize": 10, - "pageSizeOptions": Array [ - 10, - 20, - 50, - ], - } - } - responsive={true} - search={ - Object { - "box": Object { - "incremental": true, - }, - "defaultQuery": "dashboard", - "onChange": [Function], - "toolsLeft": undefined, - } - } - selection={ - Object { - "onSelectionChange": [Function], - } - } - sorting={true} - tableLayout="fixed" - > -
- - -
- -
- - - -
-
- - - - -
- - - - - -
-
- - - - - -
-
-
-
-
-
-
-
-
-
-
-
- -
- - - } - onChange={[Function]} - pagination={ - Object { - "hidePerPageOptions": undefined, - "pageIndex": 0, - "pageSize": 10, - "pageSizeOptions": Array [ - 10, - 20, - 50, - ], - "totalItemCount": 2, - } - } - responsive={true} - selection={ - Object { - "onSelectionChange": [Function], - } - } - sorting={ - Object { - "allowNeutralSort": true, - "sort": undefined, - } - } - tableLayout="fixed" - > -
-
- -
- -
- -
- - -
- -
- -
- - -
- - -
- -
- - - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - -
-
-
-
-
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - -
- -
-
- - -
-
- - - - - - - - - - - - - - Actions - - - - - -
-
- - -
- -
-
- - -
-
-
- Title -
-
- - - -
-
-
- Type -
-
- - dashboardSavedObjects - -
-
-
- Description -
-
- - dashboard0 desc - -
-
-
- Last updated -
-
-
-
- - - - - - - - - - Edit - - - - - - -
-
-
- - -
- -
-
- - -
-
-
- Title -
-
- - - -
-
-
- Type -
-
- - dashboardSavedObjects - -
-
-
- Description -
-
- - dashboard1 desc - -
-
-
- Last updated -
-
-
-
- - - - - - - - - - Edit - - - - - - -
-
-
-
- -
- -
- - - -
- -
- - - : - 10 - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - -
-
-
-
-
- -
- - - -
-
-
-
-
-
- -
- -
- -
-
- - -
+ />
@@ -7154,274 +3544,11 @@ exports[`dashboard listing renders call to action when no dashboards exist 1`] = data-test-subj="dashboardLandingPage" >
- - -
- - - - } - body={ - -

- -

-

- - - , - } - } - /> -

-
- } - iconType="dashboardApp" - title={ -

- -

- } - > -
- - - - -
- - -

- - Create your first dashboard - -

-
- - - -
- - -
-

- - You can combine data views from any OpenSearch Dashboards app into one dashboard and see everything in one place. - -

-

- - - , - } - } - > - New to OpenSearch Dashboards? - - - - to take a test drive. - -

-
-
- - - -
- - - - - - -
- -
- - -
+ />
@@ -8624,2111 +4751,11 @@ exports[`dashboard listing renders table rows 1`] = ` data-test-subj="dashboardLandingPage" >
- - -
-
- -
- -
- -

- Dashboards -

-
-
-
- - -
- - - - - -
-
-
-
-
- -
- - - } - pagination={ - Object { - "initialPageIndex": 0, - "initialPageSize": 10, - "pageSizeOptions": Array [ - 10, - 20, - 50, - ], - } - } - responsive={true} - search={ - Object { - "box": Object { - "incremental": true, - }, - "defaultQuery": "", - "onChange": [Function], - "toolsLeft": undefined, - } - } - selection={ - Object { - "onSelectionChange": [Function], - } - } - sorting={true} - tableLayout="fixed" - > -
- - -
- -
- - - -
-
- - - - -
- - - - - -
-
-
-
-
-
-
-
-
-
-
-
- -
- - - } - onChange={[Function]} - pagination={ - Object { - "hidePerPageOptions": undefined, - "pageIndex": 0, - "pageSize": 10, - "pageSizeOptions": Array [ - 10, - 20, - 50, - ], - "totalItemCount": 2, - } - } - responsive={true} - selection={ - Object { - "onSelectionChange": [Function], - } - } - sorting={ - Object { - "allowNeutralSort": true, - "sort": undefined, - } - } - tableLayout="fixed" - > -
-
- -
- -
- -
- - -
- -
- -
- - -
- - -
- -
- - - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - -
-
-
-
-
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - -
- -
-
- - -
-
- - - - - - - - - - - - - - Actions - - - - - -
-
- - -
- -
-
- - -
-
-
- Title -
-
- - - -
-
-
- Type -
-
- - dashboardSavedObjects - -
-
-
- Description -
-
- - dashboard0 desc - -
-
-
- Last updated -
-
-
-
- - - - - - - - - - Edit - - - - - - -
-
-
- - -
- -
-
- - -
-
-
- Title -
-
- - - -
-
-
- Type -
-
- - dashboardSavedObjects - -
-
-
- Description -
-
- - dashboard1 desc - -
-
-
- Last updated -
-
-
-
- - - - - - - - - - Edit - - - - - - -
-
-
-
- -
- -
- - - -
- -
- - - : - 10 - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - -
-
-
-
-
- -
- - - -
-
-
-
-
-
- -
- -
- -
-
- - -
+ />
@@ -11931,2231 +5958,11 @@ exports[`dashboard listing renders warning when listingLimit is exceeded 1`] = ` data-test-subj="dashboardLandingPage" >
- - -
-
- -
- -
- -

- Dashboards -

-
-
-
- - -
- - - - - -
-
-
-
-
- -
- - - } - > -
-
- - - - Listing limit exceeded - - -
- -
- -
-

- - - , - "entityNamePlural": "dashboards", - "listingLimitText": - listingLimit - , - "listingLimitValue": 1, - "totalItems": 2, - } - } - > - You have 2 dashboards, but your - - listingLimit - - setting prevents the table below from displaying more than 1. You can change this setting under - - - - Advanced Settings - - - - . - -

-
-
-
-
-
-
- -
- - - } - pagination={ - Object { - "initialPageIndex": 0, - "initialPageSize": 10, - "pageSizeOptions": Array [ - 10, - 20, - 50, - ], - } - } - responsive={true} - search={ - Object { - "box": Object { - "incremental": true, - }, - "defaultQuery": "", - "onChange": [Function], - "toolsLeft": undefined, - } - } - selection={ - Object { - "onSelectionChange": [Function], - } - } - sorting={true} - tableLayout="fixed" - > -
- - -
- -
- - - -
-
- - - - -
- - - - - -
-
-
-
-
-
-
-
-
-
-
-
- -
- - - } - onChange={[Function]} - pagination={ - Object { - "hidePerPageOptions": undefined, - "pageIndex": 0, - "pageSize": 10, - "pageSizeOptions": Array [ - 10, - 20, - 50, - ], - "totalItemCount": 2, - } - } - responsive={true} - selection={ - Object { - "onSelectionChange": [Function], - } - } - sorting={ - Object { - "allowNeutralSort": true, - "sort": undefined, - } - } - tableLayout="fixed" - > -
-
- -
- -
- -
- - -
- -
- -
- - -
- - -
- -
- - - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - -
-
-
-
-
-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - -
- -
-
- - -
-
- - - - - - - - - - - - - - Actions - - - - - -
-
- - -
- -
-
- - -
-
-
- Title -
-
- - - -
-
-
- Type -
-
- - dashboardSavedObjects - -
-
-
- Description -
-
- - dashboard0 desc - -
-
-
- Last updated -
-
-
-
- - - - - - - - - - Edit - - - - - - -
-
-
- - -
- -
-
- - -
-
-
- Title -
-
- - - -
-
-
- Type -
-
- - dashboardSavedObjects - -
-
-
- Description -
-
- - dashboard1 desc - -
-
-
- Last updated -
-
-
-
- - - - - - - - - - Edit - - - - - - -
-
-
-
- -
- -
- - - -
- -
- - - : - 10 - - } - closePopover={[Function]} - display="inlineBlock" - hasArrow={true} - isOpen={false} - ownFocus={true} - panelPaddingSize="none" - > -
-
- - - -
-
-
-
-
- -
- - - -
-
-
-
-
-
- -
- -
- -
-
- - -
+ />
From 39663385f1c16d3bf7d1eb32886cab85555e7226 Mon Sep 17 00:00:00 2001 From: tygao Date: Mon, 22 Apr 2024 18:32:13 +0800 Subject: [PATCH 10/16] update click handle Signed-off-by: tygao --- .../nav_controls/nav_controls_service.ts | 9 ++++---- .../ui/header/right_navigation_button.tsx | 22 ++++++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) 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 64cd67d089ec..ede33106ed2c 100644 --- a/src/core/public/chrome/nav_controls/nav_controls_service.ts +++ b/src/core/public/chrome/nav_controls/nav_controls_service.ts @@ -102,15 +102,16 @@ 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: (navControl: ChromeNavControl) => - navControlsRight$.next(new Set([...navControlsRight$.value.values(), navControl])), - + registerRight, registerCenter: (navControl: ChromeNavControl) => navControlsCenter$.next(new Set([...navControlsCenter$.value.values(), navControl])), @@ -134,7 +135,7 @@ export class NavControlsService { }) ), }; - return navControlsRight$.next(new Set([...navControlsRight$.value.values(), nav])); + return registerRight(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 index 04338f5fe56a..30acde410961 100644 --- a/src/core/public/chrome/ui/header/right_navigation_button.tsx +++ b/src/core/public/chrome/ui/header/right_navigation_button.tsx @@ -4,10 +4,10 @@ */ import { EuiHeaderSectionItemButton, EuiIcon } from '@elastic/eui'; -import React from 'react'; +import React, { useMemo } from 'react'; import { InternalApplicationStart } from '../../../application'; import { HttpStart } from '../../../http'; - +import { isModifiedOrPrevented } from './nav_link'; export interface RightNavigationButtonProps { application: InternalApplicationStart; http: HttpStart; @@ -23,16 +23,27 @@ export const RightNavigationButton = ({ iconType, title, }: RightNavigationButtonProps) => { - const navigateToApp = () => { + const targetUrl = useMemo(() => { 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), { + return http.basePath.prepend(http.basePath.remove(appUrl), { withoutClientBasePath: true, }); - application.navigateToUrl(targetUrl); + }, [application.getUrlForApp, http.basePath]); + + const navigateToApp = (event: React.MouseEvent) => { + /* Use href and onClick to support "open in new tab" and SPA navigation in the same link */ + if ( + event.button === 0 && // ignore everything but left clicks + !isModifiedOrPrevented(event) + ) { + event.preventDefault(); + application.navigateToUrl(targetUrl); + } + return; }; return ( @@ -40,6 +51,7 @@ export const RightNavigationButton = ({ data-test-subj="rightNavigationButton" aria-label={title} onClick={navigateToApp} + href={targetUrl} > From 30c0ee57a50e70b11390bdd6d1f3d193a68279b1 Mon Sep 17 00:00:00 2001 From: tygao Date: Mon, 22 Apr 2024 18:32:21 +0800 Subject: [PATCH 11/16] update click handle Signed-off-by: tygao --- src/core/public/chrome/ui/header/right_navigation_button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 30acde410961..0c1333cbfffc 100644 --- a/src/core/public/chrome/ui/header/right_navigation_button.tsx +++ b/src/core/public/chrome/ui/header/right_navigation_button.tsx @@ -32,7 +32,7 @@ export const RightNavigationButton = ({ return http.basePath.prepend(http.basePath.remove(appUrl), { withoutClientBasePath: true, }); - }, [application.getUrlForApp, http.basePath]); + }, [application, http.basePath, appId]); const navigateToApp = (event: React.MouseEvent) => { /* Use href and onClick to support "open in new tab" and SPA navigation in the same link */ From c5ff56123b2a1c9eb3da99dc4bbfdcbd3ca08d97 Mon Sep 17 00:00:00 2001 From: tygao Date: Tue, 23 Apr 2024 15:57:57 +0800 Subject: [PATCH 12/16] doc: add doc for registerRightNavigation Signed-off-by: tygao --- src/core/public/chrome/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/public/chrome/README.md b/src/core/public/chrome/README.md index 6ec765a3bb0b..5911f165f15c 100644 --- a/src/core/public/chrome/README.md +++ b/src/core/public/chrome/README.md @@ -41,6 +41,19 @@ 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` From 2d1a8ee4f4b413d20716f2acbd53bfba7026966c Mon Sep 17 00:00:00 2001 From: tygao Date: Wed, 24 Apr 2024 18:52:21 +0800 Subject: [PATCH 13/16] Add `rightNavigationButton` component in chrome service for applications to register and add dev tool to top right navigation. Signed-off-by: tygao --- CHANGELOG.md | 2 +- src/core/public/chrome/README.md | 13 ----- src/core/public/chrome/chrome_service.mock.ts | 1 - src/core/public/chrome/chrome_service.tsx | 2 +- src/core/public/chrome/index.ts | 2 +- .../nav_controls/nav_controls_service.test.ts | 50 +------------------ .../nav_controls/nav_controls_service.ts | 42 ++-------------- src/core/public/chrome/ui/header/index.ts | 1 + .../ui/header/right_navigation_button.tsx | 8 +-- src/core/public/chrome/ui/index.ts | 2 + src/core/public/index.ts | 4 ++ .../dashboard_listing.test.tsx.snap | 7 +-- .../dashboard_top_nav.test.tsx.snap | 8 +-- .../dev_tools/opensearch_dashboards.json | 3 +- src/plugins/dev_tools/public/plugin.ts | 17 +++++-- 15 files changed, 37 insertions(+), 125 deletions(-) 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, + }) + ), }); } From 64051a6dc6b787e4b07d130d0c4278197eb55a78 Mon Sep 17 00:00:00 2001 From: tygao Date: Fri, 26 Apr 2024 14:54:06 +0800 Subject: [PATCH 14/16] test: update core start type Signed-off-by: tygao --- .../public/chrome/ui/header/right_navigation_button.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/public/chrome/ui/header/right_navigation_button.test.tsx b/src/core/public/chrome/ui/header/right_navigation_button.test.tsx index 9fdb1d7e4512..bbc77af24111 100644 --- a/src/core/public/chrome/ui/header/right_navigation_button.test.tsx +++ b/src/core/public/chrome/ui/header/right_navigation_button.test.tsx @@ -9,7 +9,7 @@ import { RightNavigationButton } from './right_navigation_button'; import { applicationServiceMock, httpServiceMock } from '../../../../../core/public/mocks'; const mockProps = { - application: applicationServiceMock.createInternalStartContract(), + application: applicationServiceMock.createStartContract(), http: httpServiceMock.createStartContract(), appId: 'app_id', iconType: 'mock_icon', @@ -28,7 +28,7 @@ describe('Right navigation button', () => { const props = { ...mockProps, application: { - ...applicationServiceMock.createInternalStartContract(), + ...applicationServiceMock.createStartContract(), getUrlForApp, navigateToUrl, }, From 57881d71f61ec08fd029349b697ffa35b12cab43 Mon Sep 17 00:00:00 2001 From: tygao Date: Mon, 29 Apr 2024 21:48:08 +0800 Subject: [PATCH 15/16] update RightNavigationOrder value Signed-off-by: tygao --- src/core/public/chrome/constants.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/public/chrome/constants.ts b/src/core/public/chrome/constants.ts index 31aa4fc6675d..4f98257ea5f8 100644 --- a/src/core/public/chrome/constants.ts +++ b/src/core/public/chrome/constants.ts @@ -34,6 +34,6 @@ export const GITHUB_CREATE_ISSUE_LINK = export enum RightNavigationOrder { // order of dev tool should be after advance settings - Settings = 1, - DevTool = 2, + Settings = 10, + DevTool = 20, } From 052a1fd9d80558767cf4e0a97cab97fc16fe25eb Mon Sep 17 00:00:00 2001 From: tygao Date: Mon, 29 Apr 2024 21:51:11 +0800 Subject: [PATCH 16/16] extract left click function Signed-off-by: tygao --- .../public/chrome/ui/header/right_navigation_button.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 c70386325b30..31464759aea5 100644 --- a/src/core/public/chrome/ui/header/right_navigation_button.tsx +++ b/src/core/public/chrome/ui/header/right_navigation_button.tsx @@ -34,10 +34,14 @@ export const RightNavigationButton = ({ }); }, [application, http.basePath, appId]); + const isLeftClickEvent = (event: React.MouseEvent) => { + return event.button === 0; + }; + const navigateToApp = (event: React.MouseEvent) => { /* Use href and onClick to support "open in new tab" and SPA navigation in the same link */ if ( - event.button === 0 && // ignore everything but left clicks + isLeftClickEvent(event) && // ignore everything but left clicks !isModifiedOrPrevented(event) ) { event.preventDefault();