blob: 05d9a972873dcec202d1ba9775a5f78ef7004cc7 [file] [log] [blame]
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
HostBinding,
Input,
OnDestroy,
Output
} from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { debounceTime, distinctUntilChanged, tap, filter } from 'rxjs/operators';
import { Monitor } from '../../../pojo/Monitor';
import { MonitorService } from '../../../service/monitor.service';
@Component({
selector: 'header-search',
template: `
<nz-input-group [nzPrefix]="iconTpl" [nzSuffix]="loadingTpl">
<ng-template #iconTpl>
<i nz-icon [nzType]="focus ? 'arrow-down' : 'search'"></i>
</ng-template>
<ng-template #loadingTpl>
<i *ngIf="loading" nz-icon nzType="loading"></i>
</ng-template>
<input
type="text"
nz-input
[(ngModel)]="q"
[nzAutocomplete]="auto"
(input)="search($event)"
(focus)="qFocus()"
(blur)="qBlur()"
[attr.placeholder]="'menu.search.placeholder' | i18n"
/>
</nz-input-group>
<nz-autocomplete nzBackfill="false" nzDefaultActiveFirstOption #auto>
<nz-auto-option *ngFor="let option of options" [nzValue]="option.id" [nzLabel]="option.name" (click)="onOptionSelect(option)">
<a>
{{ 'monitor.name' | i18n }} : {{ option.name }}
<span style="left:50% ; position: absolute;">{{ 'monitor.host' | i18n }} : {{ option.host }}</span>
<span style="right: 10px; position: absolute;"><i nz-icon nzType="arrow-right" nzTheme="outline"></i></span>
</a>
</nz-auto-option>
</nz-autocomplete>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeaderSearchComponent implements AfterViewInit, OnDestroy {
q = '';
qIpt: HTMLInputElement | null = null;
options: Monitor[] = [];
search$ = new BehaviorSubject('');
loading = false;
@HostBinding('class.alain-default__search-focus')
focus = false;
@HostBinding('class.alain-default__search-toggled')
searchToggled = false;
@Input()
set toggleChange(value: boolean) {
if (typeof value === 'undefined') {
return;
}
this.searchToggled = value;
this.focus = value;
if (value) {
setTimeout(() => this.qIpt!.focus());
}
}
@Output() readonly toggleChangeChange = new EventEmitter<boolean>();
constructor(
private router: Router,
private el: ElementRef<HTMLElement>,
private cdr: ChangeDetectorRef,
private monitorSvc: MonitorService
) {
this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
this.resetSearch();
});
}
ngAfterViewInit(): void {
this.qIpt = this.el.nativeElement.querySelector('.ant-input') as HTMLInputElement;
this.initOptions();
}
initOptions() {
this.search$
.pipe(
debounceTime(500),
distinctUntilChanged(),
tap({
complete: () => {
this.loading = true;
}
})
)
.subscribe(value => {
// Remote loading of search data
let searchMonitors$ = this.monitorSvc.searchMonitors(undefined, undefined, value, 9, 0, 10).subscribe(
message => {
this.loading = false;
searchMonitors$.unsubscribe();
if (message.code === 0) {
let page = message.data;
if (page.content != undefined) {
this.options = page.content;
} else {
this.options = [];
}
this.cdr.detectChanges();
} else {
console.warn(message.msg);
}
},
error => {
this.loading = false;
searchMonitors$.unsubscribe();
console.error(error.msg);
}
);
});
}
qFocus(): void {
this.focus = true;
}
qBlur(): void {
this.focus = false;
this.searchToggled = false;
this.options = [];
this.toggleChangeChange.emit(false);
}
search(ev: Event): void {
this.search$.next((ev.target as HTMLInputElement).value);
}
onOptionSelect(option: any) {
this.router.navigate([`/monitors/${option.id}`]);
this.resetSearch();
if (this.qIpt) {
this.qIpt.blur();
}
this.qBlur();
}
resetSearch() {
if (this.qIpt) {
this.qIpt!.value = '';
}
this.initOptions();
}
ngOnDestroy(): void {
this.search$.complete();
this.search$.unsubscribe();
}
}