forked from openattic/ceph
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mgr/dashboard: add telemetry activation notification
The commit adds 2 different parts to show the Telemetry activation notification in the dashboard: 1. The Telemetry activation notification component itself. It contains the definition of the notification panel. 2. The Telemetry notification service. The service is needed to be able to show/hide the notification from: * the component itself (e.g. when clicking the button button) * the Telemetry configuration component (when enabling/disabling Telemetry) * the navigation component (to set the css- classes accordingly) Fixes: https://tracker.ceph.com/issues/45464 Signed-off-by: Tatjana Dehler <tdehler@suse.com>
- Loading branch information
Tatjana Dehler
committed
Jun 19, 2020
1 parent
455dca6
commit f7e4579
Showing
11 changed files
with
273 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
...ybind/mgr/dashboard/frontend/src/app/core/navigation/navigation/navigation.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
...nd/src/app/shared/components/telemetry-notification/telemetry-notification.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<ngb-alert class="no-margin-bottom" | ||
type="warning" | ||
*ngIf="displayNotification" | ||
(close)="close($event)"> | ||
<div i18n>The Telemetry module is not submitting telemetry data at the | ||
moment. Click | ||
<a routerLink="/telemetry" | ||
class="alert-link">here</a> to activate it now.</div> | ||
</ngb-alert> |
3 changes: 3 additions & 0 deletions
3
...nd/src/app/shared/components/telemetry-notification/telemetry-notification.component.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
::ng-deep .no-margin-bottom { | ||
margin-bottom: 0; | ||
} |
125 changes: 125 additions & 0 deletions
125
...src/app/shared/components/telemetry-notification/telemetry-notification.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { HttpClientTestingModule } from '@angular/common/http/testing'; | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { NgbAlertModule } from '@ng-bootstrap/ng-bootstrap'; | ||
import { ToastrModule } from 'ngx-toastr'; | ||
import { of } from 'rxjs'; | ||
|
||
import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper'; | ||
import { UserFormModel } from '../../../core/auth/user-form/user-form.model'; | ||
import { MgrModuleService } from '../../api/mgr-module.service'; | ||
import { UserService } from '../../api/user.service'; | ||
import { PipesModule } from '../../pipes/pipes.module'; | ||
import { AuthStorageService } from '../../services/auth-storage.service'; | ||
import { NotificationService } from '../../services/notification.service'; | ||
import { TelemetryNotificationService } from '../../services/telemetry-notification.service'; | ||
import { TelemetryNotificationComponent } from './telemetry-notification.component'; | ||
|
||
describe('TelemetryActivationNotificationComponent', () => { | ||
let component: TelemetryNotificationComponent; | ||
let fixture: ComponentFixture<TelemetryNotificationComponent>; | ||
|
||
let authStorageService: AuthStorageService; | ||
let userService: UserService; | ||
let mgrModuleService: MgrModuleService; | ||
let notificationService: NotificationService; | ||
|
||
let isNotificationHiddenSpy: jasmine.Spy; | ||
let getUsernameSpy: jasmine.Spy; | ||
let userServiceGetSpy: jasmine.Spy; | ||
let getConfigSpy: jasmine.Spy; | ||
|
||
const user: UserFormModel = { | ||
username: 'username', | ||
password: undefined, | ||
name: 'User 1', | ||
email: 'user1@email.com', | ||
roles: ['read-only'], | ||
enabled: true, | ||
pwdExpirationDate: undefined, | ||
pwdUpdateRequired: true | ||
}; | ||
const admin: UserFormModel = { | ||
username: 'admin', | ||
password: undefined, | ||
name: 'User 1', | ||
email: 'user1@email.com', | ||
roles: ['administrator'], | ||
enabled: true, | ||
pwdExpirationDate: undefined, | ||
pwdUpdateRequired: true | ||
}; | ||
const telemetryEnabledConfig = { | ||
enabled: true | ||
}; | ||
const telemetryDisabledConfig = { | ||
enabled: false | ||
}; | ||
|
||
configureTestBed({ | ||
declarations: [TelemetryNotificationComponent], | ||
imports: [NgbAlertModule, HttpClientTestingModule, ToastrModule.forRoot(), PipesModule], | ||
providers: [MgrModuleService, UserService, i18nProviders] | ||
}); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(TelemetryNotificationComponent); | ||
component = fixture.componentInstance; | ||
authStorageService = TestBed.inject(AuthStorageService); | ||
userService = TestBed.inject(UserService); | ||
mgrModuleService = TestBed.inject(MgrModuleService); | ||
notificationService = TestBed.inject(NotificationService); | ||
|
||
isNotificationHiddenSpy = spyOn(component, 'isNotificationHidden').and.returnValue(false); | ||
getUsernameSpy = spyOn(authStorageService, 'getUsername').and.returnValue('username'); | ||
userServiceGetSpy = spyOn(userService, 'get').and.returnValue(of(admin)); // Not the best name but it sounded better than `getSpy` | ||
getConfigSpy = spyOn(mgrModuleService, 'getConfig').and.returnValue( | ||
of(telemetryDisabledConfig) | ||
); | ||
}); | ||
|
||
it('should create', () => { | ||
fixture.detectChanges(); | ||
expect(component).toBeTruthy(); | ||
}); | ||
|
||
it('should not show notification again if the user closed it before', () => { | ||
isNotificationHiddenSpy.and.returnValue(true); | ||
fixture.detectChanges(); | ||
expect(component.displayNotification).toBe(false); | ||
}); | ||
|
||
it('should not show notification for an user without administrator role', () => { | ||
userServiceGetSpy.and.returnValue(of(user)); | ||
fixture.detectChanges(); | ||
expect(component.displayNotification).toBe(false); | ||
}); | ||
|
||
it('should not show notification if the module is enabled already', () => { | ||
getUsernameSpy.and.returnValue('admin'); | ||
getConfigSpy.and.returnValue(of(telemetryEnabledConfig)); | ||
fixture.detectChanges(); | ||
expect(component.displayNotification).toBe(false); | ||
}); | ||
|
||
it('should show the notification if all pre-conditions set accordingly', () => { | ||
fixture.detectChanges(); | ||
expect(component.displayNotification).toBe(true); | ||
}); | ||
|
||
it('should hide the notification if the user closes it', () => { | ||
spyOn(notificationService, 'show'); | ||
fixture.detectChanges(); | ||
component.close(); | ||
expect(notificationService.show).toHaveBeenCalled(); | ||
expect(localStorage.getItem('telemetry_notification_hidden')).toBe('true'); | ||
}); | ||
|
||
it('should hide the notification if the user logs out', () => { | ||
const telemetryNotificationService = TestBed.inject(TelemetryNotificationService); | ||
spyOn(telemetryNotificationService, 'setVisibility'); | ||
fixture.detectChanges(); | ||
component.ngOnDestroy(); | ||
expect(telemetryNotificationService.setVisibility).toHaveBeenCalledWith(false); | ||
}); | ||
}); |
69 changes: 69 additions & 0 deletions
69
...tend/src/app/shared/components/telemetry-notification/telemetry-notification.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { Component, OnDestroy, OnInit } from '@angular/core'; | ||
|
||
import { I18n } from '@ngx-translate/i18n-polyfill'; | ||
|
||
import { UserFormModel } from '../../../core/auth/user-form/user-form.model'; | ||
import { MgrModuleService } from '../../api/mgr-module.service'; | ||
import { UserService } from '../../api/user.service'; | ||
import { NotificationType } from '../../enum/notification-type.enum'; | ||
import { AuthStorageService } from '../../services/auth-storage.service'; | ||
import { NotificationService } from '../../services/notification.service'; | ||
import { TelemetryNotificationService } from '../../services/telemetry-notification.service'; | ||
|
||
@Component({ | ||
selector: 'cd-telemetry-notification', | ||
templateUrl: './telemetry-notification.component.html', | ||
styleUrls: ['./telemetry-notification.component.scss'] | ||
}) | ||
export class TelemetryNotificationComponent implements OnInit, OnDestroy { | ||
displayNotification = false; | ||
|
||
constructor( | ||
private mgrModuleService: MgrModuleService, | ||
private authStorageService: AuthStorageService, | ||
private userService: UserService, | ||
private notificationService: NotificationService, | ||
private telemetryNotificationService: TelemetryNotificationService, | ||
private i18n: I18n | ||
) {} | ||
|
||
ngOnInit() { | ||
this.telemetryNotificationService.update.subscribe((visible: boolean) => { | ||
this.displayNotification = visible; | ||
}); | ||
|
||
if (!this.isNotificationHidden()) { | ||
const username = this.authStorageService.getUsername(); | ||
this.userService.get(username).subscribe((user: UserFormModel) => { | ||
if (user.roles.includes('administrator')) { | ||
this.mgrModuleService.getConfig('telemetry').subscribe((options) => { | ||
if (!options['enabled']) { | ||
this.telemetryNotificationService.setVisibility(true); | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
ngOnDestroy() { | ||
this.telemetryNotificationService.setVisibility(false); | ||
} | ||
|
||
isNotificationHidden(): boolean { | ||
return localStorage.getItem('telemetry_notification_hidden') === 'true'; | ||
} | ||
|
||
close() { | ||
this.telemetryNotificationService.setVisibility(false); | ||
localStorage.setItem('telemetry_notification_hidden', 'true'); | ||
this.notificationService.show( | ||
NotificationType.success, | ||
this.i18n('Telemetry activation reminder muted'), | ||
this.i18n( | ||
'You can activate the module on the Telemetry configuration ' + | ||
'page (<b>Dashboard Settings</b> -> <b>Telemetry configuration</b>) at any time.' | ||
) | ||
); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
...ind/mgr/dashboard/frontend/src/app/shared/services/telemetry-notification.service.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { TestBed } from '@angular/core/testing'; | ||
|
||
import { configureTestBed } from '../../../testing/unit-test-helper'; | ||
import { TelemetryNotificationService } from './telemetry-notification.service'; | ||
|
||
describe('TelemetryNotificationService', () => { | ||
let service: TelemetryNotificationService; | ||
|
||
configureTestBed({ | ||
providers: [TelemetryNotificationService] | ||
}); | ||
|
||
beforeEach(() => { | ||
service = TestBed.inject(TelemetryNotificationService); | ||
spyOn(service.update, 'emit'); | ||
}); | ||
|
||
it('should be created', () => { | ||
expect(service).toBeTruthy(); | ||
}); | ||
|
||
it('should set notification visibility to true', () => { | ||
service.setVisibility(true); | ||
expect(service.visible).toBe(true); | ||
expect(service.update.emit).toHaveBeenCalledWith(true); | ||
}); | ||
|
||
it('should set notification visibility to false', () => { | ||
service.setVisibility(false); | ||
expect(service.visible).toBe(false); | ||
expect(service.update.emit).toHaveBeenCalledWith(false); | ||
}); | ||
}); |
16 changes: 16 additions & 0 deletions
16
src/pybind/mgr/dashboard/frontend/src/app/shared/services/telemetry-notification.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { EventEmitter, Injectable, Output } from '@angular/core'; | ||
|
||
@Injectable({ | ||
providedIn: 'root' | ||
}) | ||
export class TelemetryNotificationService { | ||
visible = false; | ||
|
||
@Output() | ||
update: EventEmitter<boolean> = new EventEmitter<boolean>(); | ||
|
||
setVisibility(visible: boolean) { | ||
this.visible = visible; | ||
this.update.emit(visible); | ||
} | ||
} |