UI: Redesign user menu: move profile and security menu item to account item

This commit is contained in:
Vladyslav_Prykhodko 2023-07-11 10:40:04 +03:00
parent 738cb5cebf
commit f7b60e1c0e
12 changed files with 210 additions and 21 deletions

View File

@ -244,7 +244,7 @@ export class AuthService {
if (authState && authState.authUser) {
if (authState.authUser.authority === Authority.TENANT_ADMIN || authState.authUser.authority === Authority.CUSTOMER_USER) {
if ((this.userHasDefaultDashboard(authState) && authState.forceFullscreen) || authState.authUser.isPublic) {
if (path === 'profile' || path === 'security') {
if (path.startsWith('account')) {
if (this.userHasProfile(authState.authUser)) {
return false;
} else {

View File

@ -262,6 +262,34 @@ export class MenuService {
isMdiIcon: true
}
]
},
{
id: 'account',
name: 'profile.profile',
type: 'link',
path: '/account',
disabled: true,
icon: 'mdi:message-badge',
isMdiIcon: true,
pages: [
{
id: 'personal_info',
name: 'account.personal-info',
fullName: 'account.personal-info',
type: 'link',
path: '/account/profile',
icon: 'mdi:badge-account-horizontal',
isMdiIcon: true
},
{
id: 'security',
name: 'security.security',
fullName: 'security.security',
type: 'link',
path: '/account/security',
icon: 'lock'
}
]
}
);
return sections;
@ -634,6 +662,34 @@ export class MenuService {
icon: 'track_changes'
}
]
},
{
id: 'account',
name: 'profile.profile',
type: 'link',
path: '/account',
disabled: true,
icon: 'mdi:message-badge',
isMdiIcon: true,
pages: [
{
id: 'personal_info',
name: 'account.personal-info',
fullName: 'account.personal-info',
type: 'link',
path: '/account/profile',
icon: 'mdi:badge-account-horizontal',
isMdiIcon: true
},
{
id: 'security',
name: 'security.security',
fullName: 'security.security',
type: 'link',
path: '/account/security',
icon: 'lock'
}
]
}
);
return sections;
@ -885,6 +941,34 @@ export class MenuService {
icon: 'inbox'
}
]
},
{
id: 'account',
name: 'profile.profile',
type: 'link',
path: '/account',
disabled: true,
icon: 'mdi:message-badge',
isMdiIcon: true,
pages: [
{
id: 'personal_info',
name: 'account.personal-info',
fullName: 'account.personal-info',
type: 'link',
path: '/account/profile',
icon: 'mdi:badge-account-horizontal',
isMdiIcon: true
},
{
id: 'security',
name: 'security.security',
fullName: 'security.security',
type: 'link',
path: '/account/security',
icon: 'lock'
}
]
}
);
return sections;

View File

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { AfterViewInit, Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { fromEvent } from 'rxjs';
import { Store } from '@ngrx/store';
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
@ -27,10 +27,10 @@ import { MediaBreakpoints } from '@shared/models/constants';
import screenfull from 'screenfull';
import { MatSidenav } from '@angular/material/sidenav';
import { AuthState } from '@core/auth/auth.models';
import { WINDOW } from '@core/services/window.service';
import { instanceOfSearchableComponent, ISearchableComponent } from '@home/models/searchable-component.models';
import { ActiveComponentService } from '@core/services/active-component.service';
import { RouterTabsComponent } from '@home/components/router-tabs.component';
import { Router } from '@angular/router';
@Component({
selector: 'tb-home',
@ -65,8 +65,8 @@ export class HomeComponent extends PageComponent implements AfterViewInit, OnIni
hideLoadingBar = false;
constructor(protected store: Store<AppState>,
@Inject(WINDOW) private window: Window,
private activeComponentService: ActiveComponentService,
private router: Router,
public breakpointObserver: BreakpointObserver) {
super(store);
}
@ -120,7 +120,8 @@ export class HomeComponent extends PageComponent implements AfterViewInit, OnIni
}
goBack() {
this.window.history.back();
const dashboardId = this.authState.userDetails.additionalInfo.defaultDashboardId;
this.router.navigate(['dashboard', dashboardId]).then(() => {});
}
activeComponentChanged(activeComponent: any) {

View File

@ -17,6 +17,8 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { MenuService } from '@core/services/menu.service';
import { MenuSection } from '@core/services/menu.models';
import { Observable, of } from 'rxjs';
import { mergeMap, share } from 'rxjs/operators';
@Component({
selector: 'tb-side-menu',
@ -26,15 +28,23 @@ import { MenuSection } from '@core/services/menu.models';
})
export class SideMenuComponent implements OnInit {
menuSections$ = this.menuService.menuSections();
menuSections$: Observable<Array<MenuSection>>;
constructor(private menuService: MenuService) {
this.menuSections$ = this.menuService.menuSections().pipe(
mergeMap((sections) => this.filterSections(sections)),
share()
);
}
trackByMenuSection(index: number, section: MenuSection){
return section.id;
}
private filterSections(sections: Array<MenuSection>): Observable<Array<MenuSection>> {
return of(sections.filter(section => !section.disabled));
}
ngOnInit() {
}

View File

@ -0,0 +1,54 @@
///
/// Copyright © 2016-2023 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { RouterTabsComponent } from '@home/components/router-tabs.component';
import { Authority } from '@shared/models/authority.enum';
import { securityRoutes } from '@home/pages/security/security-routing.module';
import { profileRoutes } from '@home/pages/profile/profile-routing.module';
const routes: Routes = [
{
path: 'account',
component: RouterTabsComponent,
data: {
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN, Authority.CUSTOMER_USER],
breadcrumb: {
label: 'account.account',
icon: 'account_circle'
}
},
children: [
{
path: '',
children: [],
data: {
auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN, Authority.CUSTOMER_USER],
redirectTo: '/account/profile',
}
},
...profileRoutes,
...securityRoutes
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AccountRoutingModule { }

View File

@ -0,0 +1,28 @@
///
/// Copyright © 2016-2023 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { NgModule } from '@angular/core';
import { AccountRoutingModule } from '@home/pages/account/account-routing.module';
import { CommonModule } from '@angular/common';
@NgModule({
declarations: [ ],
imports: [
CommonModule,
AccountRoutingModule
]
})
export class AccountModule { }

View File

@ -42,6 +42,7 @@ import { AlarmModule } from '@home/pages/alarm/alarm.module';
import { EntitiesModule } from '@home/pages/entities/entities.module';
import { FeaturesModule } from '@home/pages/features/features.module';
import { NotificationModule } from '@home/pages/notification/notification.module';
import { AccountModule } from '@home/pages/account/account.module';
@NgModule({
exports: [
@ -70,7 +71,8 @@ import { NotificationModule } from '@home/pages/notification/notification.module
ApiUsageModule,
OtaUpdateModule,
UserModule,
VcModule
VcModule,
AccountModule
]
})
export class HomePagesModule { }

View File

@ -40,7 +40,7 @@ export class UserProfileResolver implements Resolve<User> {
}
}
const routes: Routes = [
export const profileRoutes: Routes = [
{
path: 'profile',
component: ProfileComponent,
@ -59,6 +59,13 @@ const routes: Routes = [
}
];
const routes: Routes = [
{
path: 'profile',
redirectTo: 'account/profile'
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],

View File

@ -53,7 +53,7 @@ export class UserTwoFAProvidersResolver implements Resolve<Array<TwoFactorAuthPr
}
}
const routes: Routes = [
export const securityRoutes: Routes = [
{
path: 'security',
component: SecurityComponent,
@ -73,6 +73,13 @@ const routes: Routes = [
}
];
const routes: Routes = [
{
path: 'security',
redirectTo: '/account/security'
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],

View File

@ -28,13 +28,9 @@
</button>
<mat-menu #userMenu="matMenu" xPosition="before">
<div class="tb-user-menu-items" *ngIf="authority$ | async; let authority">
<button mat-menu-item (click)="openProfile()">
<button mat-menu-item (click)="openAccount()">
<mat-icon class="material-icons">account_circle</mat-icon>
<span translate>home.profile</span>
</button>
<button mat-menu-item (click)="openSecurity()">
<mat-icon class="material-icons">lock</mat-icon>
<span translate>security.security</span>
<span translate>account.account</span>
</button>
<button mat-menu-item (click)="logout()">
<mat-icon class="material-icons">exit_to_app</mat-icon>

View File

@ -102,12 +102,8 @@ export class UserMenuComponent implements OnInit, OnDestroy {
return name;
}
openProfile(): void {
this.router.navigate(['profile']);
}
openSecurity(): void {
this.router.navigate(['security']);
openAccount(): void {
this.router.navigate(['account']);
}
logout(): void {

View File

@ -10,6 +10,10 @@
"permission-denied": "Permission Denied",
"permission-denied-text": "You don't have permission to perform this operation!"
},
"account": {
"account": "Account",
"personal-info": "Personal info"
},
"action": {
"activate": "Activate",
"suspend": "Suspend",