From a663a84d06806942c8724995ae420cebc028289a Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Tue, 1 Oct 2024 00:46:10 +0800 Subject: [PATCH] [navigation]feat: remember state when expand / collapse left nav (#8286) * feat: remember state Signed-off-by: SuZhou-Joe * Changeset file for PR #8286 created/updated * feat: optimize code Signed-off-by: SuZhou-Joe * feat: update Signed-off-by: SuZhou-Joe --------- Signed-off-by: SuZhou-Joe Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> --- changelogs/fragments/8286.yml | 2 ++ .../collapsible_nav_group_enabled.test.tsx | 2 -- .../header/collapsible_nav_group_enabled.tsx | 5 ----- .../public/chrome/ui/header/header.test.tsx | 15 +++++++++++++ src/core/public/chrome/ui/header/header.tsx | 22 +++++++++++++++---- 5 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 changelogs/fragments/8286.yml diff --git a/changelogs/fragments/8286.yml b/changelogs/fragments/8286.yml new file mode 100644 index 000000000000..fce477aa351c --- /dev/null +++ b/changelogs/fragments/8286.yml @@ -0,0 +1,2 @@ +feat: +- [navigation] remember state when expand / collapse left nav ([#8286](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8286)) \ No newline at end of file diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.test.tsx b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.test.tsx index 418dca694e21..e332cb2dac59 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.test.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.test.tsx @@ -69,7 +69,6 @@ describe('', () => { appId$: new BehaviorSubject('test'), basePath: mockBasePath, id: 'collapsibe-nav', - isLocked: false, isNavOpen: false, currentWorkspace$: new BehaviorSubject({ id: 'test', name: 'test' }), navLinks$: new BehaviorSubject([ @@ -94,7 +93,6 @@ describe('', () => { ...(props?.navLinks || []), ]), storage: new StubBrowserStorage(), - onIsLockedUpdate: () => {}, closeNav: () => {}, navigateToApp: () => Promise.resolve(), navigateToUrl: () => Promise.resolve(), diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx index d08e2a413d42..c1c9d518a219 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.tsx @@ -23,7 +23,6 @@ import { ChromeNavControl, ChromeNavLink } from '../..'; import { AppCategory, NavGroupType } from '../../../../types'; import { InternalApplicationStart } from '../../../application/types'; import { HttpStart } from '../../../http'; -import { OnIsLockedUpdate } from './'; import { createEuiListItem } from './nav_link'; import type { Logos } from '../../../../common/types'; import { @@ -42,11 +41,9 @@ export interface CollapsibleNavGroupEnabledProps { collapsibleNavHeaderRender?: () => JSX.Element | null; basePath: HttpStart['basePath']; id: string; - isLocked: boolean; isNavOpen: boolean; navLinks$: Rx.Observable; storage?: Storage; - onIsLockedUpdate: OnIsLockedUpdate; closeNav: () => void; navigateToApp: InternalApplicationStart['navigateToApp']; navigateToUrl: InternalApplicationStart['navigateToUrl']; @@ -80,10 +77,8 @@ enum NavWidth { export function CollapsibleNavGroupEnabled({ basePath, id, - isLocked, isNavOpen, storage = window.localStorage, - onIsLockedUpdate, closeNav, navigateToApp, navigateToUrl, diff --git a/src/core/public/chrome/ui/header/header.test.tsx b/src/core/public/chrome/ui/header/header.test.tsx index c9fc84ef362c..f6a10aefc74c 100644 --- a/src/core/public/chrome/ui/header/header.test.tsx +++ b/src/core/public/chrome/ui/header/header.test.tsx @@ -257,4 +257,19 @@ describe('Header', () => { expect(component.find('[data-test-subj="headerRightControl"]').exists()).toBeFalsy(); expect(component).toMatchSnapshot(); }); + + it('should remember the collapse state when new nav is enabled', () => { + const branding = { + useExpandedHeader: false, + }; + const props = { + ...mockProps(), + branding, + useUpdatedHeader: true, + onIsLockedUpdate: jest.fn(), + }; + const component = mountWithIntl(
); + component.find(EuiHeaderSectionItemButton).first().simulate('click'); + expect(props.onIsLockedUpdate).toBeCalledWith(true); + }); }); diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index e92ac628b1a9..784eb0dfc464 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -45,7 +45,7 @@ import { } from '@elastic/eui'; import { i18n } from '@osd/i18n'; import classnames from 'classnames'; -import React, { createRef, useMemo, useState } from 'react'; +import React, { createRef, useCallback, useMemo, useState } from 'react'; import useObservable from 'react-use/lib/useObservable'; import { Observable } from 'rxjs'; import { LoadingIndicator } from '../'; @@ -153,7 +153,7 @@ export function Header({ const isVisible = useObservable(observables.isVisible$, false); const headerVariant = useObservable(observables.headerVariant$, HeaderVariant.PAGE); const isLocked = useObservable(observables.isLocked$, false); - const [isNavOpen, setIsNavOpen] = useState(false); + const [isNavOpenState, setIsNavOpenState] = useState(false); const sidecarConfig = useObservable(observables.sidecarConfig$, undefined); const breadcrumbs = useObservable(observables.breadcrumbs$, []); @@ -177,6 +177,22 @@ export function Header({ return getOsdSidecarPaddingStyle(sidecarConfig); }, [sidecarConfig]); + const isNavOpen = useUpdatedHeader ? isLocked : isNavOpenState; + + const setIsNavOpen = useCallback( + (value) => { + /** + * When use updated header, we will regard the lock state as source of truth + */ + if (useUpdatedHeader) { + onIsLockedUpdate(value); + } else { + setIsNavOpenState(value); + } + }, + [setIsNavOpenState, onIsLockedUpdate, useUpdatedHeader] + ); + if (!isVisible) { return ; } @@ -616,13 +632,11 @@ export function Header({ appId$={application.currentAppId$} collapsibleNavHeaderRender={collapsibleNavHeaderRender} id={navId} - isLocked={isLocked} navLinks$={observables.navLinks$} isNavOpen={isNavOpen} basePath={basePath} navigateToApp={application.navigateToApp} navigateToUrl={application.navigateToUrl} - onIsLockedUpdate={onIsLockedUpdate} closeNav={() => { setIsNavOpen(false); if (toggleCollapsibleNavRef.current) {