From 52a0cde401aedb54389efaa35b0c4c3324a2473e Mon Sep 17 00:00:00 2001 From: "Maxence G. de Montauzan" Date: Thu, 12 Aug 2021 23:23:55 +0200 Subject: [PATCH] (front) Autocomplete search on dashboard with Datalist Create Elasticsearch service to search suggestions Send to page when choose a suggestion - bad way It's impossible to use Object with datalist So it's impossible to distinguish an album from an artist if they have the same name --- dashboard/src/app/app.module.ts | 2 + .../app/dashboard/dashboard.component.html | 19 ++++++++ .../src/app/dashboard/dashboard.component.ts | 22 +++++++++- dashboard/src/app/els.service.ts | 44 +++++++++++++++++++ dashboard/src/app/model/suggested.ts | 8 ++++ 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 dashboard/src/app/model/suggested.ts diff --git a/dashboard/src/app/app.module.ts b/dashboard/src/app/app.module.ts index 1f15372..2b66a11 100644 --- a/dashboard/src/app/app.module.ts +++ b/dashboard/src/app/app.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; +import { FormsModule } from '@angular/forms'; // <-- NgModel lives here import { AppComponent } from './app.component'; import { DashboardComponent } from './dashboard/dashboard.component'; @@ -26,6 +27,7 @@ import { AlbumsComponent } from './albums/albums.component'; imports: [ BrowserModule, HttpClientModule, + FormsModule, AppRoutingModule ], declarations: [ diff --git a/dashboard/src/app/dashboard/dashboard.component.html b/dashboard/src/app/dashboard/dashboard.component.html index 41d65c3..525f434 100644 --- a/dashboard/src/app/dashboard/dashboard.component.html +++ b/dashboard/src/app/dashboard/dashboard.component.html @@ -77,6 +77,25 @@ + +
diff --git a/dashboard/src/app/dashboard/dashboard.component.ts b/dashboard/src/app/dashboard/dashboard.component.ts index 8a4f328..3750c7b 100644 --- a/dashboard/src/app/dashboard/dashboard.component.ts +++ b/dashboard/src/app/dashboard/dashboard.component.ts @@ -1,10 +1,12 @@ import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; import { ElsService } from './../els.service'; import { Song } from './../model/song'; import { Bucket } from './../model/bucket'; import { Album } from './../model/album'; import { Artist } from './../model/artist'; +import { Suggested } from '../model/suggested'; @Component({ selector: 'app-dashboard', @@ -30,7 +32,10 @@ export class DashboardComponent implements OnInit { lastAddedAlbums: Bucket[] = []; albumArtists = []; - constructor(private elsService: ElsService) { } + searchTerm = '' + suggested : Suggested[] = [] + + constructor(private elsService: ElsService, private route: Router) { } ngOnInit(): void { this.elsService.getTime().then(result => { @@ -113,4 +118,19 @@ export class DashboardComponent implements OnInit { } }); } + + onSearchChange() { + this.elsService.getSuggest(this.searchTerm).subscribe(result => this.suggested = result); + } + + onSearchSelected($event) { + let selected = $event.target.value + // FIXME Not possible to get good element (just value) + // Need to use a plugin to do this correctly + this.suggested.forEach(element => { + if (element.name == selected) { + this.route.navigate(['/' + element.type + '/' + element.name]) + } + }); + } } diff --git a/dashboard/src/app/els.service.ts b/dashboard/src/app/els.service.ts index d130861..a08bd2d 100644 --- a/dashboard/src/app/els.service.ts +++ b/dashboard/src/app/els.service.ts @@ -8,6 +8,7 @@ import { Song } from './model/song'; import { Album } from './model/album'; import { Artist } from './model/artist'; import { Bucket } from './model/bucket'; +import { Suggested } from './model/suggested'; @Injectable() export class ElsService { @@ -15,6 +16,7 @@ export class ElsService { public static readonly SONG_INDEX_NAME = '/itunes-songs'; public static readonly ARTIST_INDEX_NAME = '/itunes-artists'; public static readonly ALBUM_INDEX_NAME = '/itunes-albums'; + public static readonly SUGGEST_INDEX_NAME = '/itunes-suggest'; protected static readonly ACTION_SEARCH = '/_search'; protected static readonly ACTION_COUNT = '/_count'; @@ -381,6 +383,34 @@ export class ElsService { ); } + getSuggest(text: string): Observable { + console.log('search sugget: ' + text); + return this.http + .post(this.elsUrl + ElsService.SUGGEST_INDEX_NAME + ElsService.ACTION_SEARCH, + JSON.stringify({ + '_source': ['album', 'artist'], + 'suggest': { + 'album-suggest': { + 'prefix': text, + 'completion': { + 'field': 'album_suggest' + } + }, + 'artist-suggest': { + 'prefix': text, + 'completion': { + 'field': 'artist_suggest' + } + } + } + }), {headers: this.headers}) + .pipe( + map(res => this.responseSuggesterToSuggested(res, 'album-suggest', 'artist-suggest')), + catchError(error => this.handleError(error, 'getSuggest(' + text + ')')) + ); + + } + /** Process a result to return just one result. * Used to get an album or an artist. * Take a name to put in console output if no result or more than one result. @@ -462,6 +492,20 @@ export class ElsService { return result; } + protected responseSuggesterToSuggested(res: any, ...suggestName: string[]): Suggested[] { + const result: Array = [] + suggestName.forEach(sname => { + res['suggest'][sname][0]['options'].forEach(option => { + let suggest = new Suggested() + // TODO If more than one key, raise exception + suggest.type = String(Object.keys(option['_source'])) + suggest.name = option['_source'][suggest.type] + result.push(suggest) + }); + }); + return result; + } + protected handleError(error: any, origin: string): Promise { console.error('An error occurred!'); console.error('Origin function: ', origin); diff --git a/dashboard/src/app/model/suggested.ts b/dashboard/src/app/model/suggested.ts new file mode 100644 index 0000000..1acfa78 --- /dev/null +++ b/dashboard/src/app/model/suggested.ts @@ -0,0 +1,8 @@ +export class Suggested { + name: string; + type: string; + + public toString() : string { + return `${this.name} (${this.type})`; + } +}