Browse Source

UI: move user menu into the side rail and turn it into a full-width trigger button

User-menu now lives at the bottom of the side-menu toolbar (separated by a 1px border) instead of in the top toolbar. Drop the displayUserInfo input and the lt-lg hide-name behaviour — the side rail always shows the name + authority next to the avatar via a single mat-menu trigger button that opens upward. Dashboard-page user-menu usages drop the now-unused displayUserInfo attribute.
pull/15888/head
Igor Kulikov 4 months ago
parent
commit
2bbcf4ecda
  1. 4
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html
  2. 2
      ui-ngx/src/app/modules/home/home.component.html
  3. 5
      ui-ngx/src/app/modules/home/home.component.scss
  4. 53
      ui-ngx/src/app/shared/components/user-menu.component.html
  5. 38
      ui-ngx/src/app/shared/components/user-menu.component.scss
  6. 5
      ui-ngx/src/app/shared/components/user-menu.component.ts

4
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.html

@ -26,7 +26,7 @@
<div class="tb-dashboard-action-panels flex flex-col items-stretch justify-center gt-sm:flex-row gt-sm:items-center gt-sm:justify-between">
<div class="tb-dashboard-action-panel tb-left-panel" [class.!hidden]="isMobileApp && !isEdit">
@if (!isPublicUser() && forceFullscreen) {
<tb-user-menu class="gt-sm:!hidden" displayUserInfo="true">
<tb-user-menu class="gt-sm:!hidden">
</tb-user-menu>
}
@if (isEdit) {
@ -88,7 +88,7 @@
<mat-icon>arrow_forward</mat-icon>
</button>
@if (!isPublicUser() && forceFullscreen) {
<tb-user-menu class="lt-md:!hidden" displayUserInfo="true">
<tb-user-menu class="lt-md:!hidden">
</tb-user-menu>
}
<button [class.!hidden]="!showRightLayoutSwitch()" mat-icon-button

2
ui-ngx/src/app/modules/home/home.component.html

@ -33,6 +33,7 @@
<div class="flex-1 overflow-y-auto">
<tb-side-menu></tb-side-menu>
</div>
<tb-user-menu></tb-user-menu>
</mat-toolbar>
</mat-sidenav>
<mat-sidenav-content>
@ -78,7 +79,6 @@
</button>
}
<tb-notification-bell></tb-notification-bell>
<tb-user-menu [displayUserInfo]="!displaySearchMode()"></tb-user-menu>
</mat-toolbar>
@if (!hideLoadingBar && (isLoading$ | async)) {
<mat-progress-bar color="warn" style="z-index: 10; margin-bottom: -4px; width: 100%;" mode="indeterminate"

5
ui-ngx/src/app/modules/home/home.component.scss

@ -50,10 +50,13 @@
}
}
.tb-side-menu-toolbar {
overflow-y: auto;
overflow: hidden;
height: inherit;
padding: 0;
border-right: 1px solid rgba(0, 0, 0, 0.12);
tb-user-menu {
border-top: 1px solid rgba(0, 0, 0, 0.12);
}
}
}
.tb-primary-toolbar {

53
ui-ngx/src/app/shared/components/user-menu.component.html

@ -15,35 +15,28 @@
limitations under the License.
-->
<section class="flex flex-row">
@if (displayUserInfo) {
<div class="tb-user-info flex flex-row lt-lg:!hidden">
<mat-icon class="material-icons tb-mini-avatar">account_circle</mat-icon>
<div class="flex flex-col items-stretch justify-center">
@if (userDisplayName$ | async; as userDisplayName) {
<span class="tb-user-display-name">{{ userDisplayName }}</span>
}
@if (authorityName$ | async; as authorityName) {
<span class="tb-user-authority">{{ authorityName | translate }}</span>
}
</div>
<button mat-button class="tb-user-menu" [matMenuTriggerFor]="userMenu">
<tb-icon class="material-icons tb-mini-avatar">mdi:account-circle-outline</tb-icon>
<div class="flex flex-col items-stretch justify-center">
@if (userDisplayName$ | async; as userDisplayName) {
<span class="tb-user-display-name">{{ userDisplayName }}</span>
}
@if (authorityName$ | async; as authorityName) {
<span class="tb-user-authority">{{ authorityName | translate }}</span>
}
</div>
</button>
<mat-menu #userMenu="matMenu" xPosition="before" yPosition="above">
@if (authority$ | async; as authority) {
<div class="tb-user-menu-items">
<button mat-menu-item (click)="openAccount()">
<mat-icon class="material-icons">account_circle</mat-icon>
<span translate>account.account</span>
</button>
<button mat-menu-item (click)="logout()">
<mat-icon class="material-icons">exit_to_app</mat-icon>
<span translate>home.logout</span>
</button>
</div>
}
<button mat-icon-button [matMenuTriggerFor]="userMenu">
<mat-icon class="material-icons">more_vert</mat-icon>
</button>
<mat-menu #userMenu="matMenu" xPosition="before">
@if (authority$ | async; as authority) {
<div class="tb-user-menu-items">
<button mat-menu-item (click)="openAccount()">
<mat-icon class="material-icons">account_circle</mat-icon>
<span translate>account.account</span>
</button>
<button mat-menu-item (click)="logout()">
<mat-icon class="material-icons">exit_to_app</mat-icon>
<span translate>home.logout</span>
</button>
</div>
}
</mat-menu>
</section>
</mat-menu>

38
ui-ngx/src/app/shared/components/user-menu.component.scss

@ -14,37 +14,47 @@
* limitations under the License.
*/
:host {
div.tb-user-info {
button.tb-user-menu {
width: 250px;
height: 100%;
padding: 16px;
display: flex;
flex-direction: row;
justify-content: start;
gap: 8px;
line-height: 1.5;
span {
text-transform: none;
text-align: start;
}
span.tb-user-display-name {
font-size: .8rem;
font-weight: 300;
letter-spacing: .008em;
color: rgba(0, 0, 0, 0.76);
font-size: 14px;
line-height: 16px;
font-weight: 500;
letter-spacing: 0.25px;
}
span.tb-user-authority {
font-size: .8rem;
font-weight: 300;
letter-spacing: .005em;
opacity: .8;
color: rgba(0, 0, 0, 0.54);
font-size: 12px;
line-height: 16px;
font-weight: 400;
letter-spacing: 0.25px;
}
}
.mat-icon.tb-mini-avatar {
width: 36px;
height: 36px;
margin: auto 8px;
font-size: 36px;
cursor: default;
width: 32px;
height: 32px;
font-size: 32px;
margin: 0;
}
}
.tb-user-menu-items {
min-width: 256px;
min-width: 250px;
}

5
ui-ngx/src/app/shared/components/user-menu.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { User } from '@shared/models/user.model';
import { Authority } from '@shared/models/authority.enum';
import { select, Store } from '@ngrx/store';
@ -23,6 +23,7 @@ import { selectAuthUser, selectUserDetails } from '@core/auth/auth.selectors';
import { map } from 'rxjs/operators';
import { AuthService } from '@core/auth/auth.service';
import { Router } from '@angular/router';
import { MatMenu, MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'tb-user-menu',
@ -33,8 +34,6 @@ import { Router } from '@angular/router';
})
export class UserMenuComponent implements OnInit, OnDestroy {
@Input() displayUserInfo: boolean;
authorities = Authority;
authority$ = this.store.pipe(

Loading…
Cancel
Save