🚸 Added SongList component for consistent song visuals everywhere.

This commit is contained in:
corner 2019-09-28 17:35:25 +02:00
parent 29d8d978aa
commit 91a0cdfd57
17 changed files with 117 additions and 66 deletions

View File

@ -3,15 +3,13 @@ import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './components/home/home.component';
import { ArtistsComponent } from './components/artists/artists.component';
import { AlbumsComponent } from './components/albums/albums.component';
import { SongComponent } from './components/song/song.component';
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'artists/:id', component: ArtistsComponent },
{ path: 'artists', component: ArtistsComponent },
{ path: 'albums/:id', component: AlbumsComponent },
{ path: 'albums', component: AlbumsComponent },
{ path: 'songs', component: SongComponent }
{ path: 'albums', component: AlbumsComponent }
];
@NgModule({

View File

@ -8,19 +8,19 @@ import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './components/home/home.component';
import { SongComponent } from './components/song/song.component';
import { ArtistsComponent } from './components/artists/artists.component';
import { AlbumsComponent } from './components/albums/albums.component';
import { ControlsComponent } from './components/controls/controls.component';
import { SonglistComponent } from './components/songlist/songlist.component';
@NgModule({
declarations: [
AppComponent,
HomeComponent,
SongComponent,
ArtistsComponent,
AlbumsComponent,
ControlsComponent
ControlsComponent,
SonglistComponent
],
imports: [
BrowserModule,

View File

@ -32,8 +32,9 @@ export class Song {
return new Album(await this.data.getAlbum(this.album));
}
async getDuration() {
return await this.data.getDuration(this.path);
async getDuration(): Promise<number> {
const apiData = await this.data.getDuration(this.path);
return apiData.data.result;
}
}

View File

@ -10,26 +10,16 @@
<ng-template #artistInfo>
<div *ngIf="( artistData | async ) as data">
<h2>{{ artistData.name }}'s profile</h2>
<h1>{{ data.name }}'s profile</h1>
<hr>
<h4>{{ artistData.name }}'s songs</h4>
<h4>{{ data.name }}'s albums</h4>
<ul>
<li *ngFor="let album of data.albums">
{{ album }}
<li *ngFor="let song of songs">
{{ song.name }}
</li>
</ul>
<h4>{{ data.name }}'s songs</h4>
<ul>
<li *ngFor="let song of data.songs">
{{ song }}
</li>
</ul>
{{ data | json}}
</div>
</ng-template>

View File

@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { ApiService } from 'src/app/services/api.service';
import { Artist, Song } from '../../classes/entities';
@Component({
selector: 'app-artists',
@ -9,8 +10,9 @@ import { ApiService } from 'src/app/services/api.service';
})
export class ArtistsComponent implements OnInit {
artistData;
artists;
artistData: Artist;
artists: Promise<Array<Artist>>;
songs: Array<Song>;
constructor(
private api: ApiService,
@ -25,7 +27,10 @@ export class ArtistsComponent implements OnInit {
if (params.has('id')) {
// ... then get artist data ...
this.artistData = this.api.getArtist(Number(params.get('id')));
this.api.getArtist(Number(params.get('id'))).then(async res => {
this.artistData = res;
this.songs = await this.api.getSong(res.songs.join());
});
} else {

View File

@ -17,8 +17,9 @@
<span class="duration">{{ duration > 0 ? audio.formatTime(duration) : '00:00' }}</span>
</div>
<span class="volume">
<div class="volume">
<fa-icon [icon]="audio.player.volume === 0 ? faVolumeMute : ( audio.player.volume > 0.5 ? faVolumeUp : faVolumeDown )"></fa-icon>
<input min="0" max="1" step="0.05" [(ngModel)]="audio.player.volume" type="range" class="form-control-range" id="volume-range">
</span>
</div>
</div>

View File

@ -3,7 +3,7 @@
padding: 18px;
line-height: 1.5em;
display: grid;
grid-template-columns: 25% 10% 55% 10%
grid-template-columns: 25% 5% 55% 15%
}
.form-control-range {
display: inline-block;
@ -18,6 +18,16 @@ div.time {
}
}
div.volume {
display: grid;
grid-template-columns: auto auto;
text-align: center;
input {
width: 90%;
}
}
figure {
margin: 0;

View File

@ -39,7 +39,7 @@ export class ControlsComponent implements OnInit {
this.currentSong = await this.api.getSong(id);
this.currentArtist = await this.currentSong.getArtist();
this.currentAlbum = await this.currentSong.getAlbum();
this.duration = (await this.currentSong.getDuration()).data.result;
this.duration = await this.currentSong.getDuration();
});
}

View File

@ -1,3 +1 @@
<div *ngIf="songs && artists">
<p *ngFor="let song of songs; let i=index" (click)="audio.setSong(song)">{{ song.name }} by <span *ngIf="artists[i]">{{ artists[i].name }}</span></p>
</div>
<app-songlist *ngIf="( songs | async ) as songs" [songs]="songs"></app-songlist>

View File

@ -10,7 +10,7 @@ import { ApiService } from 'src/app/services/api.service';
})
export class HomeComponent implements OnInit {
songs: Song[];
songs: Promise<Song[]>;
artists: Artist[] = [];
constructor(
@ -21,12 +21,7 @@ export class HomeComponent implements OnInit {
ngOnInit() {
// Load the first song from the API
// Removing the async / await from the .then() callback will load the artists async from the songs.
this.api.getSong('all').then(async res => {
this.songs = res;
await res.forEach(async (song: Song) => {
this.artists.push(await song.getArtist());
});
});
this.songs = this.api.getSong('all');
}
}

View File

@ -1 +0,0 @@
<p>song works!</p>

View File

@ -1,15 +0,0 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-song',
templateUrl: './song.component.html',
styleUrls: ['./song.component.scss']
})
export class SongComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

View File

@ -0,0 +1,23 @@
<table class="table">
<thead>
<th scope="col">#</th>
<th scope="col"></th>
<th scope="col">Song name</th>
<th scope="col">Artist name</th>
<th scope="col">Album name</th>
<th scope="col">Duration</th>
</thead>
<tbody *ngIf="songsInfo">
<tr *ngFor="let song of songsInfo; let i = index">
<th scope="row">{{ i + 1 }}</th>
<th><fa-icon (click)="audio.setSong(songs[i])" [icon]="faPlay"></fa-icon></th>
<td>{{ song.name }}</td>
<td *ngIf="song.artistInfo">{{ song.artistInfo.name }}</td>
<td *ngIf="song.albumInfo">{{ song.albumInfo.name }}</td>
<td *ngIf="song.duration">{{ audio.formatTime(song.duration) }}</td>
</tr>
</tbody>
</table>

View File

@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SongComponent } from './song.component';
import { SonglistComponent } from './songlist.component';
describe('SongComponent', () => {
let component: SongComponent;
let fixture: ComponentFixture<SongComponent>;
describe('SonglistComponent', () => {
let component: SonglistComponent;
let fixture: ComponentFixture<SonglistComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SongComponent ]
declarations: [ SonglistComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SongComponent);
fixture = TestBed.createComponent(SonglistComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -0,0 +1,46 @@
import { Component, OnInit, Input } from '@angular/core';
import { Song, Artist, Album } from '../../classes/entities';
import { faPlay } from '@fortawesome/free-solid-svg-icons';
import { AudioService } from 'src/app/services/audio.service';
@Component({
selector: 'app-songlist',
templateUrl: './songlist.component.html',
styleUrls: ['./songlist.component.scss']
})
export class SonglistComponent implements OnInit {
@Input() songs: Song[];
songsInfo = [];
// ? fontAwesome imports
faPlay = faPlay;
constructor(public audio: AudioService) { }
ngOnInit() {
this.songs.forEach(song => {
const index = this.songsInfo.push({}) - 1;
const result = {
...song,
artistInfo: null as Artist,
albumInfo: null as Album,
duration: null as number
};
song.getArtist().then((artist: Artist) => {
result.artistInfo = artist;
song.getAlbum().then((album: Album) => {
result.albumInfo = album;
song.getDuration().then((duration: number) => {
result.duration = duration;
this.songsInfo[index] = result;
});
});
});
});
}
}

View File

@ -78,7 +78,7 @@ export class AudioService {
/**
* The setSong function set the song for the player.
* @param id The id of the song that needs to be played
* @param song The song object
*/
setSong(song: Song) {
this.player.src = this.data.apiUrl + '/play/' + song.path;