mirror of
https://github.com/akveo/ngx-admin.git
synced 2025-12-16 23:40:14 +01:00
sidebar refactoring
This commit is contained in:
parent
38e1c6cfa3
commit
515684f424
4 changed files with 168 additions and 158 deletions
121
src/app/app.menu.ts
Normal file
121
src/app/app.menu.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
export const menuItems = [
|
||||
{
|
||||
title: 'Dashboard',
|
||||
component: 'Dashboard',
|
||||
icon: 'ion-android-home',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 0
|
||||
},
|
||||
{
|
||||
title: 'UI Features',
|
||||
component: 'Ui',
|
||||
icon: 'ion-android-laptop',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 200,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Typography',
|
||||
component: 'Typography',
|
||||
},
|
||||
{
|
||||
title: 'Buttons',
|
||||
component: 'Buttons',
|
||||
},
|
||||
{
|
||||
title: 'Icons',
|
||||
component: 'Icons',
|
||||
},
|
||||
{
|
||||
title: 'Grid',
|
||||
component: 'Grid',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Maps',
|
||||
component: 'Maps',
|
||||
icon: 'ion-ios-location-outline',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 300,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Google Maps',
|
||||
component: 'GoogleMaps',
|
||||
},
|
||||
{
|
||||
title: 'Leaflet Maps',
|
||||
component: 'LeafletMaps',
|
||||
},
|
||||
{
|
||||
title: 'Bubble Maps',
|
||||
component: 'BubbleMaps',
|
||||
},
|
||||
{
|
||||
title: 'Line Maps',
|
||||
component: 'LineMaps',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Charts',
|
||||
component: 'Charts',
|
||||
icon: 'ion-stats-bars',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 400,
|
||||
subMenu: [
|
||||
// {
|
||||
// title: 'Chart Js',
|
||||
// component: 'ChartJs',
|
||||
// },
|
||||
{
|
||||
title: 'ChartistJs',
|
||||
component: 'ChartistJs',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Form Elements',
|
||||
component: 'Forms',
|
||||
icon: 'ion-compose',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 500,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Form Inputs',
|
||||
component: 'Inputs',
|
||||
},
|
||||
{
|
||||
title: 'Form Layouts',
|
||||
component: 'Layouts',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Menu Level 1',
|
||||
icon: 'ion-ios-more',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Menu Level 1.1',
|
||||
disabled: true,
|
||||
selected: false,
|
||||
expanded: false
|
||||
},
|
||||
{
|
||||
title: 'Menu Level 1.2',
|
||||
subMenu: [{
|
||||
title: 'Menu Level 1.2.1',
|
||||
disabled: true,
|
||||
selected: false,
|
||||
expanded: false
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
|
@ -5,9 +5,6 @@ import {AppState} from '../../../app.state';
|
|||
import {layoutSizes} from '../../../theme';
|
||||
import {SidebarService} from './sidebar.service';
|
||||
|
||||
// TODO: separate menu and sidebar
|
||||
// TODO: move some functionality to decorators
|
||||
|
||||
@Component({
|
||||
selector: 'sidebar',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
|
@ -36,15 +33,10 @@ export class Sidebar {
|
|||
private _sidebarService:SidebarService,
|
||||
private _state:AppState) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.menuItems = this._sidebarService.getMenuItems();
|
||||
this.selectMenuItem();
|
||||
this._router.root.subscribe(() => this.selectMenuItem());
|
||||
this._router.root.subscribe((path) => this._selectMenuItem(path));
|
||||
}
|
||||
|
||||
// TODO: is it really the best event for this kind of things?
|
||||
ngAfterViewInit() {
|
||||
this.updateSidebarHeight();
|
||||
}
|
||||
|
|
@ -102,28 +94,9 @@ export class Sidebar {
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: there is a bug in the router thus all child routers are considered as active
|
||||
private selectMenuItem() {
|
||||
let currentMenu;
|
||||
private _selectMenuItem(currentPath = null) {
|
||||
|
||||
let isCurrent = (instructions) => (instructions.filter(i => typeof i !== 'undefined').length > 0 ? this._router.isRouteActive(this._router.generate(instructions)) : false);
|
||||
let assignCurrent = (menu) => (menu.selected ? currentMenu = menu : null);
|
||||
|
||||
this.menuItems.forEach(function (menu: any) {
|
||||
|
||||
menu.selected = isCurrent([menu.name]);
|
||||
menu.expanded = menu.expanded || menu.selected;
|
||||
assignCurrent(menu);
|
||||
|
||||
if (menu.subMenu) {
|
||||
menu.subMenu.forEach(function (subMenu) {
|
||||
subMenu.selected = isCurrent([menu.name, subMenu.name]) && !subMenu.disabled;
|
||||
assignCurrent(menu);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// notifies all subscribers
|
||||
let currentMenu = this._sidebarService.selectMenuItem(this._router, this.menuItems, currentPath);
|
||||
this._state.notifyDataChanged('menu.activeLink', currentMenu);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<aside class="al-sidebar" (mouseleave)="hoverElemTop=outOfArea">
|
||||
<aside class="al-sidebar" (mouseleave)="hoverElemTop=outOfArea" sidebarResize>
|
||||
<ul class="al-sidebar-list">
|
||||
<li *ngFor="let item of menuItems" class="al-sidebar-list-item"
|
||||
[ngClass]="{'selected': item.selected, 'with-sub-menu': item.subMenu}">
|
||||
|
||||
<a *ngIf="!item.subMenu" [routerLink]="[item.name]" class="al-sidebar-list-link">
|
||||
<a *ngIf="!item.subMenu" [routerLink]="[item.component]" class="al-sidebar-list-link">
|
||||
<i class="{{ item.icon }}"></i><span>{{ item.title }}</span>
|
||||
</a>
|
||||
|
||||
|
|
@ -27,11 +27,11 @@
|
|||
[ngClass]="{expanded: subitem.expanded, 'slide-right': subitem.slideRight}">
|
||||
<li *ngFor="let subSubitem of subitem.subMenu" (mouseenter)="hoverItem($event, item)"
|
||||
[ngClass]="{selected: subitem.selected}">
|
||||
<a (mouseenter)="hoverItem($event, item)" [routerLink]="[item.name, subitem.name, subSubitem.name]">
|
||||
<a (mouseenter)="hoverItem($event, item)" [routerLink]="[item.component, subitem.component, subSubitem.component]">
|
||||
{{ subSubitem.title }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a *ngIf="!subitem.subMenu" [routerLink]="[item.name, subitem.name]"
|
||||
<a *ngIf="!subitem.subMenu" [routerLink]="[item.component, subitem.component]"
|
||||
(mouseenter)="hoverItem($event, item)" target="{{subitem.blank ? '_blank' : '_self'}}">
|
||||
{{ subitem.title}}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1,133 +1,49 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {menuItems} from '../../../app.menu';
|
||||
|
||||
@Injectable()
|
||||
export class SidebarService {
|
||||
|
||||
staticMenuItems = [
|
||||
{
|
||||
title: 'Dashboard',
|
||||
name: 'Dashboard',
|
||||
icon: 'ion-android-home',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 0
|
||||
},
|
||||
{
|
||||
title: 'UI Features',
|
||||
name: 'Ui',
|
||||
icon: 'ion-android-laptop',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 200,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Typography',
|
||||
name: 'Typography',
|
||||
},
|
||||
{
|
||||
title: 'Buttons',
|
||||
name: 'Buttons',
|
||||
},
|
||||
{
|
||||
title: 'Icons',
|
||||
name: 'Icons',
|
||||
},
|
||||
{
|
||||
title: 'Grid',
|
||||
name: 'Grid',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Maps',
|
||||
name: 'Maps',
|
||||
icon: 'ion-ios-location-outline',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 300,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Google Maps',
|
||||
name: 'GoogleMaps',
|
||||
},
|
||||
{
|
||||
title: 'Leaflet Maps',
|
||||
name: 'LeafletMaps',
|
||||
},
|
||||
{
|
||||
title: 'Bubble Maps',
|
||||
name: 'BubbleMaps',
|
||||
},
|
||||
{
|
||||
title: 'Line Maps',
|
||||
name: 'LineMaps',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Charts',
|
||||
name: 'Charts',
|
||||
icon: 'ion-stats-bars',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 400,
|
||||
subMenu: [
|
||||
// {
|
||||
// title: 'Chart Js',
|
||||
// name: 'ChartJs',
|
||||
// },
|
||||
{
|
||||
title: 'ChartistJs',
|
||||
name: 'ChartistJs',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Form Elements',
|
||||
name: 'Forms',
|
||||
icon: 'ion-compose',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
order: 500,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Form Inputs',
|
||||
name: 'Inputs',
|
||||
},
|
||||
{
|
||||
title: 'Form Layouts',
|
||||
name: 'Layouts',
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Menu Level 1',
|
||||
icon: 'ion-ios-more',
|
||||
selected: false,
|
||||
expanded: false,
|
||||
subMenu: [
|
||||
{
|
||||
title: 'Menu Level 1.1',
|
||||
disabled: true,
|
||||
selected: false,
|
||||
expanded: false
|
||||
},
|
||||
{
|
||||
title: 'Menu Level 1.2',
|
||||
subMenu: [{
|
||||
title: 'Menu Level 1.2.1',
|
||||
disabled: true,
|
||||
selected: false,
|
||||
expanded: false
|
||||
}]
|
||||
}
|
||||
]
|
||||
}];
|
||||
|
||||
constructor() {
|
||||
getMenuItems() {
|
||||
return menuItems;
|
||||
}
|
||||
|
||||
getMenuItems() {
|
||||
return this.staticMenuItems;
|
||||
selectMenuItem(router, items:Array<any>, currentPath:string) {
|
||||
let currentMenu;
|
||||
|
||||
let assignCurrent = (menu) => (menu.selected ? currentMenu = menu : null);
|
||||
|
||||
items.forEach((menu: any) => {
|
||||
|
||||
menu.selected = this._isCurrent(router, this._generateRoute(router, [menu.component]));
|
||||
menu.expanded = menu.expanded || menu.selected;
|
||||
assignCurrent(menu);
|
||||
|
||||
if (menu.subMenu) {
|
||||
menu.subMenu.forEach((subMenu) => {
|
||||
let route = this._generateRoute(router, [menu.component, subMenu.component]);
|
||||
subMenu.selected = !subMenu.disabled && this._isCurrent(router, route) && this._resolvePath(route, '') == currentPath;
|
||||
assignCurrent(menu);
|
||||
});
|
||||
}
|
||||
});
|
||||
return currentMenu;
|
||||
}
|
||||
|
||||
private _isCurrent(router, route) {
|
||||
return route ? router.isRouteActive(route) : false;
|
||||
}
|
||||
|
||||
private _generateRoute(router, instructions) {
|
||||
return instructions.filter(i => typeof i !== 'undefined').length > 0 ? router.generate(instructions) : null;
|
||||
}
|
||||
|
||||
private _resolvePath(instruction, collected) {
|
||||
if (instruction !== null) {
|
||||
collected += instruction.urlPath + '/';
|
||||
return this._resolvePath(instruction.child, collected)
|
||||
} else {
|
||||
return collected.slice(0, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue