From 5c131118a680e54314c9c94c1f32a3ec2b1faa91 Mon Sep 17 00:00:00 2001 From: Tatjana Dehler Date: Fri, 15 May 2020 15:54:04 +0200 Subject: [PATCH] mgr/dashboard: support >1 top notification panels Update navigation component in order to show more than one notification panel on top of the page. Signed-off-by: Tatjana Dehler (cherry picked from commit 455dca6bbe0c26ad682be394335a68399d17c486) Conflicts: src/pybind/mgr/dashboard/frontend/src/app/shared/components/pwd-expiration-notification/pwd-expiration-notification.component.html The alert component has been migrated from ngx-bootstrap to ng-boostrap in master: https://github.com/ceph/ceph/pull/35297 --- .../navigation/navigation.component.scss | 31 ++++++----- .../navigation/navigation.component.spec.ts | 52 +++++++++++++++++++ .../navigation/navigation.component.ts | 25 ++++++++- ...pwd-expiration-notification.component.html | 2 +- .../pwd-expiration-notification.component.ts | 4 +- .../frontend/src/styles/defaults.scss | 2 +- 6 files changed, 97 insertions(+), 19 deletions(-) diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.scss index 0000dd3337ede..9c0d8f09d7334 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.scss +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.scss @@ -10,7 +10,7 @@ border-top: 4px solid $color-nav-top-bar; &.isPwdDisplayed { - top: $pwd-exp-height; + top: $top-notification-height; } .navbar-brand, @@ -255,22 +255,25 @@ $sidebar-width: 200px; } /* --------------------------------------------------- - isPwdDisplayed + topNotification settings --------------------------------------------------- */ -:host.isPwdDisplayed { - .cd-navbar-top .cd-navbar-brand { - top: $pwd-exp-height; - } - #sidebar { - top: $navbar-height + $pwd-exp-height; - } +@for $i from 1 through 2 { + :host.top-notification-#{$i} { + .cd-navbar-top .cd-navbar-brand { + top: $top-notification-height * $i; + } - #content { - top: $navbar-height + $pwd-exp-height; - } + #sidebar { + top: $navbar-height + $top-notification-height * $i; + } + + #content { + top: $navbar-height + $top-notification-height * $i; + } - cd-notifications-sidebar { - top: $navbar-height + $pwd-exp-height + 10px; + cd-notifications-sidebar { + top: $navbar-height + $top-notification-height * $i + 10px; + } } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts index 1302f7a3abee6..0f7764e05d9d8 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.spec.ts @@ -180,4 +180,56 @@ describe('NavigationComponent', () => { }); } }); + + describe('showTopNotification', () => { + const notification1 = 'notificationName1'; + const notification2 = 'notificationName2'; + + beforeEach(() => { + component.notifications = []; + }); + + it('should show notification', () => { + component.showTopNotification(notification1, true); + expect(component.notifications.includes(notification1)).toBeTruthy(); + expect(component.notifications.length).toBe(1); + }); + + it('should not add a second notification if it is already shown', () => { + component.showTopNotification(notification1, true); + component.showTopNotification(notification1, true); + expect(component.notifications.includes(notification1)).toBeTruthy(); + expect(component.notifications.length).toBe(1); + }); + + it('should add a second notification if the first one is different', () => { + component.showTopNotification(notification1, true); + component.showTopNotification(notification2, true); + expect(component.notifications.includes(notification1)).toBeTruthy(); + expect(component.notifications.includes(notification2)).toBeTruthy(); + expect(component.notifications.length).toBe(2); + }); + + it('should hide an active notification', () => { + component.showTopNotification(notification1, true); + expect(component.notifications.includes(notification1)).toBeTruthy(); + expect(component.notifications.length).toBe(1); + component.showTopNotification(notification1, false); + expect(component.notifications.length).toBe(0); + }); + + it('should not fail if it tries to hide an inactive notification', () => { + expect(() => component.showTopNotification(notification1, false)).not.toThrow(); + expect(component.notifications.length).toBe(0); + }); + + it('should keep other notifications if it hides one', () => { + component.showTopNotification(notification1, true); + component.showTopNotification(notification2, true); + expect(component.notifications.length).toBe(2); + component.showTopNotification(notification2, false); + expect(component.notifications.length).toBe(1); + expect(component.notifications.includes(notification1)).toBeTruthy(); + }); + }); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts index c184d0cda5fcd..ce04147754015 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.ts @@ -18,7 +18,10 @@ import { SummaryService } from '../../../shared/services/summary.service'; styleUrls: ['./navigation.component.scss'] }) export class NavigationComponent implements OnInit, OnDestroy { - @HostBinding('class.isPwdDisplayed') isPwdDisplayed = false; + notifications: string[] = []; + @HostBinding('class') get class(): string { + return 'top-notification-' + this.notifications.length; + } permissions: Permissions; enabledFeature$: FeatureTogglesMap$; @@ -50,9 +53,14 @@ export class NavigationComponent implements OnInit, OnDestroy { this.summaryData = summary; }) ); + /* + Note: If you're going to add more top notifications please do not forget to increase + the number of generated css-classes in section topNotification settings in the scss + file. + */ this.subs.add( this.authStorageService.isPwdDisplayed$.subscribe((isDisplayed) => { - this.isPwdDisplayed = isDisplayed; + this.showTopNotification('isPwdDisplayed', isDisplayed); }) ); } @@ -80,4 +88,17 @@ export class NavigationComponent implements OnInit, OnDestroy { this.displayedSubMenu = menu; } } + + showTopNotification(name: string, isDisplayed: boolean) { + if (isDisplayed) { + if (!this.notifications.includes(name)) { + this.notifications.push(name); + } + } else { + const index = this.notifications.indexOf(name); + if (index >= 0) { + this.notifications.splice(index, 1); + } + } + } } diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/pwd-expiration-notification/pwd-expiration-notification.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/pwd-expiration-notification/pwd-expiration-notification.component.html index 36615164bd62f..5a43e92e1dce4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/pwd-expiration-notification/pwd-expiration-notification.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/pwd-expiration-notification/pwd-expiration-notification.component.html @@ -1,6 +1,6 @@