icons added, sidebar classes, better fonts loader

This commit is contained in:
nixa 2016-04-28 13:08:33 +03:00
parent 53aa869d22
commit b13c169995
8 changed files with 203 additions and 85 deletions

24
bower.json Normal file
View file

@ -0,0 +1,24 @@
{
"name": "angular2-webpack-starter",
"description": "Angular 2 admin template.",
"main": "",
"authors": [
"Patrick Stapleton <patrick@angularclass.com>"
],
"license": "MIT",
"moduleType": [
"es6"
],
"homepage": "",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"Ionicons": "ionicons#~2.0.1"
}
}

View file

@ -48,13 +48,13 @@ module.exports = {
* *
* See: http://webpack.github.io/docs/configuration.html#resolve-extensions * See: http://webpack.github.io/docs/configuration.html#resolve-extensions
*/ */
extensions: ['', '.ts', '.js'], extensions: ['', '.ts', '.js', '.css', '.scss'],
// Make sure root is src // Make sure root is src
root: helpers.root('src'), root: helpers.root('src'),
// remove other default values // remove other default values
modulesDirectories: ['node_modules'] modulesDirectories: ['node_modules', 'bower_components']
}, },
@ -128,15 +128,15 @@ module.exports = {
{ {
test: /\.scss$/, test: /\.scss$/,
loaders: ['raw-loader','sass-loader'] loaders: ['raw-loader', 'sass-loader']
}, },
{ {
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" test: /\.woff(2)?(\?v=.+)?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff"
}, },
{ {
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "file-loader" test: /\.(ttf|eot|svg)(\?v=.+)?$/, loader: "file-loader"
}, },
{ {

View file

@ -38,7 +38,7 @@
"docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./src/", "docs": "npm run typedoc -- --options typedoc.json --exclude '**/*.spec.ts' ./src/",
"start": "npm run server:dev", "start": "npm run server:dev",
"start:hmr": "npm run server:dev:hmr", "start:hmr": "npm run server:dev:hmr",
"postinstall": "npm run typings -- install", "postinstall": "npm run typings -- install && bower install",
"preversion": "npm run build", "preversion": "npm run build",
"version": "npm run build", "version": "npm run build",
"postversion": "git push && git push --tags" "postversion": "git push && git push --tags"

View file

@ -6,10 +6,13 @@ import {RouteConfig, Router} from 'angular2/router';
import {Pages} from './pages'; import {Pages} from './pages';
/* // TODO: is it really the best place to globally require that dependency?
* App Component require("!style!css!sass!./theme/sass/_ionicons.scss");
* Top Level Component
*/ /*
* App Component
* Top Level Component
*/
@Component({ @Component({
selector: 'app', selector: 'app',
pipes: [ ], pipes: [ ],
@ -31,7 +34,7 @@ import {Pages} from './pages';
}) })
@RouteConfig([ @RouteConfig([
{ {
path: '/pages/...', path: '/...',
name: 'Pages', name: 'Pages',
component: Pages, component: Pages,
useAsDefault: true useAsDefault: true

View file

@ -0,0 +1,3 @@
$ionicons-font-path: "~Ionicons/fonts";
@import "~Ionicons/scss/ionicons";

View file

@ -1,6 +1,7 @@
import {Component, ElementRef} from 'angular2/core'; import {Component, ElementRef} from 'angular2/core';
import {SidebarService} from './sidebar.service'; import {SidebarService} from './sidebar.service';
import {Location} from 'angular2/router';
@Component({ @Component({
selector: 'sidebar', selector: 'sidebar',
@ -11,12 +12,70 @@ import {SidebarService} from './sidebar.service';
pipes: [] pipes: []
}) })
export class Sidebar { export class Sidebar {
menuItems = []; elementRef: ElementRef;
menuHeight = 0; location: Location;
constructor(el: ElementRef, private _sidebarService: SidebarService) { menuItems: Array<any>;
menuHeight: number;
isMenuCollapsed: boolean;
constructor(el: ElementRef, location: Location, private _sidebarService: SidebarService) {
this.elementRef = el;
this.location = location;
this.menuItems = this._sidebarService.getMenuItems(); this.menuItems = this._sidebarService.getMenuItems();
// this.menuHeight = el.nativeElement.childNodes[0].clientHeight - 84;
this.selectMenuItem();
}
// TODO: is it really the best event for this kind of things?
ngAfterViewInit() {
// TODO: get rid of magic 84 constant
this.menuHeight = this.elementRef.nativeElement.childNodes[0].clientHeight - 84;
}
menuExpand () {
this.isMenuCollapsed = false;
}
menuCollapse () {
this.isMenuCollapsed = true;
}
toggleSubMenu ($event, item) {
var submenu = $($event.currentTarget).next();
if (this.isMenuCollapsed) {
this.menuExpand();
if (!item.expanded) {
setTimeout(function () {
item.expanded = !item.expanded;
// TODO: incomplete
// submenu.slideToggle();
}, 0);
}
} else {
item.expanded = !item.expanded;
// TODO: incomplete
// submenu.slideToggle();
}
return false;
}
private selectMenuItem() {
let currentPath = this.location.path();
let isCurrent = (root) => (('#' + currentPath).indexOf(root) == 0);
this.menuItems.forEach(function (menu) {
menu.selected = isCurrent(menu.root);
menu.expanded = menu.expanded || menu.selected;
console.log(menu);
if (menu.subMenu) {
menu.subMenu.forEach(function (subMenu) {
subMenu.selected = isCurrent(subMenu.root) && !subMenu.disabled;
});
}
});
} }
} }

View file

@ -1,11 +1,17 @@
<aside class="al-sidebar"> <aside class="al-sidebar">
<ul class="al-sidebar-list"> <ul class="al-sidebar-list">
<li *ngFor="#item of menuItems" class="al-sidebar-list-item" <li *ngFor="#item of menuItems" class="al-sidebar-list-item"
ngClass="{'selected': item.selected, 'with-sub-menu': item.subMenu}"> [ngClass]="{'selected': item.selected, 'with-sub-menu': item.subMenu}">
<a *ngIf="item.subMenu" href="{{ item.root }}" class="al-sidebar-list-link"> <a *ngIf="!item.subMenu" href="{{ item.root }}" class="al-sidebar-list-link">
<i class="{{ item.icon }}"></i><span>{{ item.title }}</span> <i class="{{ item.icon }}"></i><span>{{ item.title }}</span>
</a> </a>
<a *ngIf="item.subMenu" ng-mouseenter="hoverItem($event, item)" (click)="toggleSubMenu($event, item)" class="al-sidebar-list-link" href>
<i class="{{ item.icon }}"></i><span>{{ item.title }}</span>
<b class="fa" [ngClass]="{'fa-angle-up': item.expanded, 'fa-angle-down': !item.expanded}" *ngIf="item.subMenu"></b>
</a>
</li> </li>
</ul> </ul>
<div class="sidebar-hover-elem"></div> <div class="sidebar-hover-elem"></div>

View file

@ -3,77 +3,100 @@ import {Injectable} from 'angular2/core';
@Injectable() @Injectable()
export class SidebarService { export class SidebarService {
staticMenuItems = [ { staticMenuItems = [
title: 'Pages', {
icon: 'ion-document', title: 'Pages',
subMenu: [{ icon: 'ion-document',
title: 'Sign In', subMenu: [
root: 'auth.html', {
blank: true title: 'Sign In',
}, { root: 'auth.html',
title: 'Sign Up', blank: true
root: 'reg.html', },
blank: true {
}, { title: 'Sign Up',
title: 'User Profile', root: 'reg.html',
root: '#/profile' blank: true
}, { },
title: '404 Page', {
root: '404.html', title: 'User Profile',
blank: true root: '#/profile'
}] },
}, { {
title: 'Menu Level 1', title: '404 Page',
icon: 'ion-ios-more', root: '404.html',
subMenu: [{ blank: true
title: 'Menu Level 1.1', }
root: '#', ]
disabled: true },
}, { {
title: 'Menu Level 1.2', title: 'Menu Level 1',
subMenu: [{ icon: 'ion-ios-more',
title: 'Menu Level 1.2.1', subMenu: [
root: '#', {
disabled: true title: 'Menu Level 1.1',
}] root: '#',
}] disabled: true
}]; },
{
title: 'Menu Level 1.2',
subMenu: [{
title: 'Menu Level 1.2.1',
root: '#',
disabled: true
}]
}
]
}];
getMenuItems() { getMenuItems() {
// var states = defineMenuItemStates(); var states = this.defineMenuItemStates();
// var menuItems = states.filter(function(item) { var menuItems = states.filter(function(item) {
// return item.level == 0; return item.level == 0;
// }); });
//
// menuItems.forEach(function(item) { menuItems.forEach(function(item) {
// var children = states.filter(function(child) { var children = states.filter(function(child) {
// return child.level == 1 && child.name.indexOf(item.name) === 0; return child.level == 1 && child.name.indexOf(item.name) === 0;
// }); });
// item.subMenu = children.length ? children : null; item.subMenu = children.length ? children : null;
// }); });
//
// return menuItems.concat(staticMenuItems); return menuItems.concat(this.staticMenuItems);
return this.staticMenuItems;
}; };
defineMenuItemStates() { defineMenuItemStates() {
// return $state.get()
// .filter(function(s) { // TODO mock state object
// return s.sidebarMeta; var state = [{
// }) name: 'dashboard',
// .map(function(s) { title: 'Dashboard',
// var meta = s.sidebarMeta; selected: true,
// return { url: '/pages/dashboard',
// name: s.name, templateUrl: 'app/pages/dashboard/dashboard.html',
// title: s.title, sidebarMeta: {
// level: (s.name.match(/\./g) || []).length, icon: 'ion-android-home',
// order: meta.order, order: 0,
// icon: meta.icon, }
// root: '#/' + s.name.replace('.', '/'), }];
// };
// }) return state
// .sort(function(a, b) { .filter(function(s) {
// return (a.level - b.level) * 100 + a.order - b.order; return s.sidebarMeta != null;
// }); })
.map(function(s) {
var meta = s.sidebarMeta;
return {
name: s.name,
title: s.title,
level: (s.name.match(/\./g) || []).length,
order: meta.order,
icon: meta.icon,
root: '#/' + s.name.replace('.', '/'),
};
})
.sort(function(a, b) {
return (a.level - b.level) * 100 + a.order - b.order;
});
} }
} }