From 25828bb7894c7dd299bed536b1d02a6f2e41762e Mon Sep 17 00:00:00 2001 From: "Maxence G. de Montauzan" Date: Thu, 2 Feb 2023 01:43:58 +0100 Subject: [PATCH] (front) Service refactoring for sorting operations - Create an ElsArtistService to use common query - Move services in a subfolder Use a function to add sort filter --- dashboard/src/app/album/album.component.html | 2 +- dashboard/src/app/album/album.component.ts | 8 +- dashboard/src/app/albums/albums.component.ts | 2 +- dashboard/src/app/app.module.ts | 8 +- dashboard/src/app/artist/artist.component.ts | 21 ++- .../src/app/dashboard/dashboard.component.ts | 2 +- .../els-album.service.spec.ts | 0 .../{ => els-service}/els-album.service.ts | 11 +- .../els-service/els-artist.service.spec.ts | 16 +++ .../src/app/els-service/els-artist.service.ts | 121 +++++++++++++++++ .../els-sort.service.spec.ts | 0 .../app/{ => els-service}/els-sort.service.ts | 10 +- .../app/{ => els-service}/els.service.spec.ts | 0 .../src/app/{ => els-service}/els.service.ts | 123 ++++-------------- dashboard/src/app/genre/genre.component.ts | 2 +- .../src/app/to-sort/to-sort.component.html | 2 +- .../src/app/to-sort/to-sort.component.ts | 2 +- .../app/top-played/top-played.component.ts | 2 +- 18 files changed, 197 insertions(+), 135 deletions(-) rename dashboard/src/app/{ => els-service}/els-album.service.spec.ts (100%) rename dashboard/src/app/{ => els-service}/els-album.service.ts (90%) create mode 100644 dashboard/src/app/els-service/els-artist.service.spec.ts create mode 100644 dashboard/src/app/els-service/els-artist.service.ts rename dashboard/src/app/{ => els-service}/els-sort.service.spec.ts (100%) rename dashboard/src/app/{ => els-service}/els-sort.service.ts (95%) rename dashboard/src/app/{ => els-service}/els.service.spec.ts (100%) rename dashboard/src/app/{ => els-service}/els.service.ts (79%) diff --git a/dashboard/src/app/album/album.component.html b/dashboard/src/app/album/album.component.html index a7c9c53..03db68c 100644 --- a/dashboard/src/app/album/album.component.html +++ b/dashboard/src/app/album/album.component.html @@ -1,7 +1,7 @@

{{albumName}}

-
+
To sort filter applyed. Songs are filter on location.
Album folder: {{album['Location']}}
diff --git a/dashboard/src/app/album/album.component.ts b/dashboard/src/app/album/album.component.ts index c750fcc..7a359d6 100644 --- a/dashboard/src/app/album/album.component.ts +++ b/dashboard/src/app/album/album.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; -import { ElsService } from './../els.service'; +import { ElsService } from '../els-service/els.service'; import { Song } from './../model/song'; import { Album } from './../model/album'; import { SongTableComponent } from '../song-table/song-table.component'; @@ -18,7 +18,7 @@ export class AlbumComponent implements OnInit { albumName = ''; songs: Array = []; album: Album = new Album(); // If album not found, will be replaced by 'undefined' - toSort: boolean = false; // Show only song to sort + sortFilter: boolean = false; // Show only song to sort // Prevent useless data load + activate button in interface var moreDataAvailable = true; @@ -31,7 +31,7 @@ export class AlbumComponent implements OnInit { ngOnInit(): void { this.route.params.subscribe((params: Params) => this.albumName = params['name']); - this.route.queryParams.subscribe(params => { this.toSort = params.tosort ?? false; }); + this.route.queryParams.subscribe(params => { this.sortFilter = params.tosort ?? false; }); this.loadSongs(); @@ -49,7 +49,7 @@ export class AlbumComponent implements OnInit { } this.lockLoadData = true; - this.elsService.getAlbumSongs(this.albumName, this.songs.length, this.toSort).subscribe( + this.elsService.getAlbumSongs(this.albumName, this.songs.length, this.sortFilter).subscribe( data => { this.moreDataAvailable = data.length === ElsService.DEFAULT_SIZE; diff --git a/dashboard/src/app/albums/albums.component.ts b/dashboard/src/app/albums/albums.component.ts index 6c5f088..f10c20c 100644 --- a/dashboard/src/app/albums/albums.component.ts +++ b/dashboard/src/app/albums/albums.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { ElsAlbumService } from '../els-album.service'; +import { ElsAlbumService } from '../els-service/els-album.service'; import { Album } from '../model/album'; diff --git a/dashboard/src/app/app.module.ts b/dashboard/src/app/app.module.ts index ed9fbd0..c76632c 100644 --- a/dashboard/src/app/app.module.ts +++ b/dashboard/src/app/app.module.ts @@ -11,8 +11,8 @@ import { GenreComponent } from './genre/genre.component'; import { SongTableComponent } from './song-table/song-table.component'; import { TopPlayedComponent } from './top-played/top-played.component'; -import { ElsService } from './els.service'; -import { ElsAlbumService } from './els-album.service'; +import { ElsService } from './els-service/els.service'; +import { ElsAlbumService } from './els-service/els-album.service'; import { AppRoutingModule } from './app-routing.module'; @@ -25,6 +25,7 @@ import { AlbumsComponent } from './albums/albums.component'; import { ToSortComponent } from './to-sort/to-sort.component'; import {NgbModule} from '@ng-bootstrap/ng-bootstrap'; +import { ElsArtistService } from './els-service/els-artist.service'; @NgModule({ imports: [ @@ -52,7 +53,8 @@ import {NgbModule} from '@ng-bootstrap/ng-bootstrap'; ], providers: [ ElsService, - ElsAlbumService + ElsAlbumService, + ElsArtistService ], bootstrap: [ AppComponent ] }) diff --git a/dashboard/src/app/artist/artist.component.ts b/dashboard/src/app/artist/artist.component.ts index 58f2be7..9c3f53a 100644 --- a/dashboard/src/app/artist/artist.component.ts +++ b/dashboard/src/app/artist/artist.component.ts @@ -1,11 +1,11 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; -import { Location } from '@angular/common'; -import { ElsService } from './../els.service'; import { Song } from './../model/song'; import { Artist } from './../model/artist'; import { SongTableComponent } from '../song-table/song-table.component'; +import { ElsArtistService } from '../els-service/els-artist.service'; +import { ElsService } from '../els-service/els.service'; @Component({ selector: 'app-artist', @@ -25,19 +25,26 @@ export class ArtistComponent implements OnInit { artist: Artist = new Artist(); lockLoadData = false; countSong: number; + toSortFilter: boolean = false; // Show only song to sort constructor( - private elsService: ElsService, + private elsService: ElsArtistService, private route: ActivatedRoute, - private location: Location ) { } ngOnInit(): void { this.route.params.subscribe((params: Params) => this.artistName = params['name']); + this.route.queryParams.subscribe(params => { this.toSortFilter = params.tosort ?? false; }); this.elsService.getArtist(this.artistName).subscribe(data => this.artist = data); - this.elsService.getCountArtistSong(this.artistName).subscribe(data => this.countSong = data); + this.elsService.getCountArtistSong(this.artistName, this.toSortFilter).subscribe(data => { + this.countSong = data + this.artist['Track Count'] = this.countSong; + // TODO Async problem: some time, get updated data, some time no + // TODO Use only this value? + // TODO ==> Show each time if there are unsorted songs + }); this.loadSongs(); } @@ -54,9 +61,11 @@ export class ArtistComponent implements OnInit { } this.lockLoadData = true; - this.elsService.getArtistSongs(this.artistName, this.songs.length).subscribe( + this.elsService.getArtistSongs(this.artistName, this.songs.length, this.toSortFilter).subscribe( data => { this.moreDataAvailable = data.length === ElsService.DEFAULT_SIZE; + console.log(data.length) + console.log(this.moreDataAvailable) // Erase song array with result for first load, then add elements one by one // instead use concat => concat will sort table at each load, very consuming! and not user friendly diff --git a/dashboard/src/app/dashboard/dashboard.component.ts b/dashboard/src/app/dashboard/dashboard.component.ts index 41dcc87..16a0050 100644 --- a/dashboard/src/app/dashboard/dashboard.component.ts +++ b/dashboard/src/app/dashboard/dashboard.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; -import { ElsService } from './../els.service'; +import { ElsService } from '../els-service/els.service'; import { Song } from './../model/song'; import { Bucket } from './../model/bucket'; import { Suggested } from '../model/suggested'; diff --git a/dashboard/src/app/els-album.service.spec.ts b/dashboard/src/app/els-service/els-album.service.spec.ts similarity index 100% rename from dashboard/src/app/els-album.service.spec.ts rename to dashboard/src/app/els-service/els-album.service.spec.ts diff --git a/dashboard/src/app/els-album.service.ts b/dashboard/src/app/els-service/els-album.service.ts similarity index 90% rename from dashboard/src/app/els-album.service.ts rename to dashboard/src/app/els-service/els-album.service.ts index 9ba70a0..f4be022 100644 --- a/dashboard/src/app/els-album.service.ts +++ b/dashboard/src/app/els-service/els-album.service.ts @@ -1,12 +1,11 @@ import { Injectable } from '@angular/core'; -import { HttpClient, HttpHeaders } from '@angular/common/http' +import { HttpClient } from '@angular/common/http' import { Observable } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; -import { Album } from './model/album'; +import { Album } from './../model/album'; import { ElsService } from './els.service'; -import { ActivatedRoute } from '@angular/router'; @Injectable() export class ElsAlbumService extends ElsService { @@ -37,10 +36,8 @@ export class ElsAlbumService extends ElsService { 'size': 500 } - constructor( - protected http: HttpClient, - protected route: ActivatedRoute) { - super(http, route); + constructor(protected http: HttpClient) { + super(http); } getAlbums(query: any): Observable { diff --git a/dashboard/src/app/els-service/els-artist.service.spec.ts b/dashboard/src/app/els-service/els-artist.service.spec.ts new file mode 100644 index 0000000..debf2e5 --- /dev/null +++ b/dashboard/src/app/els-service/els-artist.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ElsArtistService } from './els-artist.service'; + +describe('ElsArtistService', () => { + let service: ElsArtistService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ElsArtistService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/dashboard/src/app/els-service/els-artist.service.ts b/dashboard/src/app/els-service/els-artist.service.ts new file mode 100644 index 0000000..3e36857 --- /dev/null +++ b/dashboard/src/app/els-service/els-artist.service.ts @@ -0,0 +1,121 @@ +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { Observable } from "rxjs"; +import { catchError, map } from "rxjs/operators"; +import { Artist } from "../model/artist"; +import { Song } from "../model/song"; +import { ElsService } from "./els.service"; + +@Injectable() +export class ElsArtistService extends ElsService { + constructor(protected http: HttpClient) { + super(http); + } + + private getQuerySongsWithArtistName( + artistName: string, + sortFilter: boolean = false, + size: number = 0, + from: number = 0 + ) { + let query = { + query: { + bool: { + should: [ + { match_phrase: { "Album Artist": artistName } }, + { match_phrase: { Artist: artistName } }, + ], + must_not: [], + }, + }, + }; + + if (sortFilter) { + console.log("ElsArtistService- TO SORT filter enabled"); + query = this.addSortFilterToQuery(query); + } + + if (size) { + query["size"] = size; + } + + if (from) { + query["from"] = from; + } + return query; + } + + public getArtist(artistName: string): Observable { + return this.http + .post( + this.elsUrl + ElsService.ARTIST_INDEX_NAME + ElsService.ACTION_SEARCH, + JSON.stringify({ + query: { + match_phrase: { Artist: artistName }, + }, + size: ElsService.DEFAULT_SIZE, + }), + { headers: this.headers } + ) + .pipe( + map((res) => this.responseToOneTypedResult(res, artistName)), + catchError((error) => + this.handleError(error, "getArtist(" + artistName + ")") + ) + ); + } + + public getArtistSongs( + artistName: string, + from: number = 0, + sortFilter = false + ): Observable { + console.info( + "getArtistSongs- Artist name: " + artistName + " - from: " + from + ); + + let query = this.getQuerySongsWithArtistName( + artistName, + sortFilter, + ElsService.DEFAULT_SIZE, + from + ); + + return this.http + .post( + this.elsUrl + ElsService.SONG_INDEX_NAME + ElsService.ACTION_SEARCH, + JSON.stringify(query), + { headers: this.headers } + ) + .pipe( + map((res) => this.responseToSongs(res)), + catchError((error) => + this.handleError( + error, + "getArtistSongs(" + artistName + "," + from + ")" + ) + ) + ); + } + + public getCountArtistSong( + artistName: string, + sortFilter = false + ): Observable { + console.log("artistname: " + artistName); + const query = this.getQuerySongsWithArtistName(artistName, sortFilter); + + return this.http + .post( + this.elsUrl + ElsService.SONG_INDEX_NAME + ElsService.ACTION_COUNT, + JSON.stringify(query), + { headers: this.headers } + ) + .pipe( + map((res) => res.count as number), + catchError((error) => + this.handleError(error, "getCountArtistSong" + artistName + ")") + ) + ); + } +} diff --git a/dashboard/src/app/els-sort.service.spec.ts b/dashboard/src/app/els-service/els-sort.service.spec.ts similarity index 100% rename from dashboard/src/app/els-sort.service.spec.ts rename to dashboard/src/app/els-service/els-sort.service.spec.ts diff --git a/dashboard/src/app/els-sort.service.ts b/dashboard/src/app/els-service/els-sort.service.ts similarity index 95% rename from dashboard/src/app/els-sort.service.ts rename to dashboard/src/app/els-service/els-sort.service.ts index 152110b..14001ed 100644 --- a/dashboard/src/app/els-sort.service.ts +++ b/dashboard/src/app/els-service/els-sort.service.ts @@ -4,19 +4,15 @@ import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; import { ElsService } from './els.service'; -import { Album } from './model/album'; -import { Bucket } from './model/bucket'; -import { Song } from './model/song'; +import { Album } from './../model/album'; @Injectable({ providedIn: 'root' }) export class ElsSortService extends ElsService { - constructor( - protected http: HttpClient, - protected route: ActivatedRoute) { - super(http, route); + constructor(protected http: HttpClient) { + super(http); } getTime(): Promise { diff --git a/dashboard/src/app/els.service.spec.ts b/dashboard/src/app/els-service/els.service.spec.ts similarity index 100% rename from dashboard/src/app/els.service.spec.ts rename to dashboard/src/app/els-service/els.service.spec.ts diff --git a/dashboard/src/app/els.service.ts b/dashboard/src/app/els-service/els.service.ts similarity index 79% rename from dashboard/src/app/els.service.ts rename to dashboard/src/app/els-service/els.service.ts index 1a8273c..ddef74a 100644 --- a/dashboard/src/app/els.service.ts +++ b/dashboard/src/app/els-service/els.service.ts @@ -1,15 +1,14 @@ -import { Injectable } from '@angular/core'; +import { Inject, Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http' import { Observable } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; -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'; -import { ActivatedRoute } from '@angular/router'; +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 { @@ -22,20 +21,11 @@ export class ElsService { protected static readonly ACTION_SEARCH = '/_search'; protected static readonly ACTION_COUNT = '/_count'; - protected elsUrl = 'http://localhost:9200'; + protected elsUrl = 'http://192.168.1.20:9200'; protected headers = new HttpHeaders({'Content-Type': 'application/json'}); - protected defaultLocation = "/F:/Musique" // TODO Use conf + protected defaultLocation = "/F:/Musique"; // TODO Use conf - constructor( - protected http: HttpClient, - protected route: ActivatedRoute) { } - - fetchToSortParam() { - const toSort = this.route.snapshot.queryParams['backend'] || 'defaultUrl'; - console.log('fetchToSortParam return ' + toSort) - return toSort; - // ? Retrieve to sort on Service or on each component and add a parameter for each methods? - } + constructor(protected http: HttpClient) { } getTime(): Promise { return this.http @@ -208,11 +198,7 @@ export class ElsService { if (toSortFilter) { console.log("getAlbumSongs- TO SORT filter enabled"); - query.query.bool.must_not.push({ - term: { - "Location.tree": this.defaultLocation, - }, - }); + query = this.addSortFilterToQuery(query) } return this.http @@ -246,31 +232,11 @@ export class ElsService { }), {headers: this.headers}) .pipe( map(res => this.responseToSongs(res)), - catchError(error => this.handleError(error, 'getAlbumSongs(' + genreName + ',' + from + ')')) + catchError(error => this.handleError(error, 'getGenreSongs(' + genreName + ',' + from + ')')) ); } - getArtistSongs(artistName: string, from: number = 0): Observable { - console.info('getArtistSongs- Artist name: ' + artistName + ' - from: ' + from); - return this.http - .post(this.elsUrl + ElsService.SONG_INDEX_NAME + ElsService.ACTION_SEARCH, - JSON.stringify({ - 'query': { - 'bool': { - 'should': [ - {'match_phrase' : { 'Album Artist' : artistName }}, - {'match_phrase' : { 'Artist' : artistName }} - ] - } - }, - 'size': ElsService.DEFAULT_SIZE, - 'from': from - }), {headers: this.headers}) - .pipe( - map(res => this.responseToSongs(res)), - catchError(error => this.handleError(error, 'getArtistSongs(' + artistName + ',' + from + ')')) - ); - } + getAlbum(albumName: string): Observable { // TODO Why this is used on album pages? @@ -289,21 +255,6 @@ export class ElsService { ); } - getArtist(artistName: string): Observable { - return this.http - .post(this.elsUrl + ElsService.ARTIST_INDEX_NAME + ElsService.ACTION_SEARCH, - JSON.stringify({ - 'query': { - 'match_phrase': { 'Artist': artistName } - }, - 'size': ElsService.DEFAULT_SIZE - }), {headers: this.headers}) - .pipe( - map(res => this.responseToOneTypedResult(res, artistName)), - catchError(error => this.handleError(error, 'getArtist(' + artistName + ')')) - ); - } - getGenres(ordering: string = 'desc'): Observable { return this.http .post(this.elsUrl + ElsService.SONG_INDEX_NAME + ElsService.ACTION_SEARCH, @@ -326,25 +277,6 @@ export class ElsService { ); } -// getGenreCount(): Observable { -// return this.http -// .post(this.elsUrl + 'song' + ElsService.ACTION_SEARCH, -// JSON.stringify({ -// 'aggs' : { -// 'genres' : { -// 'cardinality' : { -// 'field' : 'Genre.original', -// 'missing': 'N/A', -// } -// } -// }, -// 'size': 0 -// }), {headers: this.headers}) -// .pipe( -// map(res => res.aggregations.genres.value) -// ); -// } - getLastAddedAlbums(month: number): Observable { return this.http .post(this.elsUrl + ElsService.SONG_INDEX_NAME + ElsService.ACTION_SEARCH, @@ -406,26 +338,6 @@ export class ElsService { ); } - getCountArtistSong(artistName: string): Observable { - console.log('artistname: ' + artistName); - return this.http - .post(this.elsUrl + ElsService.SONG_INDEX_NAME + ElsService.ACTION_COUNT, - JSON.stringify({ - 'query': { - 'bool': { - 'should': [ - {'match_phrase' : { 'Album Artist' : artistName }}, - {'match_phrase' : { 'Artist' : artistName }} - ] - } - } - }), {headers: this.headers}) - .pipe( - map(res => res.count as number), - catchError(error => this.handleError(error, 'getCountArtistSong' + artistName + ')')) - ); - } - getSuggest(text: string): Observable { console.log('search sugget: ' + text); return this.http @@ -461,7 +373,7 @@ export class ElsService { * @param res Response to process * @param name The searched name - for console output */ - private responseToOneTypedResult(res: any, name: string): T { + protected responseToOneTypedResult(res: any, name: string): T { const hits = res.hits.hits; if (hits.length < 1) { @@ -556,4 +468,13 @@ export class ElsService { console.error(error); // for demo purposes only return Promise.reject(error.message || error); } + + protected addSortFilterToQuery(query) { + query.query.bool.must_not.push({ + term: { + "Location.tree": this.defaultLocation, + }, + }); + return query; + } } diff --git a/dashboard/src/app/genre/genre.component.ts b/dashboard/src/app/genre/genre.component.ts index 89631e7..55fdf3e 100644 --- a/dashboard/src/app/genre/genre.component.ts +++ b/dashboard/src/app/genre/genre.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; -import { ElsService } from '../els.service'; +import { ElsService } from '../els-service/els.service'; import { SongTableComponent } from '../song-table/song-table.component'; import { Song } from '../model/song'; diff --git a/dashboard/src/app/to-sort/to-sort.component.html b/dashboard/src/app/to-sort/to-sort.component.html index 4dc2c79..ffd428a 100644 --- a/dashboard/src/app/to-sort/to-sort.component.html +++ b/dashboard/src/app/to-sort/to-sort.component.html @@ -100,7 +100,7 @@ - {{album['Album Artist']}}  + {{album['Album Artist']}}  diff --git a/dashboard/src/app/to-sort/to-sort.component.ts b/dashboard/src/app/to-sort/to-sort.component.ts index eccdd02..75deab3 100644 --- a/dashboard/src/app/to-sort/to-sort.component.ts +++ b/dashboard/src/app/to-sort/to-sort.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { ElsSortService } from '../els-sort.service'; +import { ElsSortService } from '../els-service/els-sort.service'; import { Bucket } from '../model/bucket'; import { Utils } from '../utils'; diff --git a/dashboard/src/app/top-played/top-played.component.ts b/dashboard/src/app/top-played/top-played.component.ts index 2cdf912..64eb2ad 100644 --- a/dashboard/src/app/top-played/top-played.component.ts +++ b/dashboard/src/app/top-played/top-played.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit } from '@angular/core'; -import { ElsService } from '../els.service'; +import { ElsService } from '../els-service/els.service'; import { Album } from '../model/album'; import { Artist } from '../model/artist';