From d49631da49232a640714056a06156c1660371944 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Thu, 8 Aug 2024 15:00:53 +0800 Subject: [PATCH 01/23] feat: change nav groups Signed-off-by: SuZhou-Joe --- src/core/utils/default_app_categories.ts | 7 +++ .../data_source_management/public/plugin.ts | 45 +++---------------- src/plugins/home/public/plugin.ts | 26 +---------- .../index_pattern_management/public/plugin.ts | 43 ++---------------- .../saved_objects_management/public/plugin.ts | 43 ++---------------- src/plugins/workspace/public/plugin.ts | 35 +++++++++++++++ 6 files changed, 55 insertions(+), 144 deletions(-) diff --git a/src/core/utils/default_app_categories.ts b/src/core/utils/default_app_categories.ts index e68e1667e22..412336817f1 100644 --- a/src/core/utils/default_app_categories.ts +++ b/src/core/utils/default_app_categories.ts @@ -130,4 +130,11 @@ export const DEFAULT_APP_CATEGORIES: Record = Object.freeze }), order: 1000, }, + manageWorkspace: { + id: 'manageWorkspace', + label: i18n.translate('core.ui.manageWorkspaceNav.label', { + defaultMessage: 'Manage workspace', + }), + order: 8000, + }, }); diff --git a/src/plugins/data_source_management/public/plugin.ts b/src/plugins/data_source_management/public/plugin.ts index c384e30089f..e9eb5d17088 100644 --- a/src/plugins/data_source_management/public/plugin.ts +++ b/src/plugins/data_source_management/public/plugin.ts @@ -93,6 +93,9 @@ export interface DataSourceManagementPluginStart { getAuthenticationMethodRegistry: () => IAuthenticationMethodRegistry; } +/** + * The id is used in src/plugins/workspace/public/plugin.ts and please change that accordingly if you change the id here. + */ export const DSM_APP_ID = 'dataSources'; export class DataSourceManagementPlugin @@ -145,6 +148,8 @@ export class DataSourceManagementPlugin /** * The data sources features in observability has the same name as `DSM_APP_ID` * Add a suffix to avoid duplication + * + * The id is used in src/plugins/workspace/public/plugin.ts and please change that accordingly if you change the id here. */ const DSM_APP_ID_FOR_STANDARD_APPLICATION = `${DSM_APP_ID}_core`; @@ -181,46 +186,6 @@ export class DataSourceManagementPlugin }, ]); - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.observability, [ - { - id: DSM_APP_ID_FOR_STANDARD_APPLICATION, - category: DEFAULT_APP_CATEGORIES.manage, - order: 100, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.search, [ - { - id: DSM_APP_ID_FOR_STANDARD_APPLICATION, - category: DEFAULT_APP_CATEGORIES.manage, - order: 100, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS['security-analytics'], [ - { - id: DSM_APP_ID_FOR_STANDARD_APPLICATION, - category: DEFAULT_APP_CATEGORIES.manage, - order: 100, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.analytics, [ - { - id: DSM_APP_ID_FOR_STANDARD_APPLICATION, - category: DEFAULT_APP_CATEGORIES.manage, - order: 100, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.all, [ - { - id: DSM_APP_ID_FOR_STANDARD_APPLICATION, - category: DEFAULT_APP_CATEGORIES.manage, - order: 100, - }, - ]); - // when the feature flag is disabled, we don't need to register any of the mds components if (!this.featureFlagStatus) { return undefined; diff --git a/src/plugins/home/public/plugin.ts b/src/plugins/home/public/plugin.ts index 0e555f9a301..fe1099a8e63 100644 --- a/src/plugins/home/public/plugin.ts +++ b/src/plugins/home/public/plugin.ts @@ -64,7 +64,7 @@ import { PLUGIN_ID, HOME_APP_BASE_PATH, IMPORT_SAMPLE_DATA_APP_ID } from '../com import { DataSourcePluginStart } from '../../data_source/public'; import { workWithDataSection } from './application/components/homepage/sections/work_with_data'; import { learnBasicsSection } from './application/components/homepage/sections/learn_basics'; -import { DEFAULT_NAV_GROUPS, DEFAULT_APP_CATEGORIES } from '../../../core/public'; +import { DEFAULT_NAV_GROUPS } from '../../../core/public'; import { ContentManagementPluginSetup, ContentManagementPluginStart, @@ -179,9 +179,7 @@ export class HomePublicPlugin title: i18n.translate('home.tutorialDirectory.featureCatalogueTitle', { defaultMessage: 'Add sample data', }), - navLinkStatus: core.chrome.navGroup.getNavGroupEnabled() - ? AppNavLinkStatus.visible - : AppNavLinkStatus.hidden, + navLinkStatus: AppNavLinkStatus.hidden, mount: async (params: AppMountParameters) => { const [coreStart] = await core.getStartServices(); setCommonService(); @@ -196,26 +194,6 @@ export class HomePublicPlugin }); urlForwarding.forwardApp('home', 'home'); - const configurationInfoForImportSampleData = { - id: IMPORT_SAMPLE_DATA_APP_ID, - title: i18n.translate('home.nav.sampleData.label', { - defaultMessage: 'Sample data', - }), - order: 400, - category: DEFAULT_APP_CATEGORIES.manage, - }; - - // Register sample data to all of the use cases in 2.16 - [ - DEFAULT_NAV_GROUPS.all, - DEFAULT_NAV_GROUPS.analytics, - DEFAULT_NAV_GROUPS['security-analytics'], - DEFAULT_NAV_GROUPS.observability, - DEFAULT_NAV_GROUPS.search, - ].forEach((navGroup) => - core.chrome.navGroup.addNavLinksToGroup(navGroup, [configurationInfoForImportSampleData]) - ); - const featureCatalogue = { ...this.featuresCatalogueRegistry.setup() }; featureCatalogue.register({ diff --git a/src/plugins/index_pattern_management/public/plugin.ts b/src/plugins/index_pattern_management/public/plugin.ts index 36bc22c5d65..674470dd436 100644 --- a/src/plugins/index_pattern_management/public/plugin.ts +++ b/src/plugins/index_pattern_management/public/plugin.ts @@ -68,6 +68,9 @@ const sectionsHeader = i18n.translate('indexPatternManagement.indexPattern.secti defaultMessage: 'Index patterns', }); +/** + * The id is used in src/plugins/workspace/public/plugin.ts and please change that accordingly if you change the id here. + */ const IPM_APP_ID = 'indexPatterns'; export class IndexPatternManagementPlugin @@ -159,46 +162,6 @@ export class IndexPatternManagementPlugin }, }); - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.analytics, [ - { - id: IPM_APP_ID, - category: DEFAULT_APP_CATEGORIES.manage, - order: 200, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.observability, [ - { - id: IPM_APP_ID, - category: DEFAULT_APP_CATEGORIES.manage, - order: 200, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.search, [ - { - id: IPM_APP_ID, - category: DEFAULT_APP_CATEGORIES.manage, - order: 200, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS['security-analytics'], [ - { - id: IPM_APP_ID, - category: DEFAULT_APP_CATEGORIES.manage, - order: 200, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.all, [ - { - id: IPM_APP_ID, - category: DEFAULT_APP_CATEGORIES.manage, - order: 200, - }, - ]); - return this.indexPatternManagementService.setup({ httpClient: core.http }); } diff --git a/src/plugins/saved_objects_management/public/plugin.ts b/src/plugins/saved_objects_management/public/plugin.ts index 8529a955568..1521518a510 100644 --- a/src/plugins/saved_objects_management/public/plugin.ts +++ b/src/plugins/saved_objects_management/public/plugin.ts @@ -160,6 +160,9 @@ export class SavedObjectsManagementPlugin if (core.chrome.navGroup.getNavGroupEnabled()) { core.application.register({ + /** + * The id is used in src/plugins/workspace/public/plugin.ts and please change that accordingly if you change the id here. + */ id: 'objects', title: i18n.translate('savedObjectsManagement.assets.label', { defaultMessage: 'Assets', @@ -192,46 +195,6 @@ export class SavedObjectsManagementPlugin }, ]); - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.observability, [ - { - id: 'objects', - category: DEFAULT_APP_CATEGORIES.manage, - order: 300, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.search, [ - { - id: 'objects', - category: DEFAULT_APP_CATEGORIES.manage, - order: 300, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS['security-analytics'], [ - { - id: 'objects', - category: DEFAULT_APP_CATEGORIES.manage, - order: 300, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.analytics, [ - { - id: 'objects', - category: DEFAULT_APP_CATEGORIES.manage, - order: 300, - }, - ]); - - core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.all, [ - { - id: 'objects', - category: DEFAULT_APP_CATEGORIES.manage, - order: 300, - }, - ]); - // sets up the context mappings and registers any triggers/actions for the plugin bootstrap(uiActions); diff --git a/src/plugins/workspace/public/plugin.ts b/src/plugins/workspace/public/plugin.ts index 6516525bdbf..ac92d63809d 100644 --- a/src/plugins/workspace/public/plugin.ts +++ b/src/plugins/workspace/public/plugin.ts @@ -23,6 +23,7 @@ import { DEFAULT_NAV_GROUPS, NavGroupType, ALL_USE_CASE_ID, + DEFAULT_APP_CATEGORIES, } from '../../../core/public'; import { WORKSPACE_FATAL_ERROR_APP_ID, @@ -234,6 +235,38 @@ export class WorkspacePlugin }); } + /** + * Add nav links belong to `manage workspace` to all of the use cases. + * @param coreSetup + */ + private registerManageWorkspaceCategory(coreSetup: CoreSetup) { + [ + DEFAULT_NAV_GROUPS.all, + DEFAULT_NAV_GROUPS.analytics, + DEFAULT_NAV_GROUPS.observability, + DEFAULT_NAV_GROUPS.search, + DEFAULT_NAV_GROUPS['security-analytics'], + ].forEach((navGroup) => { + coreSetup.chrome.navGroup.addNavLinksToGroup(navGroup, [ + { + id: 'dataSources_core', + category: DEFAULT_APP_CATEGORIES.manageWorkspace, + order: 100, + }, + { + id: 'indexPatterns', + category: DEFAULT_APP_CATEGORIES.manageWorkspace, + order: 200, + }, + { + id: 'objects', + category: DEFAULT_APP_CATEGORIES.manageWorkspace, + order: 300, + }, + ]); + }); + } + public async setup( core: CoreSetup, { savedObjectsManagement, management, dataSourceManagement }: WorkspacePluginSetupDeps @@ -394,6 +427,8 @@ export class WorkspacePlugin }, ]); + this.registerManageWorkspaceCategory(core); + return {}; } From f09e773b6a685310deaaffd15b3b7eefc6922406 Mon Sep 17 00:00:00 2001 From: "opensearch-changeset-bot[bot]" <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 07:02:39 +0000 Subject: [PATCH 02/23] Changeset file for PR #7655 created/updated --- changelogs/fragments/7655.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/7655.yml diff --git a/changelogs/fragments/7655.yml b/changelogs/fragments/7655.yml new file mode 100644 index 00000000000..70a921f4e6d --- /dev/null +++ b/changelogs/fragments/7655.yml @@ -0,0 +1,2 @@ +feat: +- [navigation] Left navigation collective ([#7655](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7655)) \ No newline at end of file From f92e4f5cb4c461348593135a2964123546be51cb Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Thu, 8 Aug 2024 15:37:11 +0800 Subject: [PATCH 03/23] feat: move visualizations to all use case Signed-off-by: SuZhou-Joe --- src/plugins/visualize/public/plugin.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/visualize/public/plugin.ts b/src/plugins/visualize/public/plugin.ts index 3a2ffc13374..d266589f9a3 100644 --- a/src/plugins/visualize/public/plugin.ts +++ b/src/plugins/visualize/public/plugin.ts @@ -256,6 +256,13 @@ export class VisualizePlugin order: 400, }, ]); + core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.all, [ + { + id: visualizeAppId, + category: undefined, + order: 400, + }, + ]); urlForwarding.forwardApp('visualize', 'visualize'); From b72e50879da9c4f9448459da5c08efe89c9c64ae Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Thu, 8 Aug 2024 17:52:57 +0800 Subject: [PATCH 04/23] feat: change the scrollable area Signed-off-by: SuZhou-Joe --- .../header/collapsible_nav_group_enabled.scss | 2 +- .../header/collapsible_nav_group_enabled.tsx | 66 +++++++++++-------- .../collapsible_nav_group_enabled_top.tsx | 9 ++- src/plugins/management/public/plugin.ts | 4 +- 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.scss b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.scss index 77626cab7eb..c15f57d263b 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.scss +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.scss @@ -34,7 +34,7 @@ border-right: $ouiBorderThin; } - .scrollable-container { + .flex-1-container { flex: 1; } 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 c0d2a87635e..74a5529ade7 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 @@ -324,41 +324,51 @@ export function CollapsibleNavGroupEnabled({ paddingSize="none" >
-
+ {!isNavOpen ? null : ( - {!isNavOpen ? null : ( - <> - setCurrentNavGroup(undefined)} - currentNavGroup={currentNavGroup} - shouldShrinkNavigation={!isNavOpen} - onClickShrink={closeNav} - visibleUseCases={visibleUseCases} - /> - { - if (navItem.title === titleForSeeAll && navItem.category?.id) { - const navGroup = navGroupsMap[navItem.category.id]; - onGroupClick(event, navGroup); - } - }} - appId={appId} - /> - - )} + setCurrentNavGroup(undefined)} + currentNavGroup={currentNavGroup} + shouldShrinkNavigation={!isNavOpen} + onClickShrink={closeNav} + visibleUseCases={visibleUseCases} + /> -
+ )} + {!isNavOpen ? null : ( + + { + if (navItem.title === titleForSeeAll && navItem.category?.id) { + const navGroup = navGroupsMap[navItem.category.id]; + onGroupClick(event, navGroup); + } + }} + appId={appId} + /> + + )} + { + // This element is used to push icons to the bottom of left navigation when collapsed + !isNavOpen ?
: null + }
- +
{shouldShowHomeLink ? ( @@ -130,6 +130,11 @@ export const CollapsibleNavTop = ({ + +
+ {currentNavGroup?.title} +
+
); }; diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index d376feeafe7..0b0975eefb9 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -106,7 +106,7 @@ export class ManagementPlugin implements Plugin Date: Mon, 12 Aug 2024 11:59:22 +0800 Subject: [PATCH 05/23] feat: register manage workspace category when in a workspace Signed-off-by: SuZhou-Joe --- src/plugins/workspace/public/plugin.ts | 42 ++------- .../public/services/use_case_service.ts | 85 ++++++++++++++++++- 2 files changed, 90 insertions(+), 37 deletions(-) diff --git a/src/plugins/workspace/public/plugin.ts b/src/plugins/workspace/public/plugin.ts index 66192c6d4ee..13d8153e34c 100644 --- a/src/plugins/workspace/public/plugin.ts +++ b/src/plugins/workspace/public/plugin.ts @@ -235,44 +235,19 @@ export class WorkspacePlugin }); } - /** - * Add nav links belong to `manage workspace` to all of the use cases. - * @param coreSetup - */ - private registerManageWorkspaceCategory(coreSetup: CoreSetup) { - [ - DEFAULT_NAV_GROUPS.all, - DEFAULT_NAV_GROUPS.analytics, - DEFAULT_NAV_GROUPS.observability, - DEFAULT_NAV_GROUPS.search, - DEFAULT_NAV_GROUPS['security-analytics'], - ].forEach((navGroup) => { - coreSetup.chrome.navGroup.addNavLinksToGroup(navGroup, [ - { - id: 'dataSources_core', - category: DEFAULT_APP_CATEGORIES.manageWorkspace, - order: 100, - }, - { - id: 'indexPatterns', - category: DEFAULT_APP_CATEGORIES.manageWorkspace, - order: 200, - }, - { - id: 'objects', - category: DEFAULT_APP_CATEGORIES.manageWorkspace, - order: 300, - }, - ]); - }); - } - public async setup( core: CoreSetup, { savedObjectsManagement, management, dataSourceManagement }: WorkspacePluginSetupDeps ) { const workspaceClient = new WorkspaceClient(core.http, core.workspaces); await workspaceClient.init(); + + this.useCase.setup({ + chrome: core.chrome, + getStartServices: core.getStartServices, + workspaces: core.workspaces, + }); + core.application.registerAppUpdater(this.appUpdater$); this.unregisterNavGroupUpdater = core.chrome.navGroup.registerNavGroupUpdater( this.navGroupUpdater$ @@ -427,8 +402,6 @@ export class WorkspacePlugin }, ]); - this.registerManageWorkspaceCategory(core); - return {}; } @@ -538,5 +511,6 @@ export class WorkspacePlugin this.unregisterNavGroupUpdater?.(); this.registeredUseCasesUpdaterSubscription?.unsubscribe(); this.workspaceAndUseCasesCombineSubscription?.unsubscribe(); + this.useCase.stop(); } } diff --git a/src/plugins/workspace/public/services/use_case_service.ts b/src/plugins/workspace/public/services/use_case_service.ts index eed33795a49..ec0e973b6da 100644 --- a/src/plugins/workspace/public/services/use_case_service.ts +++ b/src/plugins/workspace/public/services/use_case_service.ts @@ -3,16 +3,91 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Observable } from 'rxjs'; +import { combineLatest, Observable, Subscription } from 'rxjs'; import { distinctUntilChanged, map } from 'rxjs/operators'; -import { ChromeStart, PublicAppInfo } from '../../../../core/public'; +import { + ChromeStart, + CoreSetup, + DEFAULT_APP_CATEGORIES, + PublicAppInfo, + WorkspacesSetup, +} from '../../../../core/public'; import { WORKSPACE_USE_CASES } from '../../common/constants'; -import { convertNavGroupToWorkspaceUseCase, isEqualWorkspaceUseCase } from '../utils'; +import { + convertNavGroupToWorkspaceUseCase, + getFirstUseCaseOfFeatureConfigs, + isEqualWorkspaceUseCase, +} from '../utils'; + +export interface UseCaseServiceSetupDeps { + chrome: CoreSetup['chrome']; + workspaces: WorkspacesSetup; + getStartServices: CoreSetup['getStartServices']; +} export class UseCaseService { + private workspaceAndManageWorkspaceCategorySubscription?: Subscription; constructor() {} + /** + * Add nav links belong to `manage workspace` to all of the use cases. + * @param coreSetup + * @param currentWorkspace + */ + private async registerManageWorkspaceCategory(setupDeps: UseCaseServiceSetupDeps) { + const [coreStart] = await setupDeps.getStartServices(); + this.workspaceAndManageWorkspaceCategorySubscription?.unsubscribe(); + this.workspaceAndManageWorkspaceCategorySubscription = combineLatest([ + setupDeps.workspaces.currentWorkspace$, + coreStart.chrome.navGroup.getNavGroupsMap$(), + ]) + .pipe( + map(([currentWorkspace, navGroupMap]) => { + const currentUseCase = getFirstUseCaseOfFeatureConfigs(currentWorkspace?.features || []); + if (!currentUseCase) { + return undefined; + } + + return navGroupMap[currentUseCase]; + }) + ) + .pipe( + distinctUntilChanged((navGroupInfo, anotherNavGroup) => { + return navGroupInfo?.id === anotherNavGroup?.id; + }) + ) + .subscribe((navGroupInfo) => { + if (navGroupInfo) { + setupDeps.chrome.navGroup.addNavLinksToGroup(navGroupInfo, [ + { + id: 'dataSources_core', + category: DEFAULT_APP_CATEGORIES.manageWorkspace, + order: 100, + }, + { + id: 'indexPatterns', + category: DEFAULT_APP_CATEGORIES.manageWorkspace, + order: 200, + }, + { + id: 'objects', + category: DEFAULT_APP_CATEGORIES.manageWorkspace, + order: 300, + }, + ]); + } + }); + } + + setup({ chrome, workspaces, getStartServices }: UseCaseServiceSetupDeps) { + this.registerManageWorkspaceCategory({ + chrome, + workspaces, + getStartServices, + }); + } + start({ chrome, workspaceConfigurableApps$, @@ -70,4 +145,8 @@ export class UseCaseService { }, }; } + + stop() { + this.workspaceAndManageWorkspaceCategorySubscription?.unsubscribe(); + } } From 3110391221bfce5281b5492c6cf78afd520c3d19 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Mon, 12 Aug 2024 12:00:30 +0800 Subject: [PATCH 06/23] feat: register index patterns to settings and setup Signed-off-by: SuZhou-Joe --- src/plugins/index_pattern_management/public/plugin.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/plugins/index_pattern_management/public/plugin.ts b/src/plugins/index_pattern_management/public/plugin.ts index 9b3041149dd..74ec2458709 100644 --- a/src/plugins/index_pattern_management/public/plugin.ts +++ b/src/plugins/index_pattern_management/public/plugin.ts @@ -46,7 +46,7 @@ import { } from './service'; import { ManagementSetup } from '../../management/public'; -import { AppStatus } from '../../../core/public'; +import { AppStatus, DEFAULT_NAV_GROUPS } from '../../../core/public'; import { getScopedBreadcrumbs } from '../../opensearch_dashboards_react/public'; export interface IndexPatternManagementSetupDependencies { @@ -162,6 +162,14 @@ export class IndexPatternManagementPlugin }, }); + core.chrome.navGroup.addNavLinksToGroup(DEFAULT_NAV_GROUPS.settingsAndSetup, [ + { + id: IPM_APP_ID, + title: sectionsHeader, + order: 400, + }, + ]); + return this.indexPatternManagementService.setup({ httpClient: core.http }); } From baacc38b2e9a67dd27ff72cf8ba3ebe0ee62eae9 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Mon, 12 Aug 2024 14:40:08 +0800 Subject: [PATCH 07/23] feat: show correct icon in top Signed-off-by: SuZhou-Joe --- src/core/public/chrome/chrome_service.tsx | 1 + .../header/collapsible_nav_group_enabled.tsx | 19 +++++- .../collapsible_nav_group_enabled_top.tsx | 64 ++++++++++--------- src/core/public/chrome/ui/header/header.tsx | 4 +- 4 files changed, 55 insertions(+), 33 deletions(-) diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 3b61ee3ee94..2c8160cb2df 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -319,6 +319,7 @@ export class ChromeService { navGroupsMap$={navGroup.getNavGroupsMap$()} setCurrentNavGroup={navGroup.setCurrentNavGroup} workspaceList$={workspaces.workspaceList$} + currentWorkspace$={workspaces.currentWorkspace$} /> ), 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 77dd57e8371..a1940f25cee 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 @@ -18,6 +18,7 @@ import React, { useMemo } from 'react'; import useObservable from 'react-use/lib/useObservable'; import * as Rx from 'rxjs'; import classNames from 'classnames'; +import { WorkspacesStart } from 'src/core/public/workspace'; import { ChromeNavControl, ChromeNavLink } from '../..'; import { AppCategory, NavGroupStatus } from '../../../../types'; import { InternalApplicationStart } from '../../../application/types'; @@ -59,6 +60,7 @@ export interface CollapsibleNavGroupEnabledProps { currentNavGroup$: Rx.Observable; setCurrentNavGroup: ChromeNavGroupServiceStartContract['setCurrentNavGroup']; capabilities: InternalApplicationStart['capabilities']; + currentWorkspace$: WorkspacesStart['currentWorkspace$']; } interface NavGroupsProps { @@ -224,10 +226,20 @@ export function CollapsibleNavGroupEnabled({ capabilities, ...observables }: CollapsibleNavGroupEnabledProps) { - const navLinks = useObservable(observables.navLinks$, []).filter((link) => !link.hidden); + const allNavLinks = useObservable(observables.navLinks$, []); + const navLinks = allNavLinks.filter((link) => !link.hidden); + const homeLink = useMemo(() => allNavLinks.find((item) => item.id === 'home'), [allNavLinks]); const appId = useObservable(observables.appId$, ''); const navGroupsMap = useObservable(observables.navGroupsMap$, {}); const currentNavGroup = useObservable(observables.currentNavGroup$, undefined); + const firstVisibleNavLinkOfAllUseCase = useMemo( + () => + fulfillRegistrationLinksToChromeNavLinks( + navGroupsMap[ALL_USE_CASE_ID]?.navLinks || [], + navLinks + )[0], + [navGroupsMap, navLinks] + ); const visibleUseCases = useMemo( () => @@ -364,14 +376,17 @@ export function CollapsibleNavGroupEnabled({ style={{ flexGrow: 0, paddingBottom: 0 }} > setCurrentNavGroup(undefined)} + setCurrentNavGroup={setCurrentNavGroup} currentNavGroup={currentNavGroup} shouldShrinkNavigation={!isNavOpen} onClickShrink={closeNav} visibleUseCases={visibleUseCases} + currentWorkspace$={observables.currentWorkspace$} /> )} diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx index 0c407fbea55..e4e7b81ff20 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx @@ -4,7 +4,8 @@ */ import React, { useMemo } from 'react'; -import { Logos } from 'opensearch-dashboards/public'; +import useObservable from 'react-use/lib/useObservable'; +import { Logos, WorkspacesStart } from 'opensearch-dashboards/public'; import { EuiButtonEmpty, EuiButtonIcon, @@ -17,19 +18,22 @@ import { import { InternalApplicationStart } from 'src/core/public/application'; import { i18n } from '@osd/i18n'; import { createEuiListItem } from './nav_link'; -import { NavGroupItemInMap } from '../../nav_group'; +import { ChromeNavGroupServiceStartContract, NavGroupItemInMap } from '../../nav_group'; import { ChromeNavLink } from '../../nav_links'; import { ALL_USE_CASE_ID } from '../../../../../core/utils'; export interface CollapsibleNavTopProps { + homeLink?: ChromeNavLink; + firstVisibleNavLinkOfAllUseCase?: ChromeNavLink; navLinks: ChromeNavLink[]; currentNavGroup?: NavGroupItemInMap; navigateToApp: InternalApplicationStart['navigateToApp']; logos: Logos; - onClickBack?: () => void; onClickShrink?: () => void; shouldShrinkNavigation: boolean; visibleUseCases: NavGroupItemInMap[]; + currentWorkspace$: WorkspacesStart['currentWorkspace$']; + setCurrentNavGroup: ChromeNavGroupServiceStartContract['setCurrentNavGroup']; } export const CollapsibleNavTop = ({ @@ -37,40 +41,39 @@ export const CollapsibleNavTop = ({ currentNavGroup, navigateToApp, logos, - onClickBack, onClickShrink, shouldShrinkNavigation, visibleUseCases, + currentWorkspace$, + setCurrentNavGroup, + homeLink, + firstVisibleNavLinkOfAllUseCase, }: CollapsibleNavTopProps) => { - const homeLink = useMemo(() => navLinks.find((link) => link.id === 'home'), [navLinks]); + const currentWorkspace = useObservable(currentWorkspace$); - const isOutsideWorkspace = useMemo( - () => !visibleUseCases.find((useCase) => useCase.id === currentNavGroup?.id), - [currentNavGroup, visibleUseCases] + const isAllUseCaseWorkspace = useMemo(() => visibleUseCases.length > 1 && !!currentWorkspace, [ + currentWorkspace, + visibleUseCases, + ]); + + const isInsideSecondLevel = useMemo( + () => isAllUseCaseWorkspace && currentNavGroup?.id !== ALL_USE_CASE_ID, + [isAllUseCaseWorkspace, currentNavGroup] ); const shouldShowBackButton = useMemo(() => { - if (!currentNavGroup || currentNavGroup.id === ALL_USE_CASE_ID || shouldShrinkNavigation) { - return false; - } - - // It means user is in a specific type of workspace - if (visibleUseCases.length <= 1) { + if (shouldShrinkNavigation) { return false; } - if (isOutsideWorkspace) { - return true; - } - - return visibleUseCases.length > 1; - }, [visibleUseCases, currentNavGroup, shouldShrinkNavigation, isOutsideWorkspace]); + return isInsideSecondLevel; + }, [isInsideSecondLevel, shouldShrinkNavigation]); const shouldShowHomeLink = useMemo(() => { - if (!homeLink || shouldShrinkNavigation) return false; + if (shouldShrinkNavigation) return false; return !shouldShowBackButton; - }, [shouldShowBackButton, homeLink, shouldShrinkNavigation]); + }, [shouldShowBackButton, shouldShrinkNavigation]); const homeLinkProps = useMemo(() => { if (homeLink) { @@ -104,17 +107,18 @@ export const CollapsibleNavTop = ({ { + if (firstVisibleNavLinkOfAllUseCase) { + navigateToApp(firstVisibleNavLinkOfAllUseCase.id); + } + setCurrentNavGroup(ALL_USE_CASE_ID); + }} data-test-subj="collapsibleNavBackButton" > - {isOutsideWorkspace - ? i18n.translate('core.ui.primaryNav.homeButtonLabel', { - defaultMessage: 'Home', - }) - : i18n.translate('core.ui.primaryNav.backButtonLabel', { - defaultMessage: 'Back', - })} + {i18n.translate('core.ui.primaryNav.backButtonLabel', { + defaultMessage: 'Back', + })} ) : null} diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 9c4ae18d4a3..3f131290449 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -73,7 +73,7 @@ import { ISidecarConfig, getOsdSidecarPaddingStyle } from '../../../overlays'; import { CollapsibleNavGroupEnabled } from './collapsible_nav_group_enabled'; import { ChromeNavGroupServiceStartContract, NavGroupItemInMap } from '../../nav_group'; import { RecentItems } from './recent_items'; -import { WorkspaceObject } from '../../../../public/workspace'; +import { WorkspaceObject, WorkspacesStart } from '../../../../public/workspace'; export interface HeaderProps { opensearchDashboardsVersion: string; @@ -111,6 +111,7 @@ export interface HeaderProps { navGroupsMap$: Observable>; setCurrentNavGroup: ChromeNavGroupServiceStartContract['setCurrentNavGroup']; workspaceList$: Observable; + currentWorkspace$: WorkspacesStart['currentWorkspace$']; } export function Header({ @@ -318,6 +319,7 @@ export function Header({ currentNavGroup$={observables.currentNavGroup$} setCurrentNavGroup={setCurrentNavGroup} capabilities={application.capabilities} + currentWorkspace$={observables.currentWorkspace$} /> ) : ( Date: Mon, 12 Aug 2024 15:15:49 +0800 Subject: [PATCH 08/23] feat: use gap to replace margin Signed-off-by: SuZhou-Joe --- .../ui/header/collapsible_nav_group_enabled.scss | 15 ++++++++------- .../ui/header/collapsible_nav_group_enabled.tsx | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.scss b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.scss index 2fb9a6ad9f2..b3733006f89 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.scss +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled.scss @@ -66,14 +66,15 @@ &.bottom-container-collapsed { flex-direction: column; align-items: center; - - > * { - margin: $euiSizeS 0; - } + gap: $euiSize; + padding-top: $euiSizeS; + padding-bottom: $euiSizeS; } - } - .nav-controls-padding { - padding: $euiSize; + &.bottom-container-expanded { + gap: 16px; + padding-top: $euiSize; + padding-bottom: $euiSize; + } } } 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 a1940f25cee..69d3c86ecbc 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 @@ -420,6 +420,7 @@ export function CollapsibleNavGroupEnabled({ className={classNames({ 'bottom-container': true, 'bottom-container-collapsed': !isNavOpen, + 'bottom-container-expanded': isNavOpen, })} > Date: Mon, 12 Aug 2024 16:39:20 +0800 Subject: [PATCH 09/23] feat: make new left nav work in mobile mode Signed-off-by: SuZhou-Joe --- .../public/chrome/ui/header/collapsible_nav_group_enabled.tsx | 3 ++- .../chrome/ui/header/collapsible_nav_group_enabled_top.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) 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 69d3c86ecbc..f1dad00c5f2 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 @@ -192,7 +192,7 @@ export function NavGroups({ .filter((item): item is EuiSideNavItemType<{}> => !!item); return ( - + {suffix} ); @@ -365,6 +365,7 @@ export function CollapsibleNavGroupEnabled({ closeButtonPosition="outside" hideCloseButton paddingSize="none" + ownFocus={false} >
{!isNavOpen ? null : ( diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx index e4e7b81ff20..f96f818ff79 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.tsx @@ -95,7 +95,7 @@ export const CollapsibleNavTop = ({ return (
- + {shouldShowHomeLink ? ( From f3d34270e560bc756dba678d1f4328313c20c2e6 Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Mon, 12 Aug 2024 17:33:11 +0800 Subject: [PATCH 10/23] fix: bootstrap error Signed-off-by: SuZhou-Joe --- .../ui/header/collapsible_nav_group_enabled.test.tsx | 10 +++------- .../header/collapsible_nav_group_enabled_top.test.tsx | 4 ++++ src/core/public/chrome/ui/header/header.test.tsx | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) 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 141b3eaf5ab..0f73c74b9c0 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 @@ -16,16 +16,11 @@ import { ChromeNavLink } from '../../nav_links'; import { ChromeRegistrationNavLink, NavGroupItemInMap } from '../../nav_group'; import { httpServiceMock } from '../../../mocks'; import { getLogos } from '../../../../common'; -import { ALL_USE_CASE_ID, DEFAULT_NAV_GROUPS } from '../../../../public'; -import { CollapsibleNavTopProps } from './collapsible_nav_group_enabled_top'; +import { ALL_USE_CASE_ID, DEFAULT_NAV_GROUPS, WorkspaceObject } from '../../../../public'; import { capabilitiesServiceMock } from '../../../application/capabilities/capabilities_service.mock'; jest.mock('./collapsible_nav_group_enabled_top', () => ({ - CollapsibleNavTop: (props: CollapsibleNavTopProps) => ( - - ), + CollapsibleNavTop: () => , })); const mockBasePath = httpServiceMock.createSetupContract({ basePath: '/test' }).basePath; @@ -138,6 +133,7 @@ describe('', () => { id: 'collapsibe-nav', isLocked: false, isNavOpen: false, + currentWorkspace$: new BehaviorSubject({ id: 'test', name: 'test' }), navLinks$: new BehaviorSubject([ { id: 'link-in-all', diff --git a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.test.tsx b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.test.tsx index 168f0ede150..c28db8eb94d 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.test.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav_group_enabled_top.test.tsx @@ -10,6 +10,8 @@ import { ChromeRegistrationNavLink } from '../../nav_group'; import { httpServiceMock } from '../../../mocks'; import { getLogos } from '../../../../common'; import { CollapsibleNavTop } from './collapsible_nav_group_enabled_top'; +import { BehaviorSubject } from 'rxjs'; +import { WorkspaceObject } from 'src/core/public/workspace'; const mockBasePath = httpServiceMock.createSetupContract({ basePath: '/test' }).basePath; @@ -66,6 +68,8 @@ describe('', () => { logos: getLogos({}, mockBasePath.serverBasePath), shouldShrinkNavigation: false, visibleUseCases: [], + currentWorkspace$: new BehaviorSubject(null), + setCurrentNavGroup: jest.fn(), }; }; it('should render home icon', async () => { diff --git a/src/core/public/chrome/ui/header/header.test.tsx b/src/core/public/chrome/ui/header/header.test.tsx index 1cfcc84acee..fe360f554b4 100644 --- a/src/core/public/chrome/ui/header/header.test.tsx +++ b/src/core/public/chrome/ui/header/header.test.tsx @@ -38,6 +38,7 @@ import { Header } from './header'; import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; import { ISidecarConfig, SIDECAR_DOCKED_MODE } from '../../../overlays'; import { EuiHeaderSectionItemButton } from '@elastic/eui'; +import { WorkspaceObject } from 'src/core/public/workspace'; jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ htmlIdGenerator: () => () => 'mockId', @@ -85,6 +86,7 @@ function mockProps() { navControlsLeftBottom$: new BehaviorSubject([]), setCurrentNavGroup: jest.fn(() => {}), workspaceList$: new BehaviorSubject([]), + currentWorkspace$: new BehaviorSubject(null), }; } From e91c997f17449f578b74a75bcfd1c703cfb4e25a Mon Sep 17 00:00:00 2001 From: SuZhou-Joe Date: Tue, 13 Aug 2024 13:19:51 +0800 Subject: [PATCH 11/23] fix: unit test error Signed-off-by: SuZhou-Joe --- ...ollapsible_nav_group_enabled.test.tsx.snap | 451 +++++++++--------- .../header/__snapshots__/header.test.tsx.snap | 55 +++ .../collapsible_nav_group_enabled.test.tsx | 8 +- .../header/collapsible_nav_group_enabled.tsx | 1 - ...collapsible_nav_group_enabled_top.test.tsx | 128 ++--- .../collapsible_nav_group_enabled_top.tsx | 5 +- 6 files changed, 318 insertions(+), 330 deletions(-) diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav_group_enabled.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav_group_enabled.test.tsx.snap index 2c6835acdae..ec13305b400 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav_group_enabled.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav_group_enabled.test.tsx.snap @@ -11,232 +11,232 @@ exports[` should render correctly 1`] = ` class="eui-fullHeight left-navigation-wrapper" >
+ +
+
- -
-
+
-
- - - + Observability +
-
+ +
+
- - -
- + - -
+ +
+
+
-
- - - + Essentials +
-
+ +
+
- - -
- + - -
+ +
- -
+ +
@@ -254,13 +254,8 @@ exports[` should render correctly 2`] = ` class="eui-fullHeight left-navigation-wrapper" >
-
-
+ class="flex-1-container" + />
@@ -283,62 +278,62 @@ exports[` should show all use case by default and class="eui-fullHeight left-navigation-wrapper" >
+ +
+
- -
-
- -
+
+

@@ -356,62 +351,62 @@ exports[` should show all use case when current na class="eui-fullHeight left-navigation-wrapper" >
+ +
+
- -
-
- -
+
+
@@ -424,7 +419,7 @@ exports[` should render correctly 1`] = ` class="euiFlexItem" >