This is an automated email from the ASF dual-hosted git repository.

ababiichuk pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git

commit 9e07d7460642b36b0d3dd195920ab6aa2a0dd608
Author: Tobias Istvan <tobias.ist...@gmail.com>
AuthorDate: Mon May 21 15:36:53 2018 +0200

    [AMBARI-23897] Log Search UI: login with invalid password – no error 
message is displayed
---
 .../login-form/login-form.component.html           |  2 +-
 .../login-form/login-form.component.spec.ts        | 23 ++++----
 .../components/login-form/login-form.component.ts  | 61 ++++++++++++++++------
 .../src/app/services/auth.service.ts               | 31 ++++++++---
 .../ambari-logsearch-web/src/assets/i18n/en.json   |  2 +
 5 files changed, 86 insertions(+), 33 deletions(-)

diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.html
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.html
index 8b9c957..9e8b2a5 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.html
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.html
@@ -16,7 +16,7 @@
 -->
 
 <div class="login-form well col-md-4 col-md-offset-4 col-sm-offset-4">
-  <div class="alert alert-danger" *ngIf="isLoginAlertDisplayed" 
[innerHTML]="'authorization.error' | translate"></div>
+  <div class="alert alert-danger" *ngIf="isLoginAlertDisplayed" 
[innerHTML]="errorMessage"></div>
   <form #loginForm="ngForm" (ngSubmit)="login()">
     <div class="form-group">
       <label for="username">{{'authorization.name' | translate}}</label>
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.spec.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.spec.ts
index 7e2f7a7..3ec55fd 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.spec.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.spec.ts
@@ -26,20 +26,23 @@ import {AuthService} from '@app/services/auth.service';
 
 import {LoginFormComponent} from './login-form.component';
 import {RouterTestingModule} from '@angular/router/testing';
+import {NotificationsService} from 'angular2-notifications';
+import {NotificationService} from 
'@app/modules/shared/services/notification.service';
 
 describe('LoginFormComponent', () => {
   let component: LoginFormComponent;
   let fixture: ComponentFixture<LoginFormComponent>;
 
   const authMock = {
-    isError: false
+    isError: false,
+    isAuthorized: false
   };
-  const httpClient = {
-    isAuthorized: true,
-    postFormData: () => {
+
+  const AuthServiceMock = {
+    login: () => {
       return {
-        subscribe: (success: () => void, error: () => void) => {
-          authMock.isError ? error() : success();
+        subscribe: (observer: (resp) => void, error: (resp) => void) => {
+          authMock.isAuthorized ? observer(authMock.isAuthorized) : 
error(authMock.isAuthorized);
         }
       };
     }
@@ -59,10 +62,11 @@ describe('LoginFormComponent', () => {
       providers: [
         AppStateService,
         {
-          provide: HttpClientService,
-          useValue: httpClient
+          provide: AuthService,
+          useValue: AuthServiceMock
         },
-        AuthService
+        NotificationsService,
+        NotificationService
       ]
     })
     .compileComponents();
@@ -98,6 +102,7 @@ describe('LoginFormComponent', () => {
       describe(test.title, () => {
         beforeEach(() => {
           authMock.isError = test.isError;
+          authMock.isAuthorized = test.isAuthorized;
           component.login();
         });
 
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.ts
 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.ts
index e3570c4..eee0b1b 100644
--- 
a/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.ts
+++ 
b/ambari-logsearch/ambari-logsearch-web/src/app/components/login-form/login-form.component.ts
@@ -16,19 +16,23 @@
  * limitations under the License.
  */
 
-import {Component} from '@angular/core';
+import {Component, ViewChild, OnInit, OnDestroy} from '@angular/core';
 import {Response} from '@angular/http';
+import {Observable} from 'rxjs/Observable';
 import 'rxjs/add/operator/finally';
+import {Subscription} from 'rxjs/Subscription';
 import {AppStateService} from '@app/services/storage/app-state.service';
 import {AuthService} from '@app/services/auth.service';
-import {Observable} from 'rxjs/Observable';
+import {NotificationService, NotificationType} from 
'@modules/shared/services/notification.service';
+import {TranslateService} from '@ngx-translate/core';
+import {FormGroup} from '@angular/forms';
 
 @Component({
   selector: 'login-form',
   templateUrl: './login-form.component.html',
   styleUrls: ['./login-form.component.less']
 })
-export class LoginFormComponent {
+export class LoginFormComponent implements OnInit, OnDestroy {
 
   username: string;
 
@@ -38,24 +42,47 @@ export class LoginFormComponent {
 
   isLoginInProgress$: Observable<boolean> = 
this.appState.getParameter('isLoginInProgress');
 
-  constructor(private authService: AuthService, private appState: 
AppStateService) {}
+  errorMessage: string;
+
+  @ViewChild('loginForm')
+  loginForm: FormGroup;
+
+  subscriptions: Subscription[] = [];
+
+  constructor(
+    private authService: AuthService,
+    private appState: AppStateService,
+    private notificationService: NotificationService,
+    private translateService: TranslateService
+  ) {}
+
+  ngOnInit(): void {
+    this.subscriptions.push(
+      this.loginForm.valueChanges.subscribe(this.onLoginFormChange)
+    );
+  }
+
+  ngOnDestroy(): void {
+    this.subscriptions.forEach((subscription: Subscription) => 
subscription.unsubscribe());
+  }
 
-  /**
-   * Handling the response from the login action. Actually the goal only to 
show or hide the login error alert.
-   * When it gets error response it shows.
-   * @param {Response} resp
-   */
-  private onLoginError = (resp: Response): void => {
-    this.isLoginAlertDisplayed = true;
+  onLoginFormChange = (event) => {
+    this.isLoginAlertDisplayed = false;
   }
 
-  /**
-   * Handling the response from the login action. Actually the goal only to 
show or hide the login error alert.
-   * When it gets success response it hides.
-   * @param {Response} resp
-   */
-  private onLoginSuccess = (resp: Response): void => {
+  private onLoginSuccess = (result: Boolean): void => {
     this.isLoginAlertDisplayed = false;
+    this.errorMessage = '';
+  }
+
+  private onLoginError = (resp: Boolean): void => {
+    Observable.combineLatest(
+      this.translateService.get('login.error.title'),
+      this.translateService.get('login.error.message')
+    ).first().subscribe(([title, message]: [string, string]) => {
+      this.errorMessage = message;
+      this.isLoginAlertDisplayed = true;
+    });
   }
 
   login() {
diff --git 
a/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.ts 
b/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.ts
index 87cdb41..a3ed9b8 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web/src/app/services/auth.service.ts
@@ -25,6 +25,7 @@ import {HttpClientService} from 
'@app/services/http-client.service';
 import {AppStateService} from '@app/services/storage/app-state.service';
 import {Router} from '@angular/router';
 import {Subscription} from 'rxjs/Subscription';
+import { Observer } from 'rxjs/Observer';
 
 export const IS_AUTHORIZED_APP_STATE_KEY: string = 'isAuthorized';
 export const IS_LOGIN_IN_PROGRESS_APP_STATE_KEY: string = 'isLoginInProgress';
@@ -75,30 +76,48 @@ export class AuthService {
    * @param {string} password
    * @returns {Observable<Response>}
    */
-  login(username: string, password: string): Observable<Response> {
+  login(username: string, password: string): Observable<Boolean> {
     this.setLoginInProgressAppState(true);
     const response$ = this.httpClient.postFormData('login', {
       username: username,
       password: password
-    });
+    }).share();
     response$.subscribe(
       (resp: Response) => this.onLoginResponse(resp),
       (resp: Response) => this.onLoginError(resp)
     );
-    return response$;
+    return response$.switchMap((resp: Response) => {
+      return Observable.create((observer: Observer<boolean>) => {
+        if (resp.ok) {
+          observer.next(resp.ok);
+        } else {
+          observer.error(resp);
+        }
+        observer.complete();
+      });
+    });
   }
 
   /**
    * The single unique entry point to request a logout action
    * @returns {Observable<boolean | Error>}
    */
-  logout(): Observable<Response> {
-    const response$ = this.httpClient.get('logout');
+  logout(): Observable<Boolean> {
+    const response$ = this.httpClient.get('logout').share();
     response$.subscribe(
       (resp: Response) => this.onLogoutResponse(resp),
       (resp: Response) => this.onLogoutError(resp)
     );
-    return response$;
+    return response$.switchMap((resp: Response) => {
+      return Observable.create((observer) => {
+        if (resp.ok) {
+          observer.next(resp.ok);
+        } else {
+          observer.error(resp);
+        }
+        observer.complete();
+      });
+    });
   }
 
   /**
diff --git a/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json 
b/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
index 00815f9..fec6991 100644
--- a/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
+++ b/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json
@@ -219,6 +219,8 @@
   "logIndexFilter.update.error": "Error at updating Log Index Filter for 
cluster <span class='cluster-name'>{{cluster}}</span>. {{message}}",
 
   "login.title": "Login",
+  "login.error.title": "Login error",
+  "login.error.message": "Unable to sign in. Invalid username/password 
combination.",
 
   "shipperConfiguration.title": "All Configuration",
   "shipperConfiguration.add": "Add",

-- 
To stop receiving notification emails like this one, please contact
ababiic...@apache.org.

Reply via email to