import { Component, Input, Output, OnInit, EventEmitter, SimpleChanges, OnChanges, ViewChild } from '@angular/core'; import { Observable , of,merge,forkJoin } from 'rxjs'; import { debounceTime,distinctUntilChanged,tap,switchMap,catchError,map} from 'rxjs/operators'; import { TypeaheadService, TimespanService } from '@farmmaps/common'; import { IQueryState } from '@farmmaps/common'; import { IPeriodState } from '../../models/period.state'; import { tassign } from 'tassign'; @Component({ selector: 'fm-map-map-search', templateUrl: './map-search.component.html', styleUrls: ['./map-search.component.scss'] }) export class MapSearchComponent { @ViewChild('searchText', { static: true }) searchText; @Input() clearEnabled: boolean @Input() set collapsed(collapsed: boolean) { this.collapsedLocal = collapsed; if (collapsed) this.searchText.nativeElement.blur(); } @Input() set searchMinified(minified: boolean) { this.searchMinifiedLocal = minified; } @Input() set period(period:IPeriodState) { this.periodLocal = tassign(this.periodLocal,{startDate: period.startDate,endDate:period.endDate}); this.startEndCaption = this.timespanService.getCaption(period.startDate, period.endDate, 4) } @Output() onSearch = new EventEmitter() @Output() onCitySearch = new EventEmitter() @Output() onClear = new EventEmitter(); @Output() onSearchCollapse = new EventEmitter(); @Output() onSearchExpand = new EventEmitter(); @Output() onToggleMenu = new EventEmitter(); @Output() onOpenModal = new EventEmitter(); @Output() onCloseModal = new EventEmitter(); @Output() onPeriodChange = new EventEmitter(); @Input() openedModalName: string; @Input() set filterOptions(filterOptions: IQueryState) { if (filterOptions && filterOptions.query && filterOptions.query.length > 0) { this.disabled = false; } else { this.disabled = true; } this.filterOptionsLocal = tassign(this.filterOptionsLocal, { tags: filterOptions.tags, query: filterOptions.query,bbox:filterOptions.bbox }); if (filterOptions.tags) { this.searchTextLocal = { name: filterOptions.tags }; } else { this.searchTextLocal = { name: filterOptions.query }; } } public collapsedLocal = true; public searchMinifiedLocal = false; public periodLocal: IPeriodState = { startDate:new Date(new Date(Date.now()).getFullYear(), new Date(Date.now()).getMonth() - 3, 1), endDate:new Date(Date.now())}; public filterOptionsLocal: IQueryState; private extent: number[]; public searchTextLocal: any; public searchTextLocalOutput: string; public dateFilter = true; public startEndCaption: string = this.timespanService.getCaption(this.periodLocal.startDate, this.periodLocal.endDate, 4); searching = false; searchFailed = false; hideSearchingWhenUnsubscribed = new Observable(() => () => this.searching = false); public disabled = true; constructor(private typeaheadService: TypeaheadService, private timespanService: TimespanService) { this.filterOptionsLocal = { query: "", tags: "", startDate: null, endDate: null, bboxFilter: false, itemType: null, itemCode:null,level:0,parentCode:null,bbox:[] }; } search = (text$: Observable) => text$.pipe( debounceTime(300), distinctUntilChanged(), tap(() => {this.searching = true;this.searchFailed=false;}), switchMap(term => term.length < 1 ? of([]) : forkJoin( this.typeaheadService.getTagTypeaheadItems(term).pipe( catchError(() => { this.searchFailed = true; return of([]); }),map( (sa:string[]) => sa.map((s,i) => ({"name":s,"type":"tag"})))), this.typeaheadService.getCityTypeaheadItems(term).pipe( catchError(() => { this.searchFailed = true; return of([]); }),map( (sa:string[]) => sa.map((s,i) => ({"name":s,"type":"city"})))), ).pipe(map(([a1,a2]) => [...a1, ...a2] ),map(a => a.sort((a, b) => (a.name.toUpperCase() > b.name.toUpperCase()) ? 1 : -1))) ), tap(() => this.searching = false), ); formatter = (x: { name: string }) => x.name; handleSearch(event) { this.filterOptionsLocal.tags = null; this.filterOptionsLocal.itemType = null; this.filterOptionsLocal.itemCode = null; this.filterOptionsLocal.parentCode = null; this.filterOptionsLocal.query = this.searchTextLocalOutput; if (this.dateFilter) { this.filterOptionsLocal.startDate = this.periodLocal.startDate; this.filterOptionsLocal.endDate = this.periodLocal.endDate; } this.onSearch.emit(this.filterOptionsLocal); } handleOpenSelectPeriodModal(event: MouseEvent) { event.preventDefault(); this.onOpenModal.emit('selectPeriodModal'); } handleCloseModal() { this.onCloseModal.emit({}); } handleSelect(event) { if(event.item.type == "tag") { event.preventDefault(); this.filterOptionsLocal.query = null; this.filterOptionsLocal.itemType = null; this.filterOptionsLocal.itemCode = null; this.filterOptionsLocal.parentCode = null; this.filterOptionsLocal.tags = event.item.name; if (this.dateFilter) { this.filterOptionsLocal.startDate = this.periodLocal.startDate; this.filterOptionsLocal.endDate = this.periodLocal.endDate; } this.onSearch.emit(this.filterOptionsLocal); this.searchTextLocal = { name: this.filterOptionsLocal.tags }; } else if (event.item.type == "city") { this.clearEnabled = true; this.onCitySearch.emit(event.item.name); } } handleSelectPeriod(event: { startDate: Date, endDate: Date }) { this.periodLocal = { startDate: event.startDate, endDate: event.endDate} this.onPeriodChange.emit(this.periodLocal); this.startEndCaption = this.timespanService.getCaption(event.startDate, event.endDate, 4); if(this.dateFilter) { this.filterOptionsLocal.startDate =event.startDate; this.filterOptionsLocal.endDate = event.endDate; this.onSearch.emit(this.filterOptionsLocal); } this.handleCloseModal(); } handleChangeEnableDateFilter(enabled) { this.dateFilter = enabled; if (enabled) { this.filterOptionsLocal.startDate = this.periodLocal.startDate; this.filterOptionsLocal.endDate = this.periodLocal.endDate; } else { this.filterOptionsLocal.startDate = null; this.filterOptionsLocal.endDate = null; } if(this.filterOptionsLocal.query || this.filterOptionsLocal.tags) this.onSearch.emit(this.filterOptionsLocal); } handleChangeEnableBBOXFilter(enabled) { this.filterOptionsLocal.bboxFilter = enabled; if (this.filterOptionsLocal.query || this.filterOptionsLocal.tags) this.onSearch.emit(this.filterOptionsLocal); } handleToggleMenu(event) { this.onToggleMenu.emit({}); } handleFocus(event) { this.onSearchExpand.emit({}); } handleChange(event: string) { this.searchTextLocalOutput = event; if (event && event.length == 1) { this.onSearchExpand.emit({}); } if (event && event.length > 0) this.disabled = false; else this.disabled = true; } handleClearClick(event) { this.onClear.emit({}); } getIcon(type):string { if(type == "tag") return "fal fa-tag"; else if(type == "city") return "fal fa-map-marker-alt"; else if(type == "search") return "fal fa-search"; } }