UI: Redesign user menu: move profile and security menu item to account item
This commit is contained in:
parent
738cb5cebf
commit
f7b60e1c0e
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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() {
|
||||
}
|
||||
|
||||
|
||||
@ -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 { }
|
||||
28
ui-ngx/src/app/modules/home/pages/account/account.module.ts
Normal file
28
ui-ngx/src/app/modules/home/pages/account/account.module.ts
Normal 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 { }
|
||||
@ -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 { }
|
||||
|
||||
@ -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],
|
||||
|
||||
@ -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],
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user