Extract table

Problem on sortable
This commit is contained in:
2017-10-19 00:24:47 +02:00
parent ae76f916ae
commit b420f32838
11 changed files with 280 additions and 258 deletions

View File

@@ -1,37 +0,0 @@
/* Thank to https://codyhouse.co/gem/back-to-top/ */
.btn-top {
display: inline-block;
height: 40px;
width: 40px;
position: fixed;
bottom: 20px;
right: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
/* image replacement properties */
/*overflow: hidden;*/
/*text-indent: 100%;*/
/*white-space: nowrap;*/
/*background: rgba(232, 98, 86, 0.8);*/
/*background: #ff9000;*/
visibility: hidden;
opacity: 0;
-webkit-transition: opacity .3s 0s, visibility 0s .3s;
-moz-transition: opacity .3s 0s, visibility 0s .3s;
transition: opacity .3s 0s, visibility 0s .3s;
}
.btn-top.btn-top-is-visible, .no-touch .btn-top:hover {
-webkit-transition: opacity .3s 0s, visibility 0s 0s;
-moz-transition: opacity .3s 0s, visibility 0s 0s;
transition: opacity .3s 0s, visibility 0s 0s;
}
.btn-top.btn-top-is-visible {
/* the button becomes visible */
visibility: visible;
opacity: 1;
}
.btn-sort {
bottom: 20px;
right: 70px;
}

View File

@@ -84,38 +84,9 @@
</div> </div>
</div> </div>
<table class="table table-striped" (window:scroll)="onScroll($event)"> <app-song-table [songs]=songs (atBottom)=loadSongs()></app-song-table>
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Artist</th>
<th>Album</th>
<th>Album Artist</th>
<th>Play Count</th>
<th>Genre</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>{{song.Name}}</td>
<td><a [routerLink]="['/artist', song.Artist]">{{song.Artist}}</a></td>
<td><a [routerLink]="['/album', song.Album]">{{song.Album}}</a></td>
<td>{{song['Album Artist']}}</td>
<td>{{song['Play Count']}}</td>
<td><a [routerLink]="['/genre', song.Genre]">{{song.Genre}}</a></td>
</tr>
</tbody>
</table>
<button type="button" *ngIf="moreDataAvailable" class="btn btn-default" aria-label="More" (click)="loadSongs()"> <button type="button" *ngIf="moreDataAvailable" class="btn btn-default" aria-label="More" (click)="loadSongs()">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> More... <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> More...
</button> </button>
<!-- Go to Top Button-->
<button type="button" class="btn btn-warning btn-top" [class.btn-top-is-visible]="atBottom"
aria-label="Top" (click)="scrollTop()">
<span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span>
</button>
</div> </div>

View File

@@ -16,8 +16,7 @@ export class AlbumComponent implements OnInit {
albumName = ''; albumName = '';
songs: Array<Song> = []; songs: Array<Song> = [];
album: Album = new Album(); // If album not found, will be replaced by 'undefined' album: Album = new Album(); // If album not found, will be replaced by 'undefined'
moreDataAvailable = false; moreDataAvailable = true;
atBottom = false;
constructor( constructor(
private elsService: ElsService, private elsService: ElsService,
@@ -35,6 +34,10 @@ export class AlbumComponent implements OnInit {
} }
loadSongs(): void { loadSongs(): void {
if (!this.moreDataAvailable) {
return;
}
this.elsService.getAlbumSongs(this.albumName, this.songs.length).subscribe( this.elsService.getAlbumSongs(this.albumName, this.songs.length).subscribe(
data => { data => {
this.moreDataAvailable = data.length === ElsService.DEFAULT_SIZE; this.moreDataAvailable = data.length === ElsService.DEFAULT_SIZE;
@@ -51,30 +54,4 @@ export class AlbumComponent implements OnInit {
} }
); );
} }
scrollTop(): void {
window.scrollTo(0, 0);
}
/**
* Handle scroll:
* - load data if at bottom of screen (if needed)
* - hide/show "go to top" button
*
* @param event scroll event
*/
onScroll(event: any) {
if (this.moreDataAvailable &&
(window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
this.loadSongs();
}
if (window.scrollY > window.innerHeight) {
this.atBottom = true;
}
if (window.scrollY === 0) {
this.atBottom = false;
}
}
} }

View File

@@ -7,6 +7,7 @@ import { DashboardComponent } from './dashboard.component';
import { AlbumComponent } from './album/album.component'; import { AlbumComponent } from './album/album.component';
import { ArtistComponent } from './artist/artist.component'; import { ArtistComponent } from './artist/artist.component';
import { GenreComponent } from './genre/genre.component'; import { GenreComponent } from './genre/genre.component';
import { SongTableComponent } from './song-table/song-table.component';
import { ElsService } from './els.service'; import { ElsService } from './els.service';
@@ -28,6 +29,7 @@ import { SortByPipe } from './sort-by.pipe';
AlbumComponent, AlbumComponent,
ArtistComponent, ArtistComponent,
GenreComponent, GenreComponent,
SongTableComponent,
ConvertMsPipe, ConvertMsPipe,
ConvertMoreExactPipe, ConvertMoreExactPipe,
SortByPipe SortByPipe

File diff suppressed because one or more lines are too long

View File

@@ -85,64 +85,9 @@
</div> </div>
</div> </div>
<table class="table table-striped" (window:scroll)="onScroll($event)"> <app-song-table [songs]=songs [sortable]=sortable (atBottom)=loadSongs()></app-song-table>
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Album</th>
<th>Year</th>
<th>Artist</th>
<th>Album Artist</th>
<th>Play Count</th>
<th>Genre</th>
<th>Bit Rate</th>
<th>Rating</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let song of songs | sortBy : 'Year':'Album':'Track Number'">
<td>{{song['Track Number'] ? (("0" + song['Track Number']).slice(-2)) : "--"}}</td>
<td>{{song.Name}}</td>
<td><a [routerLink]="['/album', song.Album]">{{song.Album}}</a></td>
<td>{{song.Year}}</td>
<td><a [routerLink]="['/artist', song.Artist]">{{song.Artist}}</a></td>
<td>{{song['Album Artist'] ? song['Album Artist'] : "-" }}</td>
<td>{{song['Play Count']}}</td>
<td><a [routerLink]="['/genre', song.Genre]">{{song.Genre}}</a></td>
<td [title]="song['Bit Rate']">
<span [class]="'signal signal-' + roundBitRate(song['Bit Rate'])"></span>
</td>
<td *ngIf="!song['Rating Computed']" [title]="'Rating: ' + song.Rating" class="star">
<span *ngIf="song.Rating >= 20" class="glyphicon glyphicon-star"></span>
<span *ngIf="song.Rating >= 40" class="glyphicon glyphicon-star"></span>
<span *ngIf="song.Rating >= 60" class="glyphicon glyphicon-star"></span>
<span *ngIf="song.Rating >= 80" class="glyphicon glyphicon-star"></span>
<span *ngIf="song.Rating >= 100" class="glyphicon glyphicon-star"></span>
</td>
<td *ngIf="song['Rating Computed']" [title]="'Computed Rating: ' + song.Rating" class="star">
<span *ngIf="song.Rating >= 20" class="glyphicon glyphicon-star-empty"></span>
<span *ngIf="song.Rating >= 40" class="glyphicon glyphicon-star-empty"></span>
<span *ngIf="song.Rating >= 60" class="glyphicon glyphicon-star-empty"></span>
<span *ngIf="song.Rating >= 80" class="glyphicon glyphicon-star-empty"></span>
<span *ngIf="song.Rating >= 100" class="glyphicon glyphicon-star-empty"></span>
</td>
<td *ngIf="song.Loved" class="loved" ><span class="glyphicon glyphicon-heart heart"></span></td>
</tr>
</tbody>
</table>
<button type="button" *ngIf="moreDataAvailable" class="btn btn-default" aria-label="More" (click)="loadSongs()"> <button type="button" *ngIf="moreDataAvailable" class="btn btn-default" aria-label="More" (click)="loadSongs()">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> More... <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> More...
</button> </button>
<!-- Go to Top Button-->
<button type="button" class="btn btn-warning btn-top" [class.btn-top-is-visible]="atBottom"
aria-label="Top" (click)="scrollTop()" title="Go back to Top!">
<span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span>
</button>
<button type="button" class="btn btn-primary btn-top btn-sort" [class.btn-top-is-visible]="sortable"
aria-label="Top" (click)="sort()" title="Sort by Album & Track Number">
<span class="glyphicon glyphicon-sort-by-attributes" aria-hidden="true"></span>
</button>
</div> </div>

View File

@@ -19,8 +19,7 @@ export class ArtistComponent implements OnInit {
songs: Array<Song> = []; songs: Array<Song> = [];
artist: Artist = new Artist(); artist: Artist = new Artist();
// To activate button in interface var // To activate button in interface var
moreDataAvailable = false; moreDataAvailable = true;
atBottom = false;
sortable = false; sortable = false;
lockLoadData = false; lockLoadData = false;
@@ -45,6 +44,10 @@ export class ArtistComponent implements OnInit {
return; return;
} }
if (!this.moreDataAvailable) {
return;
}
this.lockLoadData = true; this.lockLoadData = true;
this.elsService.getArtistSongs(this.artistName, this.songs.length).subscribe( this.elsService.getArtistSongs(this.artistName, this.songs.length).subscribe(
data => { data => {
@@ -65,39 +68,4 @@ export class ArtistComponent implements OnInit {
} }
); );
} }
scrollTop(): void {
window.scrollTo(0, 0);
}
/**
* Handle scroll:
* - load data if at bottom of screen (if needed)
* - hide/show "go to top" button
*
* @param event scroll event
*/
onScroll(event: any) {
if (this.moreDataAvailable &&
(window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
this.loadSongs();
}
if (window.scrollY > window.innerHeight) {
this.atBottom = true;
}
if (window.scrollY === 0) {
this.atBottom = false;
}
}
sort(): void {
this.songs = new SortByPipe().transform(this.songs, 'Year', 'Album', 'Track Number', 'Play Count');
this.sortable = false;
}
roundBitRate(bitRate: number) {
return Math.round(bitRate / 64);
}
} }

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,64 @@
<table class="table table-striped" (window:scroll)="onScroll($event)">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Album</th>
<th>Year</th>
<th>Artist</th>
<th>Album Artist</th>
<th>Play Count</th>
<th>Genre</th>
<th>Bit Rate</th>
<th>Rating</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let song of songs | sortBy : 'Year':'Album':'Track Number'">
<td>{{song['Track Number'] ? (("0" + song['Track Number']).slice(-2)) : "--"}}</td>
<td>{{song.Name}}</td>
<td>
<a [routerLink]="['/album', song.Album]">{{song.Album}}</a>
</td>
<td>{{song.Year}}</td>
<td>
<a [routerLink]="['/artist', song.Artist]">{{song.Artist}}</a>
</td>
<td>{{song['Album Artist'] ? song['Album Artist'] : "-" }}</td>
<td>{{song['Play Count']}}</td>
<td>
<a [routerLink]="['/genre', song.Genre]">{{song.Genre}}</a>
</td>
<td [title]="song['Bit Rate']">
<span [class]="'signal signal-' + roundBitRate(song['Bit Rate'])"></span>
</td>
<td *ngIf="!song['Rating Computed']" [title]="'Rating: ' + song.Rating" class="star">
<span *ngIf="song.Rating >= 20" class="glyphicon glyphicon-star"></span>
<span *ngIf="song.Rating >= 40" class="glyphicon glyphicon-star"></span>
<span *ngIf="song.Rating >= 60" class="glyphicon glyphicon-star"></span>
<span *ngIf="song.Rating >= 80" class="glyphicon glyphicon-star"></span>
<span *ngIf="song.Rating >= 100" class="glyphicon glyphicon-star"></span>
</td>
<td *ngIf="song['Rating Computed']" [title]="'Computed Rating: ' + song.Rating" class="star">
<span *ngIf="song.Rating >= 20" class="glyphicon glyphicon-star-empty"></span>
<span *ngIf="song.Rating >= 40" class="glyphicon glyphicon-star-empty"></span>
<span *ngIf="song.Rating >= 60" class="glyphicon glyphicon-star-empty"></span>
<span *ngIf="song.Rating >= 80" class="glyphicon glyphicon-star-empty"></span>
<span *ngIf="song.Rating >= 100" class="glyphicon glyphicon-star-empty"></span>
</td>
<td *ngIf="song.Loved" class="loved">
<span class="glyphicon glyphicon-heart heart"></span>
</td>
</tr>
</tbody>
</table>
<!-- Go to Top Button-->
<button type="button" class="btn btn-warning btn-top" [class.btn-top-is-visible]="bottomReached" aria-label="Top" (click)="scrollTop()"
title="Go back to Top!">
<span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span>
</button>
<button type="button" class="btn btn-primary btn-top btn-sort" [class.btn-top-is-visible]="sortable" aria-label="Top" (click)="sort()"
title="Sort by Album & Track Number">
<span class="glyphicon glyphicon-sort-by-attributes" aria-hidden="true"></span>
</button>

View File

@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SongTableComponent } from './song-table.component';
describe('SongTableComponent', () => {
let component: SongTableComponent;
let fixture: ComponentFixture<SongTableComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SongTableComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SongTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,61 @@
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { Song } from './../object/song';
import { SortByPipe } from './../sort-by.pipe';
@Component({
selector: 'app-song-table',
templateUrl: './song-table.component.html',
styleUrls: ['./song-table.component.css']
})
export class SongTableComponent implements OnChanges {
@Input() songs: Array<Song> = [];
@Input() sortable: boolean;
@Output() atBottom = new EventEmitter();
// To activate button in interface var
moreDataAvailable = false;
bottomReached = false;
nbSong = 0;
constructor() { }
ngOnChanges(changes: SimpleChanges) {
console.log(changes);
}
/**
* Handle scroll:
* - load data if at bottom of screen (if needed)
* - hide/show "go to top" button
*
* @param event scroll event
*/
onScroll(event: any) {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
this.atBottom.emit();
}
// Show/hide 'at top' button
if (window.scrollY > window.innerHeight) {
this.bottomReached = true;
}
if (window.scrollY === 0) {
this.bottomReached = false;
}
}
scrollTop(): void {
window.scrollTo(0, 0);
}
roundBitRate(bitRate: number) {
return Math.round(bitRate / 64);
}
sort(): void {
this.songs = new SortByPipe().transform(this.songs, 'Year', 'Album', 'Track Number', 'Play Count');
this.sortable = false;
}
}