From af75beac78be4365760aafb76d669df1c7945f64 Mon Sep 17 00:00:00 2001
From: Giuseppe Digilio <giuseppe.digilio@4science.it>
Date: Fri, 8 Mar 2019 17:37:36 +0100
Subject: [PATCH] Added navigation bar user menu

---
 src/app/core/auth/selectors.ts                |  6 ++-
 .../auth-nav-menu.component.html              |  7 ++-
 .../user-menu/user-menu.component.html        |  9 ++++
 .../user-menu/user-menu.component.scss        |  0
 .../user-menu/user-menu.component.ts          | 45 +++++++++++++++++++
 src/app/shared/log-out/log-out.component.html |  3 +-
 src/app/shared/log-out/log-out.component.ts   | 39 ++--------------
 7 files changed, 66 insertions(+), 43 deletions(-)
 create mode 100644 src/app/shared/auth-nav-menu/user-menu/user-menu.component.html
 create mode 100644 src/app/shared/auth-nav-menu/user-menu/user-menu.component.scss
 create mode 100644 src/app/shared/auth-nav-menu/user-menu/user-menu.component.ts

diff --git a/src/app/core/auth/selectors.ts b/src/app/core/auth/selectors.ts
index fa637981ae..8c88e0fce5 100644
--- a/src/app/core/auth/selectors.ts
+++ b/src/app/core/auth/selectors.ts
@@ -8,6 +8,7 @@ import { createSelector } from '@ngrx/store';
  */
 import { AuthState } from './auth.reducer';
 import { AppState } from '../../app.reducer';
+import { EPerson } from '../eperson/models/eperson.model';
 
 /**
  * Returns the user state.
@@ -35,11 +36,12 @@ const _isAuthenticatedLoaded = (state: AuthState) => state.loaded;
 
 /**
  * Return the users state
+ * NOTE: when state is REHYDRATED user object lose prototype so return always a new EPerson object
  * @function _getAuthenticatedUser
  * @param {State} state
- * @returns {User}
+ * @returns {EPerson}
  */
-const _getAuthenticatedUser = (state: AuthState) => state.user;
+const _getAuthenticatedUser = (state: AuthState) => Object.assign(new EPerson(), state.user);
 
 /**
  * Returns the authentication error.
diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.html b/src/app/shared/auth-nav-menu/auth-nav-menu.component.html
index 56a62c0fbd..b560283ad5 100644
--- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.html
+++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.html
@@ -13,10 +13,9 @@
   <li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item">
     <div ngbDropdown placement="bottom-right" class="d-inline-block" @fadeInOut>
       <a href="#" id="dropdownUser" (click)="$event.preventDefault()" class="px-1" ngbDropdownToggle><i class="fas fa-user-circle fa-lg fa-fw" [title]="'nav.logout' | translate"></i></a>
-      <ul id="logoutDropdownMenu" ngbDropdownMenu aria-labelledby="dropdownUser">
-        <li class="dropdown-item">{{(user | async).name}}</li>
-        <li class="dropdown-item"><ds-log-out></ds-log-out></li>
-      </ul>
+      <div id="logoutDropdownMenu" ngbDropdownMenu aria-labelledby="dropdownUser">
+        <ds-user-menu></ds-user-menu>
+      </div>
     </div>
   </li>
   <li *ngIf="(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
diff --git a/src/app/shared/auth-nav-menu/user-menu/user-menu.component.html b/src/app/shared/auth-nav-menu/user-menu/user-menu.component.html
new file mode 100644
index 0000000000..7c576fee86
--- /dev/null
+++ b/src/app/shared/auth-nav-menu/user-menu/user-menu.component.html
@@ -0,0 +1,9 @@
+<ds-loading *ngIf="(loading$ | async)"></ds-loading>
+<div *ngIf="!(loading$ | async)">
+  <span class="dropdown-item-text">{{(user$ | async).name}}</span>
+  <a class="dropdown-item" [routerLink]="['/mydspace']" routerLinkActive="active">{{'nav.mydspace' | translate}}</a>
+  <div class="dropdown-divider"></div>
+  <ds-log-out></ds-log-out>
+</div>
+
+
diff --git a/src/app/shared/auth-nav-menu/user-menu/user-menu.component.scss b/src/app/shared/auth-nav-menu/user-menu/user-menu.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/app/shared/auth-nav-menu/user-menu/user-menu.component.ts b/src/app/shared/auth-nav-menu/user-menu/user-menu.component.ts
new file mode 100644
index 0000000000..41298b559f
--- /dev/null
+++ b/src/app/shared/auth-nav-menu/user-menu/user-menu.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit } from '@angular/core';
+
+import { Observable } from 'rxjs';
+import { select, Store } from '@ngrx/store';
+
+import { EPerson } from '../../../core/eperson/models/eperson.model';
+import { AppState } from '../../../app.reducer';
+import { getAuthenticatedUser, isAuthenticationLoading } from '../../../core/auth/selectors';
+
+@Component({
+  selector: 'ds-user-menu',
+  templateUrl: './user-menu.component.html',
+  styleUrls: ['./user-menu.component.scss']
+})
+export class UserMenuComponent implements OnInit {
+
+  /**
+   * True if the authentication is loading.
+   * @type {Observable<boolean>}
+   */
+  public loading$: Observable<boolean>;
+
+  /**
+   * The authenticated user.
+   * @type {Observable<EPerson>}
+   */
+  public user$: Observable<EPerson>;
+
+  constructor(private store: Store<AppState>) {
+  }
+
+  ngOnInit(): void {
+
+    // set loading
+    this.loading$ = this.store.pipe(select(isAuthenticationLoading));
+
+    // set user
+    this.user$ = this.store.pipe(select(getAuthenticatedUser));
+
+    this.user$.subscribe((user) => {
+      console.log(user, user.name);
+    })
+
+  }
+}
diff --git a/src/app/shared/log-out/log-out.component.html b/src/app/shared/log-out/log-out.component.html
index f3ceae0087..ab398d1735 100644
--- a/src/app/shared/log-out/log-out.component.html
+++ b/src/app/shared/log-out/log-out.component.html
@@ -1,5 +1,4 @@
-<ds-loading *ngIf="(loading | async)"></ds-loading>
-<div *ngIf="!(loading | async)" class="form-login px-4 py-3">
+<div class="form-login px-4">
 
   <div *ngIf="(error | async) && hasError" class="alert alert-danger" role="alert" @fadeOut>{{ error | async }}</div>
 
diff --git a/src/app/shared/log-out/log-out.component.ts b/src/app/shared/log-out/log-out.component.ts
index 9e8e7f7865..0a6b936cd5 100644
--- a/src/app/shared/log-out/log-out.component.ts
+++ b/src/app/shared/log-out/log-out.component.ts
@@ -1,21 +1,12 @@
-import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
 import { Router } from '@angular/router';
 
-// @ngrx
+import { Observable } from 'rxjs';
 import { select, Store } from '@ngrx/store';
 
-// actions
 import { LogOutAction } from '../../core/auth/auth.actions';
-
-// reducers
-import {
-  getLogOutError,
-  isAuthenticated,
-  isAuthenticationLoading,
-} from '../../core/auth/selectors';
-
+import { getLogOutError, } from '../../core/auth/selectors';
 import { AppState } from '../../app.reducer';
-import { Observable } from 'rxjs';
 import { fadeOut } from '../animations/fade';
 
 @Component({
@@ -24,25 +15,13 @@ import { fadeOut } from '../animations/fade';
   styleUrls: ['./log-out.component.scss'],
   animations: [fadeOut]
 })
-export class LogOutComponent implements OnDestroy, OnInit {
+export class LogOutComponent implements OnInit {
   /**
    * The error if authentication fails.
    * @type {Observable<string>}
    */
   public error: Observable<string>;
 
-  /**
-   * True if the logout is loading.
-   * @type {boolean}
-   */
-  public loading: Observable<boolean>;
-
-  /**
-   * Component state.
-   * @type {boolean}
-   */
-  private alive = true;
-
   /**
    * @constructor
    * @param {Store<State>} store
@@ -51,22 +30,12 @@ export class LogOutComponent implements OnDestroy, OnInit {
               private store: Store<AppState>) {
   }
 
-  /**
-   *  Lifecycle hook that is called when a directive, pipe or service is destroyed.
-   */
-  public ngOnDestroy() {
-    this.alive = false;
-  }
-
   /**
    * Lifecycle hook that is called after data-bound properties of a directive are initialized.
    */
   ngOnInit() {
     // set error
     this.error = this.store.pipe(select(getLogOutError));
-
-    // set loading
-    this.loading = this.store.pipe(select(isAuthenticationLoading));
   }
 
   /**
-- 
GitLab