Album + slow service + other

This commit is contained in:
2017-05-04 18:41:55 +02:00
parent fe9638bcb5
commit 302afb6675
9 changed files with 175 additions and 46 deletions

View File

@@ -1,4 +1,4 @@
POST http://localhost:9200/itunessongs/_search
POST http://localhost:9200/itunessongs/album/_search
content-type: application/json
User-Agent: vscode-restclient
@@ -6,7 +6,7 @@ User-Agent: vscode-restclient
"query": {
"match" : {
"Album" : {
"query": "Our Love To Admire",
"query": "Crystal Castles",
"operator" : "and"
}
}
@@ -14,20 +14,20 @@ User-Agent: vscode-restclient
"size": 20
}
POST http://localhost:9200/itunessongs/_search
POST http://localhost:9200/itunessongs/song/_search
content-type: application/json
User-Agent: vscode-restclient
{
"query": {
"match_phrase" : {
"Album" : "Our Love"
"Album" : "Crystal Castles"
}
},
"size": 20
}
POST http://localhost:9200/itunessongs/_search
POST http://localhost:9200/itunessongs/song/_search
content-type: application/json
User-Agent: vscode-restclient
@@ -35,8 +35,27 @@ User-Agent: vscode-restclient
"query": {
"bool": {
"must": [
{"match_phrase" : { "Album" : "Our Love" }},
{"match_phrase" : { "Artist" : "Caribou." }}
{"match_phrase" : { "Album" : "Crystal Castles" }},
{"match_phrase" : { "Artist" : "Crystal Castles" }}
]
}
},
"size": 20
}
POST http://localhost:9200/itunessongs/song/_search
content-type: application/json
User-Agent: vscode-restclient
{
"query": {
"bool": {
"must": {
"match_phrase" : { "Album" : "Crystal Castles" }
},
"should" : [
{"match_phrase" : { "Artist" : "Crystal Castles" }},
{"match_phrase" : { "Album Artist" : "Crystal Castles" }}
]
}
},

View File

@@ -1,7 +1,38 @@
<h1>{{albumName}}</h1>
<ul class="heroes">
<div class="well">
<h3>Debug Zone</h3>
Returned song: {{songs.length}}<br />
Theorical number song: {{ album ? album['Track Count'] : "" }}
<span *ngIf="album && (songs.length == album['Track Count'])" class="glyphicon glyphicon-ok" style="color:green"></span>
<span *ngIf="album && (songs.length != album['Track Count'])" class="glyphicon glyphicon-remove" style="color:red"></span>
</div>
<!--<ul class="heroes">
<li *ngFor="let song of songs | sortBy : 'Track Number'" >
{{("0" + song['Track Number']).slice(-2)}}. {{song.Name}} ({{song.Artist}})
{{("0" + song['Track Number']).slice(-2)}}. {{song.Name}} ({{song.Artist}}) [{{song.Album}}]
</li>
</ul>
</ul>-->
<table class="table table-striped">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Artist</th>
<th>Album</th>
<th>Album Artist</th>
<th>Play Count</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let song of songs | sortBy : 'Track Number'">
<td>{{song['Track Number'] ? (("0" + song['Track Number']).slice(-2)) : "--"}}</td>
<td [title]="song.Name">{{song.Name}}</td>
<td [title]="song.Artist"><a [routerLink]="['/artist', song.Artist]">{{song.Artist}}</a></td>
<td [title]="song.Album"><a [routerLink]="['/album', song.Album]">{{song.Album}}</a></td>
<td [title]="song.Album">{{song['Album Artist']}}</td>
<td [title]="song['Play Count']">{{song['Play Count']}}</td>
</tr>
</tbody>
</table>

View File

@@ -4,6 +4,7 @@ import { Location } from '@angular/common'
import { ElsService } from './els.service'
import { Song } from './object/song';
import { Album } from './object/album';
@Component({
selector: 'album-component',
@@ -22,14 +23,17 @@ export class AlbumComponent implements OnInit {
songs: Array<Song> = [];
album: Album = new Album(); // If album not found, will be replaced by 'undefined'
ngOnInit(): void {
this.route.params
.subscribe((params: Params) => this.albumName = params['name']);
this.elsService.getAlbumSongs(this.albumName).subscribe(
data => {
this.songs = data;
}
);
this.elsService.getAlbum(this.albumName).subscribe(data => {
this.album = data;
console.log(this.album);
});
this.elsService.getAlbumSongs(this.albumName).subscribe(data => this.songs = data);
}
}

View File

@@ -13,7 +13,10 @@
<span class="glyphicon glyphicon-time stats_icon"></span>
</div>
<div class="col-xs-9 text-right">
<div class="huge"><h3>{{totalTimeSt}}</h3></div>
<div>
<h3 *ngIf="!totalTimeSt"><span class="glyphicon glyphicon-refresh loading"></span></h3>
<h3 *ngIf="totalTimeSt">{{totalTimeSt}}</h3>
</div>
<div><br>Total time</div>
</div>
</div>
@@ -28,7 +31,10 @@
<span class="glyphicon glyphicon-hdd stats_icon"></span>
</div>
<div class="col-xs-9 text-right">
<div class="huge"><h3>{{totalSizeSt}}</h3></div>
<div>
<h3 *ngIf="!totalSizeSt"><span class="glyphicon glyphicon-refresh loading"></span></h3>
<h3 *ngIf="totalSizeSt">{{totalSizeSt}}</h3>
</div>
<div><br>Total size</div>
</div>
</div>
@@ -43,7 +49,10 @@
<span class="glyphicon glyphicon-play stats_icon"></span>
</div>
<div class="col-xs-9 text-right">
<div class="huge"><h3>{{trackCountSong}}</h3></div>
<div>
<h3 *ngIf="!trackCountSong"><span class="glyphicon glyphicon-refresh loading"></span></h3>
<h3 *ngIf="trackCountSong">{{trackCountSong}}</h3>
</div>
<div><br>Total Songs</div>
</div>
</div>
@@ -54,21 +63,21 @@
<h3>Top Played Songs</h3>
<table class="table table-striped">
<thead>
<tr>
<th>Track Name</th>
<th>Artist</th>
<th>Album</th>
<th>Play Count</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let song of mostPlayedSongs">
<td [title]="song.Name">{{song.Name}}</td>
<td [title]="song.Artist"><a [routerLink]="['/artist', song.Artist]">{{song.Artist}}</a></td>
<td [title]="song.Album"><a [routerLink]="['/album', song.Album]">{{song.Album}}</a></td>
<td [title]="song['Play Count']">{{song['Play Count']}}</td>
</tr>
</tbody>
</table>
<thead>
<tr>
<th>Track Name</th>
<th>Artist</th>
<th>Album</th>
<th>Play Count</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let song of mostPlayedSongs">
<td [title]="song.Name">{{song.Name}}</td>
<td [title]="song.Artist"><a [routerLink]="['/artist', song.Artist]">{{song.Artist}}</a></td>
<td [title]="song.Album"><a [routerLink]="['/album', song.Album]">{{song.Album}}</a></td>
<td [title]="song['Play Count']">{{song['Play Count']}}</td>
</tr>
</tbody>
</table>
</div>

View File

@@ -35,11 +35,11 @@ export class DashboardComponent implements OnInit {
this.totalSizeSt = this.convertSizeToString(result);
});
this.elsService.getTrackCount("song")
this.elsService.getCount("song")
.then(result => this.trackCountSong = result);
this.elsService.getTrackCount("artist")
this.elsService.getCount("artist")
.then(result => this.trackCountArtist = result);
this.elsService.getTrackCount("album")
this.elsService.getCount("album")
.then(result => this.trackCountAlbum = result);
this.elsService.getMostPlayedTrack().subscribe(

View File

@@ -1,13 +1,13 @@
import { Injectable } from '@angular/core';
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import { Song } from './object/song';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/toPromise';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { Song } from './object/song';
import { Album } from './object/album';
@Injectable()
export class ElsService {
private elsUrl = 'http://localhost:9200/itunessongs/';
@@ -22,6 +22,12 @@ export class ElsService {
.catch(this.handleError);
}
getTimeSlowly(): Promise<number> {
return new Promise(resolve => {
setTimeout(() => resolve(this.getTime()), 2000);
});
}
getSize(): Promise<number> {
return this.http.post(this.elsUrl + "_search", JSON.stringify({aggs:{sum_time:{sum:{field:"Size"}}},"size":0}), {headers: this.headers})
.toPromise()
@@ -29,15 +35,28 @@ export class ElsService {
.catch(this.handleError);
}
getTrackCount(type: string): Promise<number> {
getSizeSlowly(): Promise<number> {
return new Promise(resolve => {
setTimeout(() => resolve(this.getSize()), 2000);
});
}
getCount(type: string): Promise<number> {
return this.http.get(this.elsUrl + type + "/_count")
.toPromise()
.then(res => res.json().count as number)
.catch(this.handleError);
}
getTrackCountSlowly(type: string): Promise<number> {
return new Promise(resolve => {
setTimeout(() => resolve(this.getCount(type)), 2000);
});
}
getMostPlayedTrack(): Observable<Song[]> {
// Thank to http://chariotsolutions.com/blog/post/angular2-observables-http-separating-services-components/
// for the map part
// Could be shorter but I think it's more readable like this.
return this.http
@@ -67,7 +86,7 @@ export class ElsService {
getAlbumSongs(albumName: string): Observable<Song[]> {
return this.http
.post(this.elsUrl + "song/_search",
JSON.stringify({"query":{"match_phrase":{"Album":albumName}},"size": 20}), // TODO Dynamic size
JSON.stringify({"query":{"match_phrase":{"Album":albumName}},"size": 50}), // TODO Dynamic size
{headers: this.headers})
.map(res => {
return res.json().hits.hits;
@@ -81,6 +100,26 @@ export class ElsService {
});
}
getAlbum(albumName: string): Observable<Album> {
return this.http
.post(this.elsUrl + "album/_search",
JSON.stringify({"query":{"match_phrase":{"Album":albumName}},"size": 50}), // TODO Dynamic size
{headers: this.headers})
.map(res => {
return res.json().hits.hits;
})
.map((hits: Array<any>) => {
if (hits.length < 1) {
console.info('No album "' + albumName + '" found.');
return undefined;
}
if (hits.length > 1) {
console.error('More than one album "' + albumName + '" found, return the first.');
}
return hits[0]._source;
});
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);

View File

@@ -0,0 +1,12 @@
export class Album {
Name: string;
Album: string;
Artist: Array<string>;
Rating: number;
Genre: Array<string>;
"Track Count": number;
"Album Rating": number;
"Persistent ID": string;
"Album Rating Computed": boolean;
"Play Count": number;
}

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>Angular QuickStart</title>
<title>Music Dashboard</title>
<base href="/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@@ -13,6 +13,10 @@
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('main.js').catch(function(err){ console.error(err); });

View File

@@ -20,6 +20,17 @@ body, input[text], button {
font-family: Cambria, Georgia;
}
.loading {
-animation: spin 1.5s infinite linear;
-webkit-animation: spin2 1.5s infinite linear;
}
@-webkit-keyframes spin2 {
from { -webkit-transform: rotate(0deg);}
to { -webkit-transform: rotate(360deg);}
}
/* . . . */
/* everywhere else */
* {