/*-------------------------------------------------------------------------------------------------------------- * Copyright (c) insite-gmbh. All rights reserved. * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------------------------*/ import { IMenuProvider } from '../interfaces/menuProvider'; import { Observable } from 'rxjs/Observable'; import { IMenuItem } from '../interfaces/menuItem'; import { DefaultMenuItem } from './defaultMenuItem'; import { OpaqueToken, Inject, EventEmitter } from '@angular/core'; import { Router, NavigationEnd } from '@angular/router'; import { EmptyMenuItem } from './emptyMenuItem'; import { MenuItemBase } from './menuItemBase'; import { Subscription } from 'rxjs/Rx'; export const BUTTONMENU_TOKEN: OpaqueToken = new OpaqueToken('buttonMenueValue'); /** * Default implementation for the button menu * @class DefaultMenuProvider * @classdesc Default implementation for the button menu * @author insite-gmbh */ export class DefaultMenuProvider implements IMenuProvider { private _lastUrl:string; private _subscribtion: Subscription; /** * Get informed if the menu selection was changed. This will be called from the select from code methods to * handle it in the menu components. */ public selectionChangedNotifier: EventEmitter = new EventEmitter(); /** * Number of entries per given level (e.g. level = line, level = rootElements) */ public maxEntriesPerLevel: number = 8; /** * constructor. * @param {Array} _menuItems menu configuration. */ constructor( @Inject(BUTTONMENU_TOKEN) private _menuItems: Array, private _router: Router) { this.fillTheGaps(); this._subscribtion = this._router.events .subscribe( (ev) => { if(this._lastUrl != ev.url) console.log(`Route changed to ${ev.url}`, ev); if (ev instanceof NavigationEnd) { this._lastUrl = ev.url; this.selectByUrl(ev.url); }else{ this.selectByUrl(this._lastUrl); } } ); } /** * Subscribe to the menues, to get informed if the menus get changing * @method subscribeToEntriesFor * @param {IMenuItem} parent parent menu (null = main menu) */ public subscribeToEntriesFor(parent: IMenuItem = null): Observable> { if (parent == null) return Observable.from(new Array>(this._menuItems)); return Observable.from(new Array>((this._menuItems[this._menuItems.indexOf(parent)] as MenuItemBase).childs)); } /** * This mehtod will be called if a submenu button was clicked. * @method applySelectAction * @param {IMenuItem} parent parent menu (null = main menu) * @return {Promise} return true if action completed successfully, otherwise false. */ public async applySelectAction(item: IMenuItem): Promise { if (this._router.url != item.action && item.action.length > 0) return await this._router.navigate([item.action]); return false; } /** * Call the method to select a menu from code byit's buttons * @method selectByButton * @param {number} parent main menu button id * @param {number} child sub menu button id */ public selectByButton(parent: number, child: number = -1) { let selected = this._menuItems[parent] as MenuItemBase; if (child >= 0) { let childItem = selected.childs[child] as MenuItemBase; if (childItem != null) this.setSelection(selected.childs, childItem); } if (selected != null) this.selectionChangedNotifier.emit(selected); } /** * Call the method to select a menu from code byit's buttons * @method selectByUrl * @param {number} parent main menu button id * @param {number} child sub menu button id */ public selectByUrl(url: string) { this._menuItems.forEach((entry, index) => { let found = false; let parent = entry as MenuItemBase; parent.childs.forEach((child, cidx) => { if (child.action == url) { this.selectByButton(index, cidx); found = true; return; } }); if (found) return; }); } private setSelection(childs: Array, item: IMenuItem) { childs.forEach(b => { b.isSelected = b == item; }); } private fillTheGaps() { this._menuItems.forEach(entry => { entry.provider = this; let numberOFEntries: number = this.maxEntriesPerLevel; let dmi = entry as MenuItemBase; let length = dmi.childs.length; let max = dmi.childs.find(x => x.id > numberOFEntries); let childs = dmi.childs.reverse(); let current = childs.pop(); dmi.childs = new Array(); if (max != null) numberOFEntries += numberOFEntries; if (current != null) current.provider = this; for (let i = 0; i < numberOFEntries; i++) { if (current != null) { if (current.id != i) { dmi.childs.push(new EmptyMenuItem(i, entry)); } else { dmi.childs.push(current); current = childs.pop(); if (current != null) current.provider = this; } } else dmi.childs.push(new EmptyMenuItem(i, entry)); } }); } }