import { FocusOrigin } from '@angular/cdk/a11y' ; import { ChangeDetectorRef , Component , OnDestroy , OnInit , ViewChild } from '@angular/core' ; import { FocusIndicatorOriginService , HierarchyBarNode , OrganizationChartComponent , OrganizationChartNode , TypeaheadKeyService , TypeaheadOptionEvent } from '@ux-aspects/ux-aspects' ; import { Observable , Subject } from 'rxjs' ; import { first } from 'rxjs/operators' ; import { OrganizationChartContext , OrganizationChartDataService } from './organization-chart.service' ; @ Component ( { selector : 'uxd-organization-chart' , templateUrl : './organization-chart.component.html' , styleUrls : [ './organization-chart.component.less' ] } ) export class OrganizationChartShowcaseComponent implements OnInit , OnDestroy { /** Define the open state of the search input */ isSearchOpen : boolean = false ; /** Determine if we should show the reveal button */ showReveal : boolean = true ; /** Store the current search query */ query : string = '' ; /** Get the organization dataset */ dataset : OrganizationChartNode < OrganizationChartContext > = this . _dataService . getDataset ( ) . children [ 0 ] ; /** Get the hierarchy from the dataset */ hierarchy : HierarchyBarNode = this . getHierarchy ( this . dataset ) ; /** Store the currently selected hierarchy bar node */ hierarchyBarSelected : HierarchyBarNode ; /** Store the currently selected organization chart node */ organizationChartSelected : OrganizationChartNode < OrganizationChartContext > ; /** Store the typeahead search options */ typeaheadOptions : OrganizationChartNode < OrganizationChartContext > [ ] = this . flatten ( this . dataset ) ; /** Store the current highlighted options */ highlighted : OrganizationChartNode < OrganizationChartContext > ; /** Emit whenever the transition ends */ onTransitionEnd = new Subject < void > ( ) ; /** Get the organization chart component instance */ @ ViewChild ( OrganizationChartComponent , { static : true } ) organizationChart : OrganizationChartComponent < OrganizationChartContext > ; constructor ( private _dataService , public typeaheadKeyService , private _changeDetector , private _focusIndicatorOrigin ) { } ngOnInit ( ) { this . onOrganizationChartSelect ( this . dataset . children [ 0 ] ) ; } ngOnDestroy ( ) { this . onTransitionEnd . complete ( ) ; } getHierarchy ( node ) { return { title : node . data . name , children : node . children ? node . children . map ( child => this . getHierarchy ( child ) ) : null } as HierarchyBarNode ; } onReveal ( ) { this . dataset = this . _dataService . getDataset ( ) ; this . hierarchy = this . getHierarchy ( this . dataset ) ; this . typeaheadOptions = this . flatten ( this . dataset ) ; this . showReveal = false ; } onOrganizationChartSelect ( node ) { this . organizationChartSelected = node ; const nodes = this . flatten ( this . hierarchy ) ; this . hierarchyBarSelected = nodes . find ( _node => _node . title === node . data . name ) ; } onHierarchyBarSelect ( node ) { const nodes = this . flatten ( this . dataset ) ; this . organizationChartSelected = nodes . find ( _node => _node . data . name === node . title ) ; } onTypeaheadSelect ( event , focusOrigin = 'mouse' ) { const node = event instanceof TypeaheadOptionEvent ? event . option : event ; this . query = '' ; this . _focusIndicatorOrigin . setOrigin ( focusOrigin ) ; const selectNode = ( ) => { this . onOrganizationChartSelect ( node ) ; this . _changeDetector . detectChanges ( ) ; this . organizationChart . focus ( node ) ; } ; if ( this . flatten ( this . dataset ) . indexOf ( node ) === - 1 ) { this . onReveal ( ) ; this . typeaheadOptions = this . flatten ( this . dataset ) ; this . onTransitionEnd . pipe ( first ( ) ) . subscribe ( ( ) => selectNode ( ) ) ; } else { selectNode ( ) ; } } /** Get a flattened array of the OrganizationChart nodes or HierarchyBarNodes */ flatten < T extends HasChildren < T > > ( nodes ) { nodes = Array . isArray ( nodes ) ? nodes : [ nodes ] ; return nodes . reduce ( ( accumulation , node ) => Array . isArray ( node . children ) ? [ ... accumulation , node , ... this . flatten ( node . children ) ] : [ ... accumulation , node ] , [ ] ) ; } getTypeaheadDisplay ( node ) { return node . data . name ; } search ( ) { const options = this . flatten ( this . _dataService . getDataset ( ) ) ; this . typeaheadOptions = options . filter ( option => { return option . data . name . toLowerCase ( ) . indexOf ( this . query . toLowerCase ( ) ) !== - 1 || option . data . role . toLowerCase ( ) . indexOf ( this . query . toLowerCase ( ) ) !== - 1 ; } ) ; } } export interface HasChildren < T > { children ? : T [ ] | ReadonlyArray < T > | Observable < T [ ] > ; }