Merge pull request #3463 from vvlladd28/improvement/menu/trackBy
Improvement draw menu and breadCrumb
This commit is contained in:
commit
075138cc5c
@ -14,9 +14,11 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
|
import { HasUUID } from '@shared/models/id/has-uuid';
|
||||||
|
|
||||||
export declare type MenuSectionType = 'link' | 'toggle';
|
export declare type MenuSectionType = 'link' | 'toggle';
|
||||||
|
|
||||||
export class MenuSection {
|
export interface MenuSection extends HasUUID{
|
||||||
name: string;
|
name: string;
|
||||||
type: MenuSectionType;
|
type: MenuSectionType;
|
||||||
path: string;
|
path: string;
|
||||||
@ -26,12 +28,12 @@ export class MenuSection {
|
|||||||
pages?: Array<MenuSection>;
|
pages?: Array<MenuSection>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HomeSection {
|
export interface HomeSection {
|
||||||
name: string;
|
name: string;
|
||||||
places: Array<HomeSectionPlace>;
|
places: Array<HomeSectionPlace>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HomeSectionPlace {
|
export interface HomeSectionPlace {
|
||||||
name: string;
|
name: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
isMdiIcon?: boolean;
|
isMdiIcon?: boolean;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import { HomeSection, MenuSection } from '@core/services/menu.models';
|
|||||||
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||||
import { Authority } from '@shared/models/authority.enum';
|
import { Authority } from '@shared/models/authority.enum';
|
||||||
import { AuthUser } from '@shared/models/user.model';
|
import { AuthUser } from '@shared/models/user.model';
|
||||||
|
import { guid } from '@core/utils';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -74,24 +75,28 @@ export class MenuService {
|
|||||||
const sections: Array<MenuSection> = [];
|
const sections: Array<MenuSection> = [];
|
||||||
sections.push(
|
sections.push(
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'home.home',
|
name: 'home.home',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/home',
|
path: '/home',
|
||||||
icon: 'home'
|
icon: 'home'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'tenant.tenants',
|
name: 'tenant.tenants',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/tenants',
|
path: '/tenants',
|
||||||
icon: 'supervisor_account'
|
icon: 'supervisor_account'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'widget.widget-library',
|
name: 'widget.widget-library',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/widgets-bundles',
|
path: '/widgets-bundles',
|
||||||
icon: 'now_widgets'
|
icon: 'now_widgets'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'admin.system-settings',
|
name: 'admin.system-settings',
|
||||||
type: 'toggle',
|
type: 'toggle',
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
@ -99,18 +104,21 @@ export class MenuService {
|
|||||||
icon: 'settings',
|
icon: 'settings',
|
||||||
pages: [
|
pages: [
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'admin.general',
|
name: 'admin.general',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/settings/general',
|
path: '/settings/general',
|
||||||
icon: 'settings_applications'
|
icon: 'settings_applications'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'admin.outgoing-mail',
|
name: 'admin.outgoing-mail',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/settings/outgoing-mail',
|
path: '/settings/outgoing-mail',
|
||||||
icon: 'mail'
|
icon: 'mail'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'admin.security-settings',
|
name: 'admin.security-settings',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/settings/security-settings',
|
path: '/settings/security-settings',
|
||||||
@ -173,54 +181,63 @@ export class MenuService {
|
|||||||
const sections: Array<MenuSection> = [];
|
const sections: Array<MenuSection> = [];
|
||||||
sections.push(
|
sections.push(
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'home.home',
|
name: 'home.home',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/home',
|
path: '/home',
|
||||||
icon: 'home'
|
icon: 'home'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'rulechain.rulechains',
|
name: 'rulechain.rulechains',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/ruleChains',
|
path: '/ruleChains',
|
||||||
icon: 'settings_ethernet'
|
icon: 'settings_ethernet'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'customer.customers',
|
name: 'customer.customers',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/customers',
|
path: '/customers',
|
||||||
icon: 'supervisor_account'
|
icon: 'supervisor_account'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'asset.assets',
|
name: 'asset.assets',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/assets',
|
path: '/assets',
|
||||||
icon: 'domain'
|
icon: 'domain'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'device.devices',
|
name: 'device.devices',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/devices',
|
path: '/devices',
|
||||||
icon: 'devices_other'
|
icon: 'devices_other'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'entity-view.entity-views',
|
name: 'entity-view.entity-views',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/entityViews',
|
path: '/entityViews',
|
||||||
icon: 'view_quilt'
|
icon: 'view_quilt'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'widget.widget-library',
|
name: 'widget.widget-library',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/widgets-bundles',
|
path: '/widgets-bundles',
|
||||||
icon: 'now_widgets'
|
icon: 'now_widgets'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'dashboard.dashboards',
|
name: 'dashboard.dashboards',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/dashboards',
|
path: '/dashboards',
|
||||||
icon: 'dashboards'
|
icon: 'dashboards'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'audit-log.audit-logs',
|
name: 'audit-log.audit-logs',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/auditLogs',
|
path: '/auditLogs',
|
||||||
@ -316,30 +333,35 @@ export class MenuService {
|
|||||||
const sections: Array<MenuSection> = [];
|
const sections: Array<MenuSection> = [];
|
||||||
sections.push(
|
sections.push(
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'home.home',
|
name: 'home.home',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/home',
|
path: '/home',
|
||||||
icon: 'home'
|
icon: 'home'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'asset.assets',
|
name: 'asset.assets',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/assets',
|
path: '/assets',
|
||||||
icon: 'domain'
|
icon: 'domain'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'device.devices',
|
name: 'device.devices',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/devices',
|
path: '/devices',
|
||||||
icon: 'devices_other'
|
icon: 'devices_other'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'entity-view.entity-views',
|
name: 'entity-view.entity-views',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/entityViews',
|
path: '/entityViews',
|
||||||
icon: 'view_quilt'
|
icon: 'view_quilt'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: guid(),
|
||||||
name: 'dashboard.dashboards',
|
name: 'dashboard.dashboards',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
path: '/dashboards',
|
path: '/dashboards',
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
[ngClass]="{'tb-toggled' : sectionActive()}"></span>
|
[ngClass]="{'tb-toggled' : sectionActive()}"></span>
|
||||||
</a>
|
</a>
|
||||||
<ul id="docs-menu-{{section.name | nospace}}" class="tb-menu-toggle-list" [ngStyle]="{height: sectionHeight()}">
|
<ul id="docs-menu-{{section.name | nospace}}" class="tb-menu-toggle-list" [ngStyle]="{height: sectionHeight()}">
|
||||||
<li *ngFor="let page of section.pages">
|
<li *ngFor="let page of section.pages; trackBy: trackBySectionPages">
|
||||||
<tb-menu-link [section]="page"></tb-menu-link>
|
<tb-menu-link [section]="page"></tb-menu-link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@ -44,4 +44,8 @@ export class MenuToggleComponent implements OnInit {
|
|||||||
return '0px';
|
return '0px';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackBySectionPages(index: number, section: MenuSection){
|
||||||
|
return section.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
<ul fxFlex fxLayout="column" fxLayoutAlign="start stretch" class="tb-side-menu">
|
<ul fxFlex fxLayout="column" fxLayoutAlign="start stretch" class="tb-side-menu">
|
||||||
<li *ngFor="let section of menuSections$| async" [ngSwitch]="section.type === 'link'">
|
<li *ngFor="let section of menuSections$ | async; trackBy: trackByMenuSection" [ngSwitch]="section.type === 'link'">
|
||||||
<tb-menu-link *ngSwitchCase="true" [section]="section"></tb-menu-link>
|
<tb-menu-link *ngSwitchCase="true" [section]="section"></tb-menu-link>
|
||||||
<tb-menu-toggle *ngSwitchCase="false" [section]="section"></tb-menu-toggle>
|
<tb-menu-toggle *ngSwitchCase="false" [section]="section"></tb-menu-toggle>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { MenuService } from '@core/services/menu.service';
|
import { MenuService } from '@core/services/menu.service';
|
||||||
|
import { MenuSection } from '@core/services/menu.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-side-menu',
|
selector: 'tb-side-menu',
|
||||||
@ -29,6 +30,10 @@ export class SideMenuComponent implements OnInit {
|
|||||||
constructor(private menuService: MenuService) {
|
constructor(private menuService: MenuService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackByMenuSection(index: number, section: MenuSection){
|
||||||
|
return section.id;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
<h1 fxFlex fxHide.gt-sm *ngIf="lastBreadcrumb$ | async; let breadcrumb">
|
<h1 fxFlex fxHide.gt-sm *ngIf="lastBreadcrumb$ | async; let breadcrumb">
|
||||||
{{ breadcrumb.ignoreTranslate ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : breadcrumb.label) : (breadcrumb.label | translate) }}
|
{{ breadcrumb.ignoreTranslate ? (breadcrumb.labelFunction ? breadcrumb.labelFunction() : breadcrumb.label) : (breadcrumb.label | translate) }}
|
||||||
</h1>
|
</h1>
|
||||||
<span fxHide.lt-md fxLayout="row" *ngFor="let breadcrumb of breadcrumbs$ | async; last as isLast;" [ngSwitch]="isLast">
|
<span fxHide.lt-md fxLayout="row" *ngFor="let breadcrumb of breadcrumbs$ | async; trackBy: trackByBreadcrumbs; last as isLast;" [ngSwitch]="isLast">
|
||||||
<a *ngSwitchCase="false" [routerLink]="breadcrumb.link" [queryParams]="breadcrumb.queryParams">
|
<a *ngSwitchCase="false" [routerLink]="breadcrumb.link" [queryParams]="breadcrumb.queryParams">
|
||||||
<mat-icon *ngIf="breadcrumb.isMdiIcon" [svgIcon]="breadcrumb.icon">
|
<mat-icon *ngIf="breadcrumb.isMdiIcon" [svgIcon]="breadcrumb.icon">
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import { BreadCrumb, BreadCrumbConfig } from './breadcrumb';
|
|||||||
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Router } from '@angular/router';
|
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationEnd, Router } from '@angular/router';
|
||||||
import { distinctUntilChanged, filter, map } from 'rxjs/operators';
|
import { distinctUntilChanged, filter, map } from 'rxjs/operators';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { guid } from '@core/utils';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-breadcrumb',
|
selector: 'tb-breadcrumb',
|
||||||
@ -94,6 +95,7 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
|
|||||||
const isMdiIcon = icon.startsWith('mdi:');
|
const isMdiIcon = icon.startsWith('mdi:');
|
||||||
const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ];
|
const link = [ route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/') ];
|
||||||
const breadcrumb = {
|
const breadcrumb = {
|
||||||
|
id: guid(),
|
||||||
label,
|
label,
|
||||||
labelFunction,
|
labelFunction,
|
||||||
ignoreTranslate,
|
ignoreTranslate,
|
||||||
@ -110,4 +112,8 @@ export class BreadcrumbComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
return newBreadcrumbs;
|
return newBreadcrumbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackByBreadcrumbs(index: number, breadcrumb: BreadCrumb){
|
||||||
|
return breadcrumb.id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
import { ActivatedRouteSnapshot, Params } from '@angular/router';
|
import { ActivatedRouteSnapshot, Params } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { HasUUID } from '@shared/models/id/has-uuid';
|
||||||
|
|
||||||
export interface BreadCrumb {
|
export interface BreadCrumb extends HasUUID{
|
||||||
label: string;
|
label: string;
|
||||||
labelFunction?: () => string;
|
labelFunction?: () => string;
|
||||||
ignoreTranslate: boolean;
|
ignoreTranslate: boolean;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user