Automatically expand/collapse sidebar on mouse over/leave.
[src/xds/xds-agent.git] / webapp / src / app / @theme / layouts / xds / xds.layout.ts
1 import { Component, OnDestroy, EventEmitter } from '@angular/core';
2 import {
3   NbMediaBreakpoint,
4   NbMediaBreakpointsService,
5   NbMenuItem,
6   NbMenuService,
7   NbSidebarService,
8   NbThemeService,
9 } from '@nebular/theme';
10
11 import { StateService } from '../../../@core/data/state.service';
12
13 import { Subscription } from 'rxjs/Subscription';
14 import { Observable } from 'rxjs/Observable';
15 import 'rxjs/add/operator/withLatestFrom';
16 import 'rxjs/add/operator/delay';
17 import 'rxjs/add/observable/of';
18 import 'rxjs/add/operator/takeUntil';
19
20 // TODO: move layouts into the framework
21 @Component({
22   selector: 'ngx-xds-layout',
23   styleUrls: ['./xds.layout.scss'],
24   templateUrl: './xds.layout.html',
25 })
26
27 export class XdsLayoutComponent implements OnDestroy {
28
29   subMenu: NbMenuItem[] = [];
30   layout: any = {};
31   sidebar: any = {};
32   sidebarCompact = true;
33
34   protected layoutState$: Subscription;
35   protected sidebarState$: Subscription;
36   protected menuClick$: Subscription;
37
38   private _mouseEnterStream: EventEmitter<any> = new EventEmitter();
39   private _mouseLeaveStream: EventEmitter<any> = new EventEmitter();
40
41   constructor(protected stateService: StateService,
42     protected menuService: NbMenuService,
43     protected themeService: NbThemeService,
44     protected bpService: NbMediaBreakpointsService,
45     protected sidebarService: NbSidebarService) {
46     this.layoutState$ = this.stateService.onLayoutState()
47       .subscribe((layout: string) => this.layout = layout);
48
49     this.sidebarState$ = this.stateService.onSidebarState()
50       .subscribe((sidebar: string) => {
51         this.sidebar = sidebar;
52       });
53
54     const isBp = this.bpService.getByName('is');
55     this.menuClick$ = this.menuService.onItemSelect()
56       .withLatestFrom(this.themeService.onMediaQueryChange())
57       .delay(20)
58       .subscribe(([item, [bpFrom, bpTo]]: [any, [NbMediaBreakpoint, NbMediaBreakpoint]]) => {
59
60         this.sidebarCompact = false;
61         if (bpTo.width <= isBp.width) {
62           this.sidebarService.collapse('menu-sidebar');
63         }
64       });
65
66     // Set sidebarCompact according to sidebar state changes
67     this.sidebarService.onToggle().subscribe(s => s.tag === 'menu-sidebar' && (this.sidebarCompact = !this.sidebarCompact));
68     this.sidebarService.onCollapse().subscribe(s => s.tag === 'menu-sidebar' && (this.sidebarCompact = true));
69     this.sidebarService.onExpand().subscribe(() => this.sidebarCompact = false);
70     this.menuService.onSubmenuToggle().subscribe(i => i.item && i.item.expanded && (this.sidebarCompact = false));
71
72     // Automatically expand sidebar on mouse over
73     this._mouseEnterStream.flatMap(e => {
74       return Observable
75         .of(e)
76         .delay(200)
77         .takeUntil(this._mouseLeaveStream);
78     })
79       .subscribe(e => (this.sidebarCompact) && this.sidebarService.toggle(true, 'menu-sidebar'));
80
81     // Automatically collapse sidebar on mouse leave
82     this._mouseLeaveStream.flatMap(e => {
83       return Observable
84         .of(e)
85         .delay(500)
86         .takeUntil(this._mouseEnterStream);
87     })
88       .subscribe(e => this.sidebarService.toggle(true, 'menu-sidebar'));
89   }
90
91   onMouseEnter($event) {
92     this._mouseEnterStream.emit($event);
93   }
94
95   onMouseLeave($event) {
96     this._mouseLeaveStream.emit($event);
97   }
98
99   toogleSidebar() {
100     this.sidebarService.toggle(true, 'menu-sidebar');
101   }
102
103   ngOnDestroy() {
104     this.layoutState$.unsubscribe();
105     this.sidebarState$.unsubscribe();
106     this.menuClick$.unsubscribe();
107   }
108 }