Extract table
Problem on sortable
This commit is contained in:
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
116
dashboard/src/app/song-table/song-table.component.css
Normal file
116
dashboard/src/app/song-table/song-table.component.css
Normal file
File diff suppressed because one or more lines are too long
64
dashboard/src/app/song-table/song-table.component.html
Normal file
64
dashboard/src/app/song-table/song-table.component.html
Normal 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>
|
||||||
25
dashboard/src/app/song-table/song-table.component.spec.ts
Normal file
25
dashboard/src/app/song-table/song-table.component.spec.ts
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
61
dashboard/src/app/song-table/song-table.component.ts
Normal file
61
dashboard/src/app/song-table/song-table.component.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user