import { Component , OnDestroy , OnInit } from '@angular/core' ; import { SearchService } from './search.service' ; import { AbstractControl , FormControl , FormGroup , Validators } from '@angular/forms' ; import { ActivatedRoute , NavigationEnd , Router } from '@angular/router' ; import { ReplaySubject } from 'rxjs' ; import { SearchResultList } from './models/search-result' ; import { HttpParams } from '@angular/common/http' ; import { filter , skip , takeUntil } from 'rxjs/operators' ; import { ProgressSpinnerService } from '../layout/progress/progress-spinner.service' ; import { PageLengthEntry } from '../layout/table/components/table-page-size/table-page-size.component' ; @ Component ( { templateUrl : './search.component.html' , styleUrls : [ './search.component.scss' ] } ) export class SearchComponent implements OnInit , OnDestroy { /**
     * Get the form control of the input field.
     */ public get input ( ) : AbstractControl { return this . searchInputForm . get ( 'input' ) ; } /**
     * Default page size
     */ private readonly defaultLimit : number = 10 ; /**
     * Results skipped for pagination.
     * Will be something like: skip = limit * (page-1).
     */ private skip : number = 0 ; /**
     * Used page size.
     * Max number of displayed results.
     */ public limit : number = this . defaultLimit ; /**
     * Current page number.
     */ public currentPage : number = 1 ; /**
     * Max number of size for pagination truncate.
     */ public maxNumberOfSites : number [ ] ; private initSearch : boolean = true ; private initFilter : boolean = true ; /**
     * Search form input group.
     */ public searchInputForm : FormGroup ; /**
     * List of search results.
     */ public searchResultList : SearchResultList ; public publicIdResult ; public filterResultList : any [ ] ; /**
     * Query parameters.
     */ public queryParameters : any = [ ] ; /**
     * Component un-subscriber.
     */ private subscriber : ReplaySubject < void > = new ReplaySubject < void > ( ) ; private public readonly defaultResultSizeList : Array < PageLengthEntry > = [ { label : '10' , value : 10 } , { label : '25' , value : 25 } , { label : '50' , value : 50 } , { label : '100' , value : 100 } , { label : '200' , value : 200 } ] ; /**
     * Page size select form group.
     */ public resultSizeForm : FormGroup = new FormGroup ( { size : new FormControl ( this . limit ) , } ) ; /**
     * Constructor of SearchComponent
     */ constructor ( private route , private searchService , private spinner , private router ) { this . searchInputForm = new FormGroup ( { input : new FormControl ( '' , Validators . required ) } ) ; } public ngOnInit ( ) { this . route . queryParamMap . pipe ( takeUntil ( this . subscriber ) ) . subscribe ( params => { this . queryParameters = params . get ( 'query' ) ; if ( params . has ( 'limit' ) ) { this . limit = ( + JSON . parse ( params . get ( 'limit' ) ) ) ; this . resultSizeForm . get ( 'size' ) . setValue ( this . limit ) ; } if ( params . has ( 'page' ) ) { this . currentPage = ( + JSON . parse ( params . get ( 'page' ) ) ) ; } else { this . currentPage = 1 ; } if ( params . has ( 'skip' ) ) { this . skip = ( + JSON . parse ( params . get ( 'skip' ) ) ) ; } else { this . skip = 0 ; } this . initSearch = true ; this . initFilter = ( window . history . state . load || window . history . state . load === undefined ) ; this . onSearch ( ) ; } ) ; this . resultLength . valueChanges . pipe ( takeUntil ( this . subscriber ) ) . subscribe ( ( size ) => { this . limit = size ; this . router . navigate ( [ ] , { relativeTo : this . route , queryParams : { limit : this . limit } , queryParamsHandling : 'merge' } ) . then ( ) ; this . onSearch ( ) ; } ) ; } /**
     * Get the form control of the size selection.
     */ public get resultLength ( ) : FormControl { return this . resultSizeForm . get ( 'size' ) as FormControl ; } /**
     * Triggers the actual search api call.
     */ public onSearch ( ) { this . publicIdResult = undefined ; this . spinner . show ( 'app' , 'Searching...' ) ; let params = new HttpParams ( ) ; params = params . set ( 'limit' , this . limit . toString ( ) ) ; params = params . set ( 'skip' , this . skip . toString ( ) ) ; this . searchService . postSearch ( this . queryParameters , params ) . pipe ( takeUntil ( this . subscriber ) ) . subscribe ( ( results ) => { this . searchResultList = results ; this . filterResultList = this . initFilter && results !== null ? results . groups : this . filterResultList ; if ( this . initSearch ) { this . maxNumberOfSites = Array . from ( { length : ( this . searchResultList . total_results ) } , ( v , k ) => k + 1 ) ; this . initSearch = false ; this . initFilter = false ; } } ) ; let localParameters = JSON . parse ( this . queryParameters ) ; if ( localParameters . length === 1 ) { localParameters [ 0 ] . searchForm = 'publicID' ; localParameters = JSON . stringify ( localParameters ) ; this . searchService . postSearch ( localParameters , params ) . pipe ( takeUntil ( this . subscriber ) ) . subscribe ( ( results ) => { if ( results !== null && results . results . length > 0 ) { this . publicIdResult = results . results [ 0 ] ; } } ) . add ( ( ) => this . spinner . hide ( 'app' ) ) ; } else { this . spinner . hide ( 'app' ) ; } } param event public onChangePage ( event ) { this . currentPage = event ; this . skip = ( this . currentPage - 1 ) * this . limit ; this . setPageParam ( this . currentPage ) ; this . onSearch ( ) ; } private setPageParam ( page ) { this . router . navigate ( [ ] , { relativeTo : this . route , queryParams : { page , skip : this . skip , query : this . queryParameters } , queryParamsHandling : 'merge' } ) . then ( ) ; } public ngOnDestroy ( ) { this . subscriber . next ( ) ; this . subscriber . complete ( ) ; } }