-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[navigation]Refactor: flatten left nav in Analytics(all) use case #8332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 33 commits
67a0a11
2532dec
86dae40
cc1fca7
d82c4f0
4a88a34
b39d9d7
6ea23c5
6bf0d6b
3578916
4546d02
9e66bc5
dc562e4
be1ee80
82334d4
13d4ec8
1916078
4a9b206
1a12067
8296d76
3450737
4a4eaad
061108d
acf325d
da8cc6a
3d047e9
71ea8f0
988ca6d
20365fa
cb44610
89ba989
ea25014
7da0bfe
faded17
bfc1f60
fde8c9b
9f7d497
0e083b1
da5e4fe
b6f4b16
a10cb84
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| feat: | ||
| - [navigation] flatten left nav in Analytics(all) use case ([#8332](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8332)) | ||
| - [navigation] Adjust the appearances of the left navigation menu and the landing page ([#8332](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8332)) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ import { | |
| ChromeNavLink, | ||
| WorkspacesStart, | ||
| } from 'opensearch-dashboards/public'; | ||
| import { i18n } from '@osd/i18n'; | ||
| import { map, switchMap, takeUntil } from 'rxjs/operators'; | ||
| import { IUiSettingsClient } from '../../ui_settings'; | ||
| import { | ||
|
|
@@ -22,7 +23,7 @@ import { ChromeNavLinks } from '../nav_links'; | |
| import { InternalApplicationStart } from '../../application'; | ||
| import { NavGroupStatus, NavGroupType } from '../../../../core/types'; | ||
| import { ChromeBreadcrumb, ChromeBreadcrumbEnricher } from '../chrome_service'; | ||
| import { ALL_USE_CASE_ID } from '../../../utils'; | ||
| import { ALL_USE_CASE_ID, DEFAULT_APP_CATEGORIES } from '../../../utils'; | ||
|
|
||
| export const CURRENT_NAV_GROUP_ID = 'core.chrome.currentNavGroupId'; | ||
|
|
||
|
|
@@ -74,6 +75,14 @@ export interface ChromeNavGroupServiceStartContract { | |
| setCurrentNavGroup: (navGroupId: string | undefined) => void; | ||
| } | ||
|
|
||
| // Custom category is used for those features not belong to any of use cases in all use case. | ||
| // and the custom category should always sit after manage category | ||
| const customCategory: AppCategory = { | ||
| id: 'custom', | ||
| label: i18n.translate('core.ui.customNavList.label', { defaultMessage: 'Custom' }), | ||
| order: (DEFAULT_APP_CATEGORIES.manage.order || 0) + 500, | ||
| }; | ||
|
|
||
| /** @internal */ | ||
| export class ChromeNavGroupService { | ||
| private readonly navGroupsMap$ = new BehaviorSubject<Record<string, NavGroupItemInMap>>({}); | ||
|
|
@@ -114,12 +123,86 @@ export class ChromeNavGroupService { | |
| } | ||
|
|
||
| private sortNavGroupNavLinks( | ||
| navGroup: NavGroupItemInMap, | ||
| navLinks: NavGroupItemInMap['navLinks'], | ||
| allValidNavLinks: Array<Readonly<ChromeNavLink>> | ||
| ) { | ||
| return getSortedNavLinks( | ||
| fulfillRegistrationLinksToChromeNavLinks(navGroup.navLinks, allValidNavLinks) | ||
| ); | ||
| return getSortedNavLinks(fulfillRegistrationLinksToChromeNavLinks(navLinks, allValidNavLinks)); | ||
| } | ||
|
|
||
| private getNavLinksForAllUseCase( | ||
| navGroupsMap: Record<string, NavGroupItemInMap>, | ||
| navLinks: Array<Readonly<ChromeNavLink>> | ||
| ) { | ||
| // Note: we need to use a new pointer when `assign navGroupsMap[ALL_USE_CASE_ID]?.navLinks` | ||
| // because we will mutate the array directly in the following code. | ||
| const navLinksResult: ChromeRegistrationNavLink[] = [ | ||
| ...(navGroupsMap[ALL_USE_CASE_ID]?.navLinks || []), | ||
| ]; | ||
|
|
||
| // Append all the links that do not have use case info to keep backward compatible | ||
| const linkIdsWithNavGroupInfo = Object.values(navGroupsMap).reduce((accumulator, navGroup) => { | ||
| return [...accumulator, ...navGroup.navLinks.map((navLink) => navLink.id)]; | ||
| }, [] as string[]); | ||
| navLinks.forEach((navLink) => { | ||
| if (linkIdsWithNavGroupInfo.includes(navLink.id)) { | ||
| return; | ||
| } | ||
| navLinksResult.push({ | ||
| ...navLink, | ||
| category: customCategory, | ||
| }); | ||
| }); | ||
|
|
||
| // Append use case section into left navigation | ||
| Object.values(navGroupsMap).forEach((group) => { | ||
| if (group.type) { | ||
| return; | ||
| } | ||
| const categoryInfo = { | ||
| id: group.id, | ||
| label: group.title, | ||
| order: group.order, | ||
| }; | ||
|
|
||
| const fulfilledLinksOfNavGroup = fulfillRegistrationLinksToChromeNavLinks( | ||
| group.navLinks, | ||
| navLinks | ||
| ); | ||
|
|
||
| const linksForAllUseCaseWithinNavGroup: ChromeRegistrationNavLink[] = []; | ||
|
|
||
| fulfilledLinksOfNavGroup.forEach((navLink) => { | ||
| if (!navLink.showInAllNavGroup) { | ||
| return; | ||
| } | ||
|
|
||
| linksForAllUseCaseWithinNavGroup.push({ | ||
| ...navLink, | ||
| category: categoryInfo, | ||
| }); | ||
| }); | ||
|
|
||
| navLinksResult.push(...linksForAllUseCaseWithinNavGroup); | ||
|
||
|
|
||
| if (!linksForAllUseCaseWithinNavGroup.length) { | ||
| /** | ||
| * Find if there are any links inside a use case but without a `see all` entry. | ||
| * If so, append these features into custom category as a fallback | ||
| */ | ||
| fulfillRegistrationLinksToChromeNavLinks(group.navLinks, navLinks).forEach((navLink) => { | ||
| // Links that already exists in all use case do not need to reappend | ||
| if (navLinksResult.find((navLinkInAll) => navLinkInAll.id === navLink.id)) { | ||
| return; | ||
| } | ||
| navLinksResult.push({ | ||
| ...navLink, | ||
| category: customCategory, | ||
| }); | ||
| }); | ||
| } | ||
| }); | ||
|
|
||
| return navLinksResult; | ||
| } | ||
|
|
||
| private getSortedNavGroupsMap$() { | ||
|
|
@@ -129,10 +212,20 @@ export class ChromeNavGroupService { | |
| map(([navGroupsMap, navLinks]) => { | ||
| return Object.keys(navGroupsMap).reduce((sortedNavGroupsMap, navGroupId) => { | ||
| const navGroup = navGroupsMap[navGroupId]; | ||
| sortedNavGroupsMap[navGroupId] = { | ||
| ...navGroup, | ||
| navLinks: this.sortNavGroupNavLinks(navGroup, navLinks), | ||
| }; | ||
| if (navGroupId === ALL_USE_CASE_ID) { | ||
| sortedNavGroupsMap[navGroupId] = { | ||
| ...navGroup, | ||
| navLinks: this.sortNavGroupNavLinks( | ||
| this.getNavLinksForAllUseCase(navGroupsMap, navLinks), | ||
| navLinks | ||
| ), | ||
| }; | ||
| } else { | ||
| sortedNavGroupsMap[navGroupId] = { | ||
| ...navGroup, | ||
| navLinks: this.sortNavGroupNavLinks(navGroup.navLinks, navLinks), | ||
| }; | ||
| } | ||
| return sortedNavGroupsMap; | ||
| }, {} as Record<string, NavGroupItemInMap>); | ||
| }) | ||
|
|
@@ -270,14 +363,8 @@ export class ChromeNavGroupService { | |
| }); | ||
| }; | ||
| if (visibleUseCases.length === 1) { | ||
| if (visibleUseCases[0].id === ALL_USE_CASE_ID) { | ||
| // If the only visible use case is all use case | ||
| // All the other nav groups will be visible because all use case can visit all of the nav groups. | ||
| Object.values(navGroupMap).forEach((navGroup) => mapAppIdToNavGroup(navGroup)); | ||
| } else { | ||
| // It means we are in a workspace, we should only use the visible use cases | ||
| visibleUseCases.forEach((navGroup) => mapAppIdToNavGroup(navGroup)); | ||
| } | ||
| // It means we are in a workspace, we should only use the visible use cases | ||
|
||
| visibleUseCases.forEach((navGroup) => mapAppIdToNavGroup(navGroup)); | ||
| } else { | ||
| // Nav group of Hidden status should be filtered out when counting navGroups the currentApp belongs to | ||
| Object.values(navGroupMap).forEach((navGroup) => { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.