import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Inject, Input, OnDestroy, OnInit, Output, Renderer2, } from '@angular/core'; import { Genes } from '../../../core/models'; import { FormControl, FormGroup } from '@angular/forms'; import { distinctUntilChanged, filter, map, takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { ApiService } from '../../../core/services/api/open-genes-api.service'; import { ToMap } from '../../../core/utils/to-map'; import { SettingsService } from '../../../core/services/settings.service'; import { SearchMode, SearchModeEnum } from '../../../core/models/settings.model'; @Component({ selector: 'app-search', templateUrl: './search.component.html', styleUrls: ['./search.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) export class SearchComponent extends ToMap implements OnInit, OnDestroy { @Inject(Document) public document: Document; @Input() genesLength: number; @Input() showTitle: boolean; @Input() showProgressBar: boolean; @Input() set isDisabled(value: boolean) { this.formDisabled = value; if (value) { this.searchForm.controls['searchField'].disable(); } else { this.searchForm.controls['searchField'].enable(); } } @Input() set searchHintsList(genes: any) { if (genes) { this.searchedData = genes; } } @Input() set setSearchMode(value: SearchMode) { if (value) { this.searchMode = value; this.searchedData = []; this.searchForm.get('searchField').setValue(''); } } @Input() fixOnTopOnMobile = true; // TODO: move it out of component and activate in parent component on event @Output() searchQuery: EventEmitter<string> = new EventEmitter<string>(); @Output() confirmedQuery: EventEmitter<boolean> = new EventEmitter<boolean>(); @Output() cancel: EventEmitter<boolean> = new EventEmitter<boolean>(); public searchedData: Partial<Genes[]>; public searchForm: FormGroup; public searchMode: SearchMode; public formDisabled: boolean; public clearFieldButton: boolean; public showSearchResult = false; public highlightText: string; public inputData = [ { searchMode: SearchModeEnum.searchByGenes, placeholder: 'search_field_start_typing', }, { searchMode: SearchModeEnum.searchByGoTerms, placeholder: 'search_field_tap_search', }, { searchMode: SearchModeEnum.searchByGenesList, placeholder: 'search_field_by_comma', }, ]; private subscription$ = new Subject(); constructor( private renderer: Renderer2, private apiService: ApiService, private settingsService: SettingsService, private cdRef: ChangeDetectorRef ) { super(); this.searchForm = new FormGroup({ searchField: new FormControl(''), }); } ngOnInit(): void { this.subsToSearchFieldChanges(); } ngOnDestroy(): void { this.subscription$.next(); this.subscription$.complete(); this.cancelSearch(); } private subsToSearchFieldChanges(): void { this.searchForm .get('searchField') .valueChanges.pipe( map((query: string) => query.toLowerCase().replace(/-/g, '')), filter((query: string) => { this.clearFieldButton = !!query; this.highlightText = query; this.showSearchResult = query?.length >= 2; if (this.showSearchResult && this.fixOnTopOnMobile) { this.renderer.addClass(document.body, 'body--search-on-main-page-is-active'); } else { this.renderer.removeClass(document.body, 'body--search-on-main-page-is-active'); } return this.showSearchResult; }), distinctUntilChanged(), takeUntil(this.subscription$) ) .subscribe((query: string) => { this.searchQuery.emit(query); this.cdRef.markForCheck(); }); } public onSearch(): void { this.confirmedQuery.emit(!!this.highlightText); } public cancelSearch(event?): void { event?.stopPropagation(); this.showSearchResult = false; this.cancel.emit(true); if (this.fixOnTopOnMobile) { this.renderer.removeClass(document.body, 'body--search-on-main-page-is-active'); } } public clearSearch(): void { this.searchForm.get('searchField').setValue(''); const query: string = this.searchForm.get('searchField').value; this.searchQuery.emit(query); this.confirmedQuery.emit(false); this.cancelSearch(); } }