From: Volker Theile Date: Mon, 18 Feb 2019 10:42:09 +0000 (+0100) Subject: mgr/dashboard: Show success notification in RGW forms X-Git-Tag: v14.1.1~88^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=57c6bca6aa3db27e7e2db68749f093b003b96838;p=ceph.git mgr/dashboard: Show success notification in RGW forms Display success notifications in the RGW user and bucket form. Signed-off-by: Volker Theile --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts index b4dcd25b50b9..22d9710604d4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.spec.ts @@ -1,36 +1,41 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { Router } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; +import { ToastModule } from 'ng2-toastr'; import { of as observableOf } from 'rxjs'; -import { configureTestBed } from '../../../../testing/unit-test-helper'; +import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper'; import { RgwBucketService } from '../../../shared/api/rgw-bucket.service'; +import { NotificationType } from '../../../shared/enum/notification-type.enum'; +import { NotificationService } from '../../../shared/services/notification.service'; import { SharedModule } from '../../../shared/shared.module'; import { RgwBucketFormComponent } from './rgw-bucket-form.component'; describe('RgwBucketFormComponent', () => { let component: RgwBucketFormComponent; let fixture: ComponentFixture; - let queryResult: Array = []; - - class MockRgwBucketService extends RgwBucketService { - enumerate() { - return observableOf(queryResult); - } - } + let rwgBucketService: RgwBucketService; configureTestBed({ declarations: [RgwBucketFormComponent], - imports: [HttpClientTestingModule, ReactiveFormsModule, RouterTestingModule, SharedModule], - providers: [{ provide: RgwBucketService, useClass: MockRgwBucketService }] + imports: [ + HttpClientTestingModule, + ReactiveFormsModule, + RouterTestingModule, + SharedModule, + ToastModule.forRoot() + ], + providers: [i18nProviders] }); beforeEach(() => { fixture = TestBed.createComponent(RgwBucketFormComponent); component = fixture.componentInstance; fixture.detectChanges(); + rwgBucketService = TestBed.get(RgwBucketService); }); it('should create', () => { @@ -77,7 +82,7 @@ describe('RgwBucketFormComponent', () => { }); it('should validate name (4/4)', () => { - queryResult = ['abcd']; + spyOn(rwgBucketService, 'enumerate').and.returnValue(observableOf(['abcd'])); const validatorFn = component.bucketNameValidator(); const ctrl = new FormControl('abcd'); ctrl.markAsDirty(); @@ -91,4 +96,36 @@ describe('RgwBucketFormComponent', () => { } }); }); + + describe('submit form', () => { + let notificationService: NotificationService; + + beforeEach(() => { + spyOn(TestBed.get(Router), 'navigate').and.stub(); + notificationService = TestBed.get(NotificationService); + spyOn(notificationService, 'show'); + }); + + it('tests create success notification', () => { + spyOn(rwgBucketService, 'create').and.returnValue(observableOf([])); + component.editing = false; + component.bucketForm.markAsDirty(); + component.submit(); + expect(notificationService.show).toHaveBeenCalledWith( + NotificationType.success, + 'Created Object Gateway bucket ""' + ); + }); + + it('tests update success notification', () => { + spyOn(rwgBucketService, 'update').and.returnValue(observableOf([])); + component.editing = true; + component.bucketForm.markAsDirty(); + component.submit(); + expect(notificationService.show).toHaveBeenCalledWith( + NotificationType.success, + 'Updated Object Gateway bucket ""' + ); + }); + }); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts index 893a68e57123..0bbf47e64342 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts @@ -2,12 +2,15 @@ import { Component, OnInit } from '@angular/core'; import { AbstractControl, AsyncValidatorFn, ValidationErrors, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; +import { I18n } from '@ngx-translate/i18n-polyfill'; import * as _ from 'lodash'; import { RgwBucketService } from '../../../shared/api/rgw-bucket.service'; import { RgwUserService } from '../../../shared/api/rgw-user.service'; +import { NotificationType } from '../../../shared/enum/notification-type.enum'; import { CdFormBuilder } from '../../../shared/forms/cd-form-builder'; import { CdFormGroup } from '../../../shared/forms/cd-form-group'; +import { NotificationService } from '../../../shared/services/notification.service'; @Component({ selector: 'cd-rgw-bucket-form', @@ -26,7 +29,9 @@ export class RgwBucketFormComponent implements OnInit { private router: Router, private formBuilder: CdFormBuilder, private rgwBucketService: RgwBucketService, - private rgwUserService: RgwUserService + private rgwUserService: RgwUserService, + private notificationService: NotificationService, + private i18n: I18n ) { this.createForm(); } @@ -81,6 +86,7 @@ export class RgwBucketFormComponent implements OnInit { // Exit immediately if the form isn't dirty. if (this.bucketForm.pristine) { this.goToListView(); + return; } const bidCtl = this.bucketForm.get('bid'); const ownerCtl = this.bucketForm.get('owner'); @@ -89,6 +95,10 @@ export class RgwBucketFormComponent implements OnInit { const idCtl = this.bucketForm.get('id'); this.rgwBucketService.update(bidCtl.value, idCtl.value, ownerCtl.value).subscribe( () => { + this.notificationService.show( + NotificationType.success, + this.i18n('Updated Object Gateway bucket "{{bid}}"', { bid: bidCtl.value }) + ); this.goToListView(); }, () => { @@ -100,6 +110,10 @@ export class RgwBucketFormComponent implements OnInit { // Add this.rgwBucketService.create(bidCtl.value, ownerCtl.value).subscribe( () => { + this.notificationService.show( + NotificationType.success, + this.i18n('Created Object Gateway bucket "{{bid}}"', { bid: bidCtl.value }) + ); this.goToListView(); }, () => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.spec.ts index 6e183172da8e..a4d5038dff6a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.spec.ts @@ -1,13 +1,17 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; +import { Router } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; +import { ToastModule } from 'ng2-toastr'; import { BsModalService } from 'ngx-bootstrap/modal'; import { of as observableOf } from 'rxjs'; -import { configureTestBed, FormHelper } from '../../../../testing/unit-test-helper'; +import { configureTestBed, FormHelper, i18nProviders } from '../../../../testing/unit-test-helper'; import { RgwUserService } from '../../../shared/api/rgw-user.service'; +import { NotificationType } from '../../../shared/enum/notification-type.enum'; +import { NotificationService } from '../../../shared/services/notification.service'; import { SharedModule } from '../../../shared/shared.module'; import { RgwUserS3Key } from '../models/rgw-user-s3-key'; import { RgwUserFormComponent } from './rgw-user-form.component'; @@ -20,8 +24,14 @@ describe('RgwUserFormComponent', () => { configureTestBed({ declarations: [RgwUserFormComponent], - imports: [HttpClientTestingModule, ReactiveFormsModule, RouterTestingModule, SharedModule], - providers: [BsModalService] + imports: [ + HttpClientTestingModule, + ReactiveFormsModule, + RouterTestingModule, + SharedModule, + ToastModule.forRoot() + ], + providers: [BsModalService, i18nProviders] }); beforeEach(() => { @@ -135,7 +145,15 @@ describe('RgwUserFormComponent', () => { })); }); - describe('onSubmit', () => { + describe('submit form', () => { + let notificationService: NotificationService; + + beforeEach(() => { + spyOn(TestBed.get(Router), 'navigate').and.stub(); + notificationService = TestBed.get(NotificationService); + spyOn(notificationService, 'show'); + }); + it('should be able to clear the mail field on update', () => { spyOn(rgwUserService, 'update'); component.editing = true; @@ -148,5 +166,27 @@ describe('RgwUserFormComponent', () => { suspended: false }); }); + + it('tests create success notification', () => { + spyOn(rgwUserService, 'create').and.returnValue(observableOf([])); + component.editing = false; + formHelper.setValue('suspended', true, true); + component.onSubmit(); + expect(notificationService.show).toHaveBeenCalledWith( + NotificationType.success, + 'Created Object Gateway user ""' + ); + }); + + it('tests update success notification', () => { + spyOn(rgwUserService, 'update').and.returnValue(observableOf([])); + component.editing = true; + formHelper.setValue('suspended', true, true); + component.onSubmit(); + expect(notificationService.show).toHaveBeenCalledWith( + NotificationType.success, + 'Updated Object Gateway user ""' + ); + }); }); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts index f1f873d9965a..a573dbdc1ca6 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts @@ -2,15 +2,18 @@ import { Component, OnInit } from '@angular/core'; import { AbstractControl, ValidationErrors, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; +import { I18n } from '@ngx-translate/i18n-polyfill'; import * as _ from 'lodash'; import { BsModalService } from 'ngx-bootstrap/modal'; import { forkJoin as observableForkJoin, Observable } from 'rxjs'; import { RgwUserService } from '../../../shared/api/rgw-user.service'; +import { NotificationType } from '../../../shared/enum/notification-type.enum'; import { CdFormBuilder } from '../../../shared/forms/cd-form-builder'; import { CdFormGroup } from '../../../shared/forms/cd-form-group'; import { CdValidators, isEmptyInputValue } from '../../../shared/forms/cd-validators'; import { FormatterService } from '../../../shared/services/formatter.service'; +import { NotificationService } from '../../../shared/services/notification.service'; import { RgwUserCapability } from '../models/rgw-user-capability'; import { RgwUserS3Key } from '../models/rgw-user-s3-key'; import { RgwUserSubuser } from '../models/rgw-user-subuser'; @@ -42,7 +45,9 @@ export class RgwUserFormComponent implements OnInit { private route: ActivatedRoute, private router: Router, private rgwUserService: RgwUserService, - private bsModalService: BsModalService + private bsModalService: BsModalService, + private notificationService: NotificationService, + private i18n: I18n ) { this.createForm(); this.listenToChanges(); @@ -225,9 +230,11 @@ export class RgwUserFormComponent implements OnInit { } onSubmit() { + let notificationTitle: string; // Exit immediately if the form isn't dirty. if (this.userForm.pristine) { this.goToListView(); + return; } const uid = this.userForm.getValue('uid'); if (this.editing) { @@ -236,10 +243,12 @@ export class RgwUserFormComponent implements OnInit { const args = this._getUpdateArgs(); this.submitObservables.push(this.rgwUserService.update(uid, args)); } + notificationTitle = this.i18n('Updated Object Gateway user "{{uid}}"', { uid: uid }); } else { // Add const args = this._getCreateArgs(); this.submitObservables.push(this.rgwUserService.create(args)); + notificationTitle = this.i18n('Created Object Gateway user "{{uid}}"', { uid: uid }); } // Check if user quota has been modified. if (this._isUserQuotaDirty()) { @@ -254,6 +263,7 @@ export class RgwUserFormComponent implements OnInit { // Finally execute all observables. observableForkJoin(this.submitObservables).subscribe( () => { + this.notificationService.show(NotificationType.success, notificationTitle); this.goToListView(); }, () => { diff --git a/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf b/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf index 13dad708dbe6..f9cbfa1ea381 100644 --- a/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf +++ b/src/pybind/mgr/dashboard/frontend/src/locale/messages.xlf @@ -5639,6 +5639,20 @@ 1 + + Updated Object Gateway bucket "" + + src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts + 1 + + + + Created Object Gateway bucket "" + + src/app/ceph/rgw/rgw-bucket-form/rgw-bucket-form.component.ts + 1 + + bucket @@ -5653,6 +5667,20 @@ 1 + + Updated Object Gateway user "" + + src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts + 1 + + + + Created Object Gateway user "" + + src/app/ceph/rgw/rgw-user-form/rgw-user-form.component.ts + 1 + + user