import {switchMap, distinctUntilChanged, debounceTime} from 'rxjs/operators'; import {Component, ElementRef, Input, Output, EventEmitter, SimpleChange} from '@angular/core'; import {Observable, Subject} from 'rxjs'; import {EntitiesSearchService} from './entitySearch.service'; import{EnvProperties} from '../properties/env-properties'; import {StringUtils} from "../string-utils.class"; import {AutoCompleteValue} from "../../searchPages/searchUtils/searchHelperClasses.class"; //Usage example // @Component({ selector: 'entities-autocomplete', host: { '(document:click)': 'handleClick($event)', }, template: `
{{showItem(item)}}
` }) export class EntitiesAutocompleteComponent { @Input() placeHolderMessage = "Search for entries"; @Input() title = "Autocomplete"; @Output() addItem = new EventEmitter(); // when selected list changes update parent component @Output() selectedValueChanged = new EventEmitter(); // when changed a method for filtering will be called @Output() updateValueLabel = new EventEmitter(); //when the value is id sends an event to update the value (for meta tags) @Input() public list = []; // the entries resulted after filtering function @Input() public selected = []; // the entries selected from user @Input() public keywordlimit = 3; // the minimum length of keyword @Input() public showSelected = true; // the minimum length of keyword @Input() public multipleSelections:boolean = true; @Input() public allowDuplicates:boolean = false; @Input() public selectedValue:string = ''; @Input() public keyword = ''; @Input() public fieldId:string ; @Input() public properties:EnvProperties ; @Input() id; public currentFieldId: string ; public currentFunderId: string ; public warningMessage = ""; public infoMessage = ""; public tries = 0; public showInput = true; public sub; public done = false; public showLoading:boolean = false; public searchTermStream = new Subject(); filtered: Observable<{}> ; // public numFilteredResults:number = 0; @Input() public funderId:string; @Input() public entityType:string ; @Input() public depositType:string ; public results = 0; public focus:boolean = false; constructor (public _search:EntitiesSearchService, private myElement: ElementRef) { this.currentFieldId=this.fieldId; this.currentFunderId=this.funderId; this.initialize(); } ngOnChanges(changes: {[propKey: string]: SimpleChange}) { if(this.currentFieldId!=this.fieldId){ //this is going to be called when this.currentFieldId=this.fieldId; this.initialize(); }else if(this.currentFunderId!=this.funderId){ this.currentFunderId=this.funderId; this.initialize(); } } private initialize(){ this.showInput = true; /* if(this.entityType == "project" && this.funderId ){ this.filtered = this.searchTermStream.pipe( debounceTime(300),distinctUntilChanged(), switchMap((term: string) => { //console.log("funder"+this.funderId); var results = this._search.searchProjectsByFunder(term, (this.funderId == "0"?"":encodeURIComponent(this.funderId)), this.properties); this.showLoading = false; this.results = results.length; return results; }),); }else */ if(this.entityType == "organization" && this.depositType ){ this.filtered = this.searchTermStream.pipe( debounceTime(300),distinctUntilChanged(), switchMap((term: string) => { var results = this._search.searchByDepositType(term, this.depositType, this.properties); this.showLoading = false; this.results = results.length; return results; }),); }else{ this.filtered = this.searchTermStream.pipe( debounceTime(300), distinctUntilChanged(), switchMap((term: string) => { var results = this._search.searchByType(StringUtils.URIEncode(term), this.entityType, this.properties); this.showLoading = false; this.results = results.length; return results; }),); this.getSelectedNameFromGivenId(); } } ngOnDestroy(){ if(this.sub){ this.sub.unsubscribe(); } } search() { this.infoMessage = ""; if(this.keyword == ""){ this.tries = 0; this.warningMessage = ""; } else if(this.keyword && this.keyword.length < this.keywordlimit){ this.tries++; if(this.tries == this.keywordlimit -1 ){ this.warningMessage = "Type at least " + this.keywordlimit + " characters"; this.tries = 0; } }else{ this.tries = 0; this.warningMessage = ""; this.searchTermStream.next(this.keyword); // if(this.numFilteredResults ==0){ this.showLoading = true; this.focus = true; // } } } remove(item:any){ var index:number =this.checkIfExists(item,this.selected); if (index > -1) { this.selected.splice(index, 1); } if(!this.multipleSelections && this.selected.length == 0 ){ this.showInput = true; this.selectedValue = ""; this.selectedValueChanged.emit({ value: this.selectedValue }); this.updateValueLabel.emit({ value:"" }); } } select(item:any){ if(this.multipleSelections){ var index:number =this.checkIfExists(item,this.selected); if (index > -1 && !this.allowDuplicates) { // this.keyword = ""; // this.filtered.splice(0, this.filtered.length); this.focus=false; return; } else{ this.selected.push(item); // this.keyword = ""; // this.filtered.splice(0, this.filtered.length); this.addItem.emit({ value: item }); this.focus=false; } }else{ this.selected.splice(0, this.selected.length); this.selected.push(item); // this.filtered.splice(0, this.filtered.length); this.keyword = ""; this.showInput = false; this.selectedValue = item.id; this.selectedValueChanged.emit({ value: this.selectedValue }); this.updateValueLabel.emit({ value:this.showItem(item) }); this.focus=false; } } private checkIfExists(item:any,list):number{ if(item.concept && item.concept.id ){ for (var _i = 0; _i < list.length; _i++) { let itemInList = list[_i]; if(item.concept.id == itemInList.concept.id){ return _i; } } }else if(item.id){ for (var _i = 0; _i < list.length; _i++) { let itemInList = list[_i]; if(item.id == itemInList.id){ return _i; } } } return -1; } showItem(item:any):string{ //console.log(item); if(!item){ return "[No title available]" } else if (item.projectName || item.projectAcronym || item.code){ //project return ((item.projectAcronym)?"["+item.projectAcronym+"] ":"")+item.projectName+((item.code)?" ("+item.code+")":""); }else if (item.name){ //search return item.name; }else if( item.concept && item.concept.label){ //context return item.concept.label; }else if (item.label){ //simple return item.label; } } truncate(str:string, size:number):string{ if(str == null){return "";} return (str.length > size)?str.substr(0,size)+'...':str; } private getSelectedNameFromGivenId(){ this.showInput = true; if(this.selectedValue && this.selectedValue.length > 0 ) { this.sub = this._search.fetchByType(this.selectedValue,this.entityType, this.properties).subscribe( data => { this.selected.push( data[0]); this.updateValueLabel.emit({ value:this.showItem(this.selected[0]) }); this.showInput = false; }, err => { //console.log("An error occured")); this.handleError("Error getting results of type: "+this.entityType+" with id: "+this.selectedValue, err); this.selected.push( {label:this.selectedValue, id :this.selectedValue}); this.updateValueLabel.emit({ value:this.showItem(this.selected[0]) }); this.showInput = false; } ); } } handleClick(event){ var clickedComponent = event.target; var inside = false; do { if (clickedComponent === this.myElement.nativeElement) { inside = true; } clickedComponent = clickedComponent.parentNode; } while (clickedComponent); if(!inside){ this.keyword = ""; // this.numFilteredResults = 0; this.searchTermStream.next(this.keyword); this.focus=false; } } private handleError(message: string, error) { console.error("Autocomplete (component): "+message, error); } }