import { Component , ElementRef , OnDestroy , ViewChild } from '@angular/core' ; import { SearchBuilderComponentDefinition , SearchBuilderFocusService , SearchBuilderQuery , SearchDateRangeComponent , SearchDateRangeConfig , SearchSelectComponent , SearchSelectConfig , SearchTextComponent , SearchTextConfig } from '@ux-aspects/ux-aspects' ; import 'chance' ; import { BsModalService } from 'ngx-bootstrap/modal' ; import { Subject } from 'rxjs' ; import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject' ; import { first , takeUntil } from 'rxjs/operators' ; @ Component ( { selector : 'app' , templateUrl : './app.component.html' , styleUrls : [ './app.component.css' ] } ) export class AppComponent implements OnDestroy { query : SearchBuilderQuery = { keywords : [ { type : 'keyword' , value : null } ] , any : [ ] , all : [ ] , none : [ ] } ; preview : string = JSON . stringify ( this . query , null , 2 ) ; valid : boolean = true ; filter$ = new BehaviorSubject < string > ( '' ) ; modalOpen : boolean = false ; panelOpen : boolean = false ; placeholders = { any : false , all : false , none : false } ; components : SearchBuilderComponentDefinition [ ] = [ { name : 'keyword' , component : SearchTextComponent , config : { placeholder : 'Enter keywords' } as SearchTextConfig } , { name : 'author' , component : SearchTextComponent , config : { label : 'Author' , placeholder : 'Enter an Author' } as SearchTextConfig } , { name : 'custodian' , component : SearchSelectComponent , config : { label : 'Custodian' , placeholder : 'Select Custodians' , options : this . getCustodians ( ) , multiple : true } as SearchSelectConfig } , { name : 'date-range' , component : SearchDateRangeComponent , config : { label : 'Date range' } as SearchDateRangeConfig } , { name : 'file-name' , component : SearchTextComponent , config : { label : 'File name' , placeholder : 'Enter a File Name' } } , { name : 'file-type' , component : SearchSelectComponent , config : { label : 'File types' , placeholder : 'Select File Types' , options : [ 'AVI' , 'BMP' , 'CSV' , 'DOC' , 'EXE' , 'GIF' , 'JPG' , 'MOV' , 'PDF' , 'PNG' , 'PPT' , 'RTF' , 'TXT' , 'XLS' , 'ZIP' ] , multiple : true } as SearchSelectConfig } , { name : 'repository' , component : SearchSelectComponent , config : { label : 'Repository' , placeholder : 'Enter a Repository' , options : [ 'Filesystem' , 'Records Manager' , 'Email' , 'Legacy Email' , 'Archives' , 'Legacy Archives' , 'Miscellaneous' ] , multiple : true } as SearchSelectConfig } , { name : 'text' , component : SearchTextComponent , config : { label : 'Text' , placeholder : 'Enter Text' } as SearchTextConfig } ] ; fields : SearchBuilderField [ ] = [ { title : 'Author' , type : 'author' , } , { title : 'Custodian' , type : 'custodian' } , { title : 'Date Range' , type : 'date-range' } , { title : 'File Name' , type : 'file-name' } , { title : 'File Type' , type : 'file-type' } , { title : 'Repository' , type : 'repository' } , { title : 'Text' , type : 'text' } ] ; filteredFields : SearchBuilderField [ ] ; @ ViewChild ( 'searchBuilderContent' ) searchBuilderContent : ElementRef < HTMLElement > ; private _field$ : Subject < SearchBuilderField > = new Subject < SearchBuilderField > ( ) ; private _onDestroy = new Subject < void > ( ) ; constructor ( private _modalService , private _searchBuilderFocusService ) { this . _modalService . onHide . pipe ( takeUntil ( this . _onDestroy ) ) . subscribe ( ( ) => this . cancel ( ) ) ; this . filter$ . pipe ( takeUntil ( this . _onDestroy ) ) . subscribe ( value => { this . filteredFields = this . fields . filter ( field => field . title . toLowerCase ( ) . indexOf ( value . toLowerCase ( ) ) >= 0 ) ; } ) ; } ngOnDestroy ( ) { this . _onDestroy . next ( ) ; this . _onDestroy . complete ( ) ; } save ( ) { this . preview = JSON . stringify ( this . query , null , 2 ) ; this . modalOpen = false ; } cancel ( ) { this . query = JSON . parse ( this . preview ) ; this . modalOpen = false ; } addKeyword ( ) { const length = this . query . keywords . push ( { type : 'keyword' , value : null } ) ; this . _searchBuilderFocusService . setFocus ( 'keywords' , length - 1 ) ; } addField ( group , event ) { const button = < HTMLElement > event . currentTarget ; this . showPanel ( ) ; this . placeholders [ group ] = true ; this . _field$ . pipe ( first ( ) ) . subscribe ( field => { this . placeholders [ group ] = false ; if ( field ) { const length = this . query [ group ] . push ( { type : field . type , value : null } ) ; this . _searchBuilderFocusService . setFocus ( group , length - 1 ) ; } else { button . focus ( ) ; } } ) ; event . stopPropagation ( ) ; } showPanel ( ) { this . filter$ . next ( '' ) ; this . panelOpen = true ; } onPanelEvent ( open ) { if ( ! open ) { this . _field$ . next ( null ) ; } } selectField ( field ) { if ( field ) { this . _field$ . next ( field ) ; this . panelOpen = false ; } } getCustodians ( ) { const custodians = [ ] ; for ( let idx = 0 ; idx < 20 ; idx ++ ) { custodians . push ( chance . name ( ) ) ; } return custodians ; } modalShown ( ) { this . _searchBuilderFocusService . setFocus ( 'keywords' , 0 ) ; } } interface SearchBuilderField { title : string ; type : string ; }