diff --git a/package.json b/package.json index 0ed0642b..f8c8660c 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "@angular/platform-browser": "2.0.0-rc.4", "@angular/platform-browser-dynamic": "2.0.0-rc.4", "@angular/platform-server": "2.0.0-rc.4", - "@angular/router": "3.0.0-alpha.8", - "@angular/router-deprecated": "2.0.0-rc.2", + "@angular/router": "3.0.0-beta.2", "@angular/forms":"0.2.0", "amcharts3": "github:amcharts/amcharts3", "ammap3": "github:amcharts/ammap3", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0f785054..8a074e89 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,17 +1,10 @@ import './app.loader.ts'; - -import {Component, ViewEncapsulation} from '@angular/core'; -import {RouteConfig} from '@angular/router-deprecated'; - -import {Pages} from './pages'; -import {Login} from './pages/login'; -import {Register} from './pages/register'; -import {AppState} from './app.state'; -import {BaThemeConfigProvider, BaThemeConfig} from './theme'; -import {BaThemeRun} from './theme/directives'; -import {BaImageLoaderService, BaThemePreloader, BaThemeSpinner} from './theme/services'; - -import {layoutPaths} from './theme/theme.constants'; +import {Component, ViewEncapsulation} from "@angular/core"; +import {AppState} from "./app.state"; +import {BaThemeConfigProvider, BaThemeConfig} from "./theme"; +import {BaThemeRun} from "./theme/directives"; +import {BaImageLoaderService, BaThemePreloader, BaThemeSpinner} from "./theme/services"; +import {layoutPaths} from "./theme/theme.constants"; /* * App Component @@ -31,31 +24,6 @@ import {layoutPaths} from './theme/theme.constants'; ` }) -@RouteConfig([ - { - path: '/pages/...', - name: 'Pages', - component: Pages, - useAsDefault: true - }, - { - path: '/login', - name: 'Login', - component: Login - }, - { - path: '/register', - name: 'Register', - component: Register - }, - // handle any non-registered route - // and simply redirects back to dashboard page - // you can specify any customer 404 page while it's not built in ito ng2-admin - { - path: '/**', - redirectTo: ['Pages'] - } -]) export class App { isMenuCollapsed:boolean = false; diff --git a/src/app/app.menu.ts b/src/app/app.menu.ts deleted file mode 100644 index 97d4a385..00000000 --- a/src/app/app.menu.ts +++ /dev/null @@ -1,173 +0,0 @@ -export const menuItems = [ - { - title: 'Dashboard', - component: 'Dashboard', - icon: 'ion-android-home', - selected: false, - expanded: false, - order: 0 - }, - { - title: 'Editors', - component: 'Editors', - icon: 'ion-edit', - order: 100, - subMenu: [ - { - title: 'CKEditor', - component: 'Ckeditor' - } - ] - }, - { - title: 'Charts', - component: 'Charts', - icon: 'ion-stats-bars', - selected: false, - expanded: false, - order: 200, - subMenu: [ - { - title: 'Chartist.Js', - component: 'ChartistJs', - }, - ] - }, - { - title: 'UI Features', - component: 'Ui', - icon: 'ion-android-laptop', - selected: false, - expanded: false, - order: 300, - subMenu: [ - { - title: 'Typography', - component: 'Typography', - }, - { - title: 'Buttons', - component: 'Buttons', - }, - { - title: 'Icons', - component: 'Icons', - }, - { - title: 'Grid', - component: 'Grid', - }, - ] - }, - { - title: 'Form Elements', - component: 'Forms', - icon: 'ion-compose', - selected: false, - expanded: false, - order: 400, - subMenu: [ - { - title: 'Form Inputs', - component: 'Inputs', - }, - { - title: 'Form Layouts', - component: 'Layouts', - }, - ] - }, - { - title: 'Tables', - component: 'Tables', - icon: 'ion-grid', - selected: false, - expanded: false, - order: 500, - subMenu: [ - { - title: 'Basic Tables', - component: 'BasicTables', - } - ] - }, - { - title: 'Maps', - component: 'Maps', - icon: 'ion-ios-location-outline', - selected: false, - expanded: false, - order: 600, - subMenu: [ - { - title: 'Google Maps', - component: 'GoogleMaps', - }, - { - title: 'Leaflet Maps', - component: 'LeafletMaps', - }, - { - title: 'Bubble Maps', - component: 'BubbleMaps', - }, - { - title: 'Line Maps', - component: 'LineMaps', - } - ] - }, - { - title: 'Pages', - icon: 'ion-document', - selected: false, - expanded: false, - order: 650, - subMenu: [ - { - title: 'Login', - url: '#/login', - }, - { - title: 'Register', - url: '#/register', - } - ] - }, - { - title: 'Menu Level 1', - icon: 'ion-ios-more', - selected: false, - expanded: false, - order: 700, - subMenu: [ - { - title: 'Menu Level 1.1', - url: '#', - disabled: true, - selected: false, - expanded: false - }, - { - title: 'Menu Level 1.2', - url: '#', - subMenu: [{ - title: 'Menu Level 1.2.1', - url: '#', - disabled: true, - selected: false, - expanded: false - }] - } - ] - }, - { - title: 'External Link', - url: 'http://akveo.com', - icon: 'ion-android-exit', - selected: false, - expanded: false, - order: 800, - target: '_blank' - } -]; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts new file mode 100644 index 00000000..af54c8e4 --- /dev/null +++ b/src/app/app.routes.ts @@ -0,0 +1,18 @@ +import {provideRouter, RouterConfig} from '@angular/router'; +import {LoginRoutes} from "./pages/login/login.routes"; +import {PagesRoutes} from "./pages/pages.routes"; +import {RegisterRoutes} from "./pages/register/register.routes"; + +export const routes:RouterConfig = [ + ...LoginRoutes, + ...RegisterRoutes, + ...PagesRoutes, + { + path: '**', + redirectTo: '/pages/dashboard' + }, +]; + +export const APP_ROUTER_PROVIDERS = [ + provideRouter(routes) +]; diff --git a/src/app/pages/charts/charts.component.ts b/src/app/pages/charts/charts.component.ts index 62cf1879..366a277c 100644 --- a/src/app/pages/charts/charts.component.ts +++ b/src/app/pages/charts/charts.component.ts @@ -1,8 +1,6 @@ -import {Component} from '@angular/core'; -import {RouteConfig} from '@angular/router-deprecated'; +import {Component} from "@angular/core"; // import {ChartJs} from "./components/chartJs"; -import {ChartistJs} from "./components/chartistJs/chartistJs.component"; @Component({ selector: 'maps', @@ -11,19 +9,6 @@ import {ChartistJs} from "./components/chartistJs/chartistJs.component"; styles: [], template: `` }) -@RouteConfig([ - { - name: 'ChartistJs', - component: ChartistJs, - path: '/chartist-js', - useAsDefault: true, - }, - // { - // name: 'ChartJs', - // component: ChartJs, - // path: '/chart-js', - // }, -]) export class Charts { constructor() { diff --git a/src/app/pages/editors/editors.component.ts b/src/app/pages/editors/editors.component.ts index ae570ac4..53eeb282 100644 --- a/src/app/pages/editors/editors.component.ts +++ b/src/app/pages/editors/editors.component.ts @@ -1,21 +1,9 @@ import {Component} from '@angular/core'; -import {RouteConfig} from '@angular/router-deprecated'; - -import {Ckeditor} from "./components/ckeditor"; @Component({ selector: 'editors', template: `` }) - -@RouteConfig([ - { - name: 'Ckeditor', - component: Ckeditor, - path: '/ckeditor', - useAsDefault: true - } -]) export class Editors { constructor() { } diff --git a/src/app/pages/forms/forms.component.ts b/src/app/pages/forms/forms.component.ts index 05bde0bf..763390c1 100644 --- a/src/app/pages/forms/forms.component.ts +++ b/src/app/pages/forms/forms.component.ts @@ -1,8 +1,4 @@ import {Component} from '@angular/core'; -import {RouteConfig} from '@angular/router-deprecated'; - -import {Inputs} from './components/inputs'; -import {Layouts} from './components/layouts'; @Component({ selector: 'forms', @@ -11,19 +7,6 @@ import {Layouts} from './components/layouts'; styles: [], template: `` }) -@RouteConfig([ - { - name: 'Inputs', - component: Inputs, - path: '/inputs', - useAsDefault: true - }, - { - name: 'Layouts', - component: Layouts, - path: '/layouts', - } -]) export class Forms { constructor() { diff --git a/src/app/pages/login/login.html b/src/app/pages/login/login.html index ad0ee101..9ca1ef9f 100644 --- a/src/app/pages/login/login.html +++ b/src/app/pages/login/login.html @@ -1,7 +1,7 @@

Sign in to ng2-admin

- New to ng2-admin? Sign up! + New to ng2-admin? Sign up!
diff --git a/src/app/pages/login/login.routes.ts b/src/app/pages/login/login.routes.ts new file mode 100644 index 00000000..2bf1df36 --- /dev/null +++ b/src/app/pages/login/login.routes.ts @@ -0,0 +1,10 @@ +import {RouterConfig} from '@angular/router'; +import {Login} from './login.component'; + +//noinspection TypeScriptValidateTypes +export const LoginRoutes: RouterConfig = [ + { + path: 'login', + component: Login + } +]; diff --git a/src/app/pages/maps/maps.component.ts b/src/app/pages/maps/maps.component.ts index cc890fd8..072cb4e7 100644 --- a/src/app/pages/maps/maps.component.ts +++ b/src/app/pages/maps/maps.component.ts @@ -1,10 +1,4 @@ -import {Component, ViewEncapsulation} from '@angular/core'; -import {RouteConfig} from '@angular/router-deprecated'; - -import {GoogleMaps} from './components/googleMaps'; -import {LeafletMaps} from "./components/leafletMaps"; -import {BubbleMaps} from "./components/bubbleMaps"; -import {LineMaps} from "./components/lineMaps"; +import {Component} from '@angular/core'; @Component({ selector: 'maps', @@ -13,29 +7,6 @@ import {LineMaps} from "./components/lineMaps"; styles: [], template: `` }) -@RouteConfig([ - { - name: 'GoogleMaps', - component: GoogleMaps, - path: '/google-maps', - useAsDefault: true - }, - { - name: 'LeafletMaps', - component: LeafletMaps, - path: '/leaflet-maps', - }, - { - name: 'BubbleMaps', - component: BubbleMaps, - path: '/bubble-maps', - }, - { - name: 'LineMaps', - component: LineMaps, - path: '/line-maps', - }, -]) export class Maps { constructor() { diff --git a/src/app/pages/pages.component.ts b/src/app/pages/pages.component.ts index 33f9c4a1..3f2a77c4 100644 --- a/src/app/pages/pages.component.ts +++ b/src/app/pages/pages.component.ts @@ -1,16 +1,6 @@ import {Component, ViewEncapsulation} from '@angular/core'; -import {RouteConfig} from '@angular/router-deprecated'; - import {BaPageTop, BaContentTop, BaSidebar, BaBackTop} from '../theme/components'; -import {Dashboard} from './dashboard'; -import {Ui} from './ui'; -import {Maps} from './maps'; -import {Charts} from './charts'; -import {Forms} from './forms'; -import {Tables} from './tables'; -import {Editors} from "./editors"; - @Component({ selector: 'pages', encapsulation: ViewEncapsulation.None, @@ -40,44 +30,6 @@ import {Editors} from "./editors"; ` }) -@RouteConfig([ - { - name: 'Editors', - component: Editors, - path: '/editors/...', - }, - { - name: 'Dashboard', - component: Dashboard, - path: '/dashboard', - useAsDefault: true, - }, - { - name: 'Ui', - component: Ui, - path: '/ui/...', - }, - { - name: 'Maps', - component: Maps, - path: '/maps/...', - }, - { - name: 'Charts', - component: Charts, - path: '/charts/...', - }, - { - name: 'Forms', - component: Forms, - path: '/forms/...', - }, - { - name: 'Tables', - component: Tables, - path: '/tables/...', - } -]) export class Pages { constructor() { diff --git a/src/app/pages/pages.routes.ts b/src/app/pages/pages.routes.ts new file mode 100644 index 00000000..3cc32d61 --- /dev/null +++ b/src/app/pages/pages.routes.ts @@ -0,0 +1,307 @@ +import {RouterConfig} from '@angular/router'; +import {Dashboard} from './dashboard/dashboard.component'; +import {Charts} from './charts/charts.component'; +import {ChartistJs} from './charts/components/chartistJs/chartistJs.component'; +import {Pages} from './pages.component'; +import {Ui} from './ui/ui.component'; +import {Typography} from './ui/components/typography/typography.component'; +import {Buttons} from './ui/components/buttons/buttons.component'; +import {Icons} from './ui/components/incons/icons.component'; +import {Grid} from './ui/components/grid/grid.component'; +import {Forms} from './forms/forms.component'; +import {Inputs} from './forms/components/inputs/inputs.component'; +import {Layouts} from './forms/components/layouts/layouts.component'; +import {BasicTables} from './tables/components/basicTables/basicTables.component'; +import {Tables} from './tables/tables.component'; +import {Maps} from './maps/maps.component'; +import {GoogleMaps} from './maps/components/googleMaps/googleMaps.component'; +import {LeafletMaps} from './maps/components/leafletMaps/leafletMaps.component'; +import {BubbleMaps} from './maps/components/bubbleMaps/bubbleMaps.component'; +import {LineMaps} from './maps/components/lineMaps/lineMaps.component'; +import {Editors} from './editors/editors.component'; +import {Ckeditor} from './editors/components/ckeditor/ckeditor.component'; + +//noinspection TypeScriptValidateTypes +export const PagesRoutes:RouterConfig = [ + { + path: 'pages', + component: Pages, + children: [ + { + path: 'dashboard', + component: Dashboard, + data: { + menu: { + title: 'Dashboard', + icon: 'ion-android-home', + selected: false, + expanded: false, + order: 0 + } + } + }, + { + path: 'editors', + component: Editors, + data: { + menu: { + title: 'Editors', + icon: 'ion-edit', + selected: false, + expanded: false, + order: 100, + } + }, + children: [ + { + path: 'ckeditor', + component: Ckeditor, + data: { + menu: { + title: 'CKEditor', + } + } + } + ] + }, + { + path: 'charts', + component: Charts, + data: { + menu: { + title: 'Charts', + icon: 'ion-stats-bars', + selected: false, + expanded: false, + order: 200, + } + }, + children: [ + { + path: 'chartist-js', + component: ChartistJs, + data: { + menu: { + title: 'Chartist.Js', + } + } + } + ] + }, + { + path: 'ui', + component: Ui, + data: { + menu: { + title: 'UI Features', + icon: 'ion-android-laptop', + selected: false, + expanded: false, + order: 300, + } + }, + children: [ + { + path: 'typography', + component: Typography, + data: { + menu: { + title: 'Typography', + } + } + }, + { + path: 'buttons', + component: Buttons, + data: { + menu: { + title: 'Buttons', + } + } + }, + { + path: 'icons', + component: Icons, + data: { + menu: { + title: 'Icons', + } + } + }, + { + path: 'grid', + component: Grid, + data: { + menu: { + title: 'Grid', + } + } + }, + ] + }, + { + path: 'forms', + component: Forms, + data: { + menu: { + title: 'Form Elements', + icon: 'ion-compose', + selected: false, + expanded: false, + order: 400, + } + }, + children: [ + { + path: 'inputs', + component: Inputs, + data: { + menu: { + title: 'Form Inputs', + } + } + }, + { + path: 'layouts', + component: Layouts, + data: { + menu: { + title: 'Form Layouts', + } + } + } + ] + }, + { + path: 'tables', + component: Tables, + data: { + menu: { + title: 'Tables', + icon: 'ion-grid', + selected: false, + expanded: false, + order: 500, + } + }, + children: [ + { + path: 'basictables', + component: BasicTables, + data: { + menu: { + title: 'Basic Tables', + } + } + } + ] + }, + { + path: 'maps', + component: Maps, + data: { + menu: { + title: 'Maps', + icon: 'ion-ios-location-outline', + selected: false, + expanded: false, + order: 600, + } + }, + children: [ + { + path: 'googlemaps', + component: GoogleMaps, + data: { + menu: { + title: 'Google Maps', + } + } + }, + { + path: 'leafletmaps', + component: LeafletMaps, + data: { + menu: { + title: 'Leaflet Maps', + } + } + }, + { + path: 'bubblemaps', + component: BubbleMaps, + data: { + menu: { + title: 'Bubble Maps', + } + } + }, + { + path: 'linemaps', + component: LineMaps, + data: { + menu: { + title: 'Line Maps', + } + } + } + ] + }, + { + path: '', + data: { + menu: { + title: 'Menu Level 1', + icon: 'ion-ios-more', + selected: false, + expanded: false, + order: 700, + } + }, + children: [ + { + path: '', + data: { + menu: { + title: 'Menu Level 1.1', + url: '#' + } + } + }, + { + path: '', + data: { + menu: { + title: 'Menu Level 1.2', + url: '#' + } + }, + children: [ + { + path: '', + data: { + menu: { + title: 'Menu Level 1.2.1', + url: '#' + } + } + } + ] + } + ] + }, + { + path: '', + data: { + menu: { + title: 'External Link', + url: 'http://akveo.com', + icon: 'ion-android-exit', + order: 800, + target: '_blank' + } + } + } + ] + } +]; diff --git a/src/app/pages/register/register.html b/src/app/pages/register/register.html index 07eb03e6..a82baf6d 100644 --- a/src/app/pages/register/register.html +++ b/src/app/pages/register/register.html @@ -1,7 +1,7 @@

Sign up to ng2-admin

- Already have an ng2-admin account? Sign in! + Already have an ng2-admin account? Sign in!
diff --git a/src/app/pages/register/register.routes.ts b/src/app/pages/register/register.routes.ts new file mode 100644 index 00000000..a6d577a8 --- /dev/null +++ b/src/app/pages/register/register.routes.ts @@ -0,0 +1,10 @@ +import {RouterConfig} from '@angular/router'; +import {Register} from './register.component'; + +//noinspection TypeScriptValidateTypes +export const RegisterRoutes: RouterConfig = [ + { + path: 'register', + component: Register + } +]; diff --git a/src/app/pages/tables/tables.component.ts b/src/app/pages/tables/tables.component.ts index 13e1f44e..1091f8e6 100644 --- a/src/app/pages/tables/tables.component.ts +++ b/src/app/pages/tables/tables.component.ts @@ -1,7 +1,4 @@ import {Component} from '@angular/core'; -import {RouteConfig} from '@angular/router-deprecated'; - -import {BasicTables} from './components/basicTables'; @Component({ selector: 'forms', @@ -10,14 +7,6 @@ import {BasicTables} from './components/basicTables'; styles: [], template: `` }) -@RouteConfig([ - { - name: 'BasicTables', - component: BasicTables, - path: '/basic', - useAsDefault: true - } -]) export class Tables { constructor() { diff --git a/src/app/pages/ui/ui.component.ts b/src/app/pages/ui/ui.component.ts index a59df0ae..bd1461b9 100644 --- a/src/app/pages/ui/ui.component.ts +++ b/src/app/pages/ui/ui.component.ts @@ -1,10 +1,4 @@ import {Component} from '@angular/core'; -import {RouteConfig} from '@angular/router-deprecated'; - -import {Typography} from './components/typography'; -import {Buttons} from './components/buttons'; -import {Icons} from './components/incons'; -import {Grid} from './components/grid'; @Component({ selector: 'ui', @@ -13,29 +7,6 @@ import {Grid} from './components/grid'; styles: [], template: `` }) -@RouteConfig([ - { - name: 'Typography', - component: Typography, - path: '/typography', - useAsDefault: true - }, - { - name: 'Buttons', - component: Buttons, - path: '/buttons', - }, - { - name: 'Icons', - component: Icons, - path: '/icons', - }, - { - name: 'Grid', - component: Grid, - path: '/grid', - } -]) export class Ui { constructor() { diff --git a/src/app/theme/components/baMenu/baMenu.component.ts b/src/app/theme/components/baMenu/baMenu.component.ts new file mode 100644 index 00000000..c20f2756 --- /dev/null +++ b/src/app/theme/components/baMenu/baMenu.component.ts @@ -0,0 +1,71 @@ +import {Component, ViewEncapsulation, Input, Output, EventEmitter} from '@angular/core'; +import {Router, RouterConfig, NavigationEnd} from '@angular/router'; +import {Subscription} from 'rxjs/Rx'; + +import {BaSlimScroll} from '../../../theme/directives'; +import {BaMenuService} from './baMenu.service'; +import {BaMenuItem} from './components/baMenuItem'; + +@Component({ + selector: 'ba-menu', + encapsulation: ViewEncapsulation.None, + styles: [require('./baMenu.scss')], + template: require('./baMenu.html'), + providers: [BaMenuService], + directives: [BaMenuItem, BaSlimScroll] +}) +export class BaMenu { + + @Input() menuRoutes:RouterConfig = []; + @Input() sidebarCollapsed:boolean = false; + @Input() menuHeight:number; + + @Output() expandMenu = new EventEmitter(); + + public menuItems:any[]; + public showHoverElem:boolean; + public hoverElemHeight:number; + public hoverElemTop:number; + protected _onRouteChange:Subscription; + public outOfArea:number = -200; + + constructor(private _router:Router, private _service:BaMenuService) { + + this._onRouteChange = this._router.events.subscribe((event) => { + if (this.menuItems && event instanceof NavigationEnd) { + this.menuItems = this._service.selectMenuItem(this.menuItems); + } + }); + } + + public ngOnInit():void { + this.menuItems = this._service.convertRoutesToMenus(this.menuRoutes); + } + + public ngOnDestroy():void { + this._onRouteChange.unsubscribe(); + } + + public hoverItem($event):void { + this.showHoverElem = true; + this.hoverElemHeight = $event.currentTarget.clientHeight; + // TODO: get rid of magic 66 constant + this.hoverElemTop = $event.currentTarget.getBoundingClientRect().top - 66; + } + + public toggleSubMenu($event):boolean { + var submenu = jQuery($event.currentTarget).next(); + + if (this.sidebarCollapsed) { + this.expandMenu.emit(null); + if (!$event.item.expanded) { + $event.item.expanded = true; + } + } else { + $event.item.expanded = !$event.item.expanded; + submenu.slideToggle(); + } + + return false; + } +} diff --git a/src/app/theme/components/baMenu/baMenu.html b/src/app/theme/components/baMenu/baMenu.html new file mode 100644 index 00000000..ebe22ab7 --- /dev/null +++ b/src/app/theme/components/baMenu/baMenu.html @@ -0,0 +1,11 @@ + diff --git a/src/app/theme/components/baMenu/baMenu.scss b/src/app/theme/components/baMenu/baMenu.scss new file mode 100644 index 00000000..c909ac72 --- /dev/null +++ b/src/app/theme/components/baMenu/baMenu.scss @@ -0,0 +1 @@ +@import '../../sass/conf/conf'; diff --git a/src/app/theme/components/baMenu/baMenu.service.ts b/src/app/theme/components/baMenu/baMenu.service.ts new file mode 100644 index 00000000..71ca44bb --- /dev/null +++ b/src/app/theme/components/baMenu/baMenu.service.ts @@ -0,0 +1,103 @@ +import {Injectable} from '@angular/core'; +import {Router, UrlTree, RouterConfig} from '@angular/router'; + +@Injectable() +export class BaMenuService { + + constructor(private _router:Router) { + } + + public convertRoutesToMenus(routes:RouterConfig):any[] { + let items = this._convertArrayToItems(routes); + return this._skipEmpty(items); + } + + public selectMenuItem(menuItems:any[]):any[] { + let items = []; + menuItems.forEach((item) => { + this._selectItem(item); + + if (item.children && item.children.length > 0) { + item.children = this.selectMenuItem(item.children); + } + items.push(item); + }); + return items; + } + + protected _skipEmpty(items:any[]):any[] { + let menu = []; + items.forEach((item) => { + let menuItem; + if (item.skip) { + if (item.children && item.children.length > 0) { + menuItem = item.children; + } + } else { + menuItem = item; + } + + if (menuItem) { + menu.push(menuItem); + } + }); + + return [].concat.apply([], menu); + } + + protected _convertArrayToItems(routes:any[], parent?:any):any[] { + let items = []; + routes.forEach((route) => { + items.push(this._convertObjectToItem(route, parent)); + }); + return items; + } + + protected _convertObjectToItem(object, parent?:any):any { + let item:any = {}; + if (object.data && object.data.menu) { + // this is a menu object + item = object.data.menu; + item.route = object; + delete item.route.data.menu; + } else { + item.route = object; + item.skip = true; + } + + // we have to collect all paths to correctly build the url then + item.route.paths = parent && parent.route && parent.route.paths ? parent.route.paths.slice(0) : []; + item.route.paths.push(item.route.path); + + if (object.children && object.children.length > 0) { + item.children = this._convertArrayToItems(object.children, item); + } + + let prepared = this._prepareItem(item); + + // if current item is selected or expanded - then parent is expanded too + if ((prepared.selected || prepared.expanded) && parent) { + parent.expanded = true; + } + + return prepared; + } + + protected _prepareItem(object:any):any { + if (!object.skip) { + + let itemUrl = this._router.serializeUrl(this._router.createUrlTree(object.route.paths)); + object.url = object.url ? object.url : '/#' + itemUrl; + + object.target = object.target || ''; + return this._selectItem(object); + } + + return object; + } + + protected _selectItem(object:any):any { + object.selected = object.url == ('/#' + this._router.url); + return object; + } +} diff --git a/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.component.ts b/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.component.ts new file mode 100644 index 00000000..46fc3a7f --- /dev/null +++ b/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.component.ts @@ -0,0 +1,28 @@ +import {Component, ViewEncapsulation, Input, Output, EventEmitter} from '@angular/core'; + +@Component({ + selector: 'ba-menu-item', + encapsulation: ViewEncapsulation.None, + styles: [require('./baMenuItem.scss')], + template: require('./baMenuItem.html'), + providers: [], + directives: [BaMenuItem] +}) +export class BaMenuItem { + + @Input() menuItem:any; + @Input() child:boolean = false; + + @Output() itemHover = new EventEmitter(); + @Output() toggleSubMenu = new EventEmitter(); + + public onHoverItem($event):void { + this.itemHover.emit($event); + } + + public onToggleSubMenu($event, item):boolean { + $event.item = item; + this.toggleSubMenu.emit($event); + return false; + } +} diff --git a/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.html b/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.html new file mode 100644 index 00000000..7f009ab3 --- /dev/null +++ b/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.html @@ -0,0 +1,21 @@ +
  • + + + + {{ menuItem.title }} + + + + {{ menuItem.title }} + + + +
      + +
    + +
  • diff --git a/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.scss b/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.scss new file mode 100644 index 00000000..00bb0106 --- /dev/null +++ b/src/app/theme/components/baMenu/components/baMenuItem/baMenuItem.scss @@ -0,0 +1 @@ +@import '../../../../sass/conf/conf'; diff --git a/src/app/theme/components/baMenu/components/baMenuItem/index.ts b/src/app/theme/components/baMenu/components/baMenuItem/index.ts new file mode 100644 index 00000000..5ee5509a --- /dev/null +++ b/src/app/theme/components/baMenu/components/baMenuItem/index.ts @@ -0,0 +1 @@ +export * from './baMenuItem.component'; diff --git a/src/app/theme/components/baMenu/index.ts b/src/app/theme/components/baMenu/index.ts new file mode 100644 index 00000000..99f5ff1f --- /dev/null +++ b/src/app/theme/components/baMenu/index.ts @@ -0,0 +1 @@ +export * from './baMenu.component.ts'; diff --git a/src/app/theme/components/baSidebar/baSidebar.component.ts b/src/app/theme/components/baSidebar/baSidebar.component.ts index 929b4662..c8825733 100644 --- a/src/app/theme/components/baSidebar/baSidebar.component.ts +++ b/src/app/theme/components/baSidebar/baSidebar.component.ts @@ -1,59 +1,42 @@ import {Component, ElementRef, HostListener, ViewEncapsulation} from '@angular/core'; -import {Router} from '@angular/router-deprecated'; - import {AppState} from '../../../app.state'; import {layoutSizes} from '../../../theme'; -import {BaSlimScroll} from '../../../theme/directives'; -import {BaSidebarService} from './baSidebar.service'; +import {BaMenu} from '../baMenu'; +import {routes} from '../../../../app/app.routes'; @Component({ selector: 'ba-sidebar', encapsulation: ViewEncapsulation.None, styles: [require('./baSidebar.scss')], template: require('./baSidebar.html'), - providers: [BaSidebarService], - directives: [BaSlimScroll] + providers: [], + directives: [BaMenu] }) export class BaSidebar { - public menuItems:Array; + // here we declare which routes we want to use as a menu in our sidebar + public routes = routes; + public menuHeight:number; public isMenuCollapsed:boolean = false; - - public showHoverElem:boolean; - public hoverElemHeight:number; - public hoverElemTop:number; - - public outOfArea:number = -200; - public isMenuShouldCollapsed:boolean = false; - protected _onRouteChange; - constructor(private _elementRef:ElementRef, - private _router:Router, - private _sidebarService:BaSidebarService, - private _state:AppState) { - this.menuItems = this._sidebarService.getMenuItems(); - this._onRouteChange = this._router.root.subscribe((path) => this._selectMenuItem()); + constructor(private _elementRef:ElementRef, private _state:AppState) { + this._state.subscribe('menu.isCollapsed', (isCollapsed) => { this.isMenuCollapsed = isCollapsed; }); } - public ngOnInit():void { if (this._shouldMenuCollapse()) { this.menuCollapse(); } } - public ngOnDestroy():void { - this._onRouteChange.unsubscribe(); - } - public ngAfterViewInit():void { - this.updateSidebarHeight(); + setTimeout(() => this.updateSidebarHeight()); } @HostListener('window:resize') @@ -81,45 +64,12 @@ export class BaSidebar { this._state.notifyDataChanged('menu.isCollapsed', this.isMenuCollapsed); } - public hoverItem($event):void { - this.showHoverElem = true; - this.hoverElemHeight = $event.currentTarget.clientHeight; - // TODO: get rid of magic 66 constant - this.hoverElemTop = $event.currentTarget.getBoundingClientRect().top - 66; - } - public updateSidebarHeight():void { // TODO: get rid of magic 84 constant this.menuHeight = this._elementRef.nativeElement.childNodes[0].clientHeight - 84; } - public toggleSubMenu($event, item):boolean { - var submenu = jQuery($event.currentTarget).next(); - - if (this.isMenuCollapsed) { - this.menuExpand(); - if (!item.expanded) { - item.expanded = true; - } - } else { - item.expanded = !item.expanded; - submenu.slideToggle(); - } - - return false; - } - private _shouldMenuCollapse():boolean { return window.innerWidth <= layoutSizes.resWidthCollapseSidebar; } - - private _selectMenuItem():void { - - let currentMenu = this._sidebarService.setRouter(this._router).selectMenuItem(this.menuItems); - this._state.notifyDataChanged('menu.activeLink', currentMenu); - // hide menu after natigation on mobile devises - if (this._shouldMenuCollapse()) { - this.menuCollapse(); - } - } } diff --git a/src/app/theme/components/baSidebar/baSidebar.html b/src/app/theme/components/baSidebar/baSidebar.html index cdb4d344..62e9eab9 100644 --- a/src/app/theme/components/baSidebar/baSidebar.html +++ b/src/app/theme/components/baSidebar/baSidebar.html @@ -1,55 +1,6 @@ diff --git a/src/app/theme/components/baSidebar/baSidebar.scss b/src/app/theme/components/baSidebar/baSidebar.scss index b5de70a3..1f843eee 100644 --- a/src/app/theme/components/baSidebar/baSidebar.scss +++ b/src/app/theme/components/baSidebar/baSidebar.scss @@ -135,7 +135,7 @@ a.al-sidebar-list-link { &.expanded { display: block; } - > li { + > ba-menu-item > li { display: block; float: none; padding: 0; diff --git a/src/app/theme/components/baSidebar/baSidebar.service.ts b/src/app/theme/components/baSidebar/baSidebar.service.ts deleted file mode 100644 index 7653aae1..00000000 --- a/src/app/theme/components/baSidebar/baSidebar.service.ts +++ /dev/null @@ -1,53 +0,0 @@ -import {Injectable} from '@angular/core'; -import {menuItems} from '../../../app.menu'; - -@Injectable() -export class BaSidebarService { - - private _router; - - public getMenuItems():Array { - return menuItems; - } - - public setRouter(router): BaSidebarService { - this._router = router; - return this; - } - - public selectMenuItem(items:Array) { - let currentMenu; - - let assignCurrent = (menu) => (menu.selected ? currentMenu = menu : null); - - items.forEach((menu: any) => { - - this._selectItem([menu.component], menu); - assignCurrent(menu); - - if (menu.subMenu) { - menu.subMenu.forEach((subMenu) => { - this._selectItem([menu.component, subMenu.component], subMenu, menu); - assignCurrent(subMenu); - }); - } - }); - return currentMenu; - } - - private _selectItem(instructions, item, parentMenu = null) { - let route = this._generateRoute(instructions); - item.selected = !item.disabled && this._isCurrent(route); - if (parentMenu) { - parentMenu.expanded = parentMenu.expanded || item.selected; - } - } - - private _isCurrent(route) { - return route ? this._router.isRouteActive(route) : false; - } - - private _generateRoute(instructions) { - return instructions.filter(i => typeof i !== 'undefined').length > 0 ? this._router.generate(instructions) : null; - } -} diff --git a/src/app/theme/components/index.ts b/src/app/theme/components/index.ts index 98c1deea..a96111fc 100644 --- a/src/app/theme/components/index.ts +++ b/src/app/theme/components/index.ts @@ -1,6 +1,7 @@ export * from './baPageTop'; export * from './baMsgCenter'; export * from './baSidebar'; +export * from './baMenu'; export * from './baContentTop'; export * from './baCard'; export * from './baAmChart'; diff --git a/src/platform/browser/directives.ts b/src/platform/browser/directives.ts index c5cd6c38..0b63ed5f 100644 --- a/src/platform/browser/directives.ts +++ b/src/platform/browser/directives.ts @@ -5,7 +5,7 @@ import {PLATFORM_DIRECTIVES} from '@angular/core'; // Angular 2 Router -import {ROUTER_DIRECTIVES} from '@angular/router-deprecated'; +import {ROUTER_DIRECTIVES} from '@angular/router'; // Angular 2 forms import { REACTIVE_FORM_DIRECTIVES } from '@angular/forms'; diff --git a/src/platform/browser/providers.ts b/src/platform/browser/providers.ts index fb4c6f41..bee58303 100644 --- a/src/platform/browser/providers.ts +++ b/src/platform/browser/providers.ts @@ -7,8 +7,8 @@ import {FORM_PROVIDERS, LocationStrategy, HashLocationStrategy} from '@angular/c // Angular 2 Http import {HTTP_PROVIDERS} from '@angular/http'; -// Angular 2 Router -import {ROUTER_PROVIDERS} from '@angular/router-deprecated'; +import {APP_ROUTER_PROVIDERS} from '../../app/app.routes'; + // Angular 2 forms import {disableDeprecatedForms, provideForms} from '@angular/forms'; @@ -22,8 +22,9 @@ export const APPLICATION_PROVIDERS = [ disableDeprecatedForms(), provideForms(), ...HTTP_PROVIDERS, - ...ROUTER_PROVIDERS, + ...APP_ROUTER_PROVIDERS, {provide: LocationStrategy, useClass: HashLocationStrategy} + {provide: LocationStrategy, useClass: HashLocationStrategy } ]; export const PROVIDERS = [ diff --git a/src/vendor.ts b/src/vendor.ts index a5c5b6cd..3ace4485 100644 --- a/src/vendor.ts +++ b/src/vendor.ts @@ -9,7 +9,7 @@ import '@angular/platform-browser-dynamic'; import '@angular/core'; import '@angular/common'; import '@angular/http'; -import '@angular/router-deprecated'; +import '@angular/router'; // RxJS import 'rxjs/add/operator/map';