sidebar refactoring

This commit is contained in:
nixa 2016-05-13 16:11:32 +03:00
parent 38e1c6cfa3
commit 515684f424
4 changed files with 168 additions and 158 deletions

121
src/app/app.menu.ts Normal file
View 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
}]
}
]
}
];

View file

@ -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);
}
}

View file

@ -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>

View file

@ -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);
}
}
}