import { animate, keyframes, query, stagger, state, style, transition, trigger } from '@angular/animations'; import { AfterViewInit, ChangeDetectorRef, Component, HostListener, OnInit, QueryList, ViewChildren } from '@angular/core'; import { MatSelectionList, MatTabChangeEvent } from '@angular/material'; import { Router } from '@angular/router'; import * as _ from 'lodash'; import { ApplicationService } from '../../../application.service'; import { Category } from '../../../models'; import { Application } from '../../../models/application/application.interface'; import { StartupService } from '../../../startup.service'; import { MenuOverlayRef } from './menu-overlay-ref'; @Component({ selector: 'vitamui-common-menu', templateUrl: './menu.component.html', styleUrls: ['./menu.component.scss'], animations: [ trigger('opacityAnimation', [ state('close', style({})), transition(':enter', [ animate('500ms cubic-bezier(0, 0, 0.2, 1)', keyframes([ style({ opacity: 0 }), style({ opacity: 1 }), ])), ]), transition('* => close', [ animate('500ms cubic-bezier(0, 0, 0.2, 1)', keyframes([ style({ opacity: 1 }), style({ opacity: 0 }), ])), ]), ]), trigger('slideLeftRight', [ transition(':enter', [ query('*', [ style({ opacity: 0, transform: 'translateX(-20px)' }), stagger(50, [ animate( '50ms', style({ opacity: 1, transform: 'none' }) ) ]) ]) ]), transition(':leave', [ animate( '250ms', style({ opacity: 0, transform: 'translateX(+100px)' }) ) ]) ]) ] }) export class MenuComponent implements OnInit, AfterViewInit { public state = ''; private applications: Application[]; public filteredApplications: Application[] = null; public applicationsGroupBy: _.Dictionary<Application[]>; public criteria: string; public tabSelectedIndex = 0; public readonly CATEGORY = [ { position: 0, identifier: 'users', name: 'Utilisateur' }, { position: 1, identifier: 'administrators', name: 'Management' }, { position: 2, identifier: 'settings', name: 'Paramétrage' }, ] as Category[]; @ViewChildren(MatSelectionList) selectedList: QueryList<MatSelectionList>; @HostListener('document:keydown', ['$event']) handleKeyboardEvent(event: KeyboardEvent) { if (event.key === 'ArrowRight') { if (this.tabSelectedIndex < this.selectedList.length - 1) { this.tabSelectedIndex++; } } else if (event.key === 'ArrowLeft') { if (this.tabSelectedIndex > 0) { this.tabSelectedIndex--; } } } constructor( private dialogRef: MenuOverlayRef, private applicationService: ApplicationService, private startupService: StartupService, private cdrRef: ChangeDetectorRef, private router: Router) { } ngAfterViewInit(): void { this.changeTabFocus(); } ngOnInit() { this.applications = _.orderBy(this.applicationService.applications, 'position'); this.applicationsGroupBy = _.groupBy(this.applications, 'category'); this.dialogRef.overlay.backdropClick().subscribe(() => this.onClose()); } public onSearch(value: string): void { if (value) { this.criteria = value; this.filteredApplications = this.applications.filter((application: Application) => application.name.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase() .includes(value.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase())); this.cdrRef.detectChanges(); if (this.filteredApplications.length > 0) { (document.getElementById('searchResults').firstElementChild as any).focus(); } } else { this.filteredApplications = null; this.criteria = ''; this.changeTabFocus(); } } public onClose(): void { this.state = 'close'; setTimeout(() => this.dialogRef.close(), 500); } public getCategory(): Category[] { return this.CATEGORY.sort((a, b) => { return a.position < b.position ? -1 : 1; }); } public changeTabFocus(value?: MatTabChangeEvent): void { if (value && value.index !== this.tabSelectedIndex) { this.tabSelectedIndex = value.index; // when clicking } // tslint:disable-next-line: variable-name setTimeout(() => this.selectedList.find((_select, index) => index === this.tabSelectedIndex).options.first.focus(), 300); } public openApplication(app: Application) { const uiUrl = this.startupService.getConfigStringValue('UI_URL'); // If called app is in the same server... if (app.url.includes(uiUrl)) { this.router.navigate([app.url.replace(uiUrl, '')]); } else { window.location.href = app.url; } } }