Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/direct service communications for lists #52

Merged
merged 12 commits into from
Aug 22, 2019
10 changes: 2 additions & 8 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@ import { ArtistsPageComponent } from './pages/artists/artists-page.component';
import {ArtistState} from './store/states/artist.state';
import {NgxsReduxDevtoolsPluginModule} from '@ngxs/devtools-plugin';
import {FormsModule} from '@angular/forms';
import {SearchState} from './store/states/search.state';
import {ArtistDetailPageComponent} from './pages/artist-detail/artist-detail-page.component';
import {NgxsStoragePluginModule} from '@ngxs/storage-plugin';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import { ArtistSaveButtonComponent } from './components/artist-save-button/artist-save-button.component';
import {AlbumSpotifyService} from './store/providers/album-spotify.service';
import {ArtistSpotifyService} from './store/providers/artist-spotify.service';
import {PlaylistSpotifyService} from './store/providers/playlist-spotify.service';
import {ProfileSpotifyService} from './store/providers/profile-spotify.service';
import {SearchSpotifyService} from './store/providers/search-spotify.service';
Expand All @@ -42,12 +39,12 @@ import {MinutesSecondsPipe} from './pipes/minutes-seconds.pipe';
import { VolumeControlComponent } from './components/volume-control/volume-control.component';
import { PlayerTrackInfoComponent } from './components/player-track-info/player-track-info.component';
import {AuthenticationState} from './store/states/authentication.state';
import { EntityListComponent } from './components/entity-list/entity-list.component';
import { AlbumsPageComponent } from './pages/album-page/albums-page.component';
import {AlbumState} from './store/states/album.state';
import { AlbumSaveButtonComponent } from './components/album-save-button/album-save-button.component';
import { AlbumDetailPageComponent } from './pages/album-detail-page/album-detail-page.component';
import { ArtistNamesComponent } from './components/artist-names/artist-names.component';
import { VirtualScrollListComponent } from './components/virtual-scroll-list/virtual-scroll-list.component';

const spotifyConfig = {
clientId: environment.clientId,
Expand Down Expand Up @@ -109,11 +106,11 @@ export function serialize(value: any) {
MinutesSecondsPipe,
VolumeControlComponent,
PlayerTrackInfoComponent,
EntityListComponent,
AlbumsPageComponent,
AlbumSaveButtonComponent,
AlbumDetailPageComponent,
ArtistNamesComponent,
VirtualScrollListComponent,
],
imports: [
BrowserModule,
Expand All @@ -122,7 +119,6 @@ export function serialize(value: any) {
NgxsModule.forRoot([
FolderState,
ArtistState,
SearchState,
TrackState,
PlayerState,
AuthenticationState,
Expand All @@ -143,8 +139,6 @@ export function serialize(value: any) {
useClass: SpotifyAuthorizationInterceptor,
multi: true
},
AlbumSpotifyService,
ArtistSpotifyService,
PlaylistSpotifyService,
ProfileSpotifyService,
SearchSpotifyService,
Expand Down
97 changes: 0 additions & 97 deletions src/app/components/entity-list/entity-list.component.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<div class="list-container disable-select" *ngIf="entities">
<table mat-table [dataSource]="entities" class="table" *ngIf="!loading">
<div class="list-container disable-select" *ngIf="dataSource">
<table mat-table [dataSource]="dataSource" class="table" [trackBy]="trackBy">
<ng-container matColumnDef="image">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let element"><img *ngIf="element.images[2]" src="{{element.images[2].url}}"/></td>
</ng-container>

<ng-container matColumnDef="album-image">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let element"><img *ngIf="element.album.images[2]" src="{{element.album.images[2].url}}"/></td>
<td mat-cell *matCellDef="let element"><img *ngIf="element.album.images[2]"
src="{{element.album.images[2].url}}"/></td>
</ng-container>

<ng-container matColumnDef="name">
Expand All @@ -23,21 +24,26 @@
</ng-container>

<ng-container matColumnDef="album">
<th mat-header-cell *matHeaderCellDef>Album</th>
<th mat-header-cell *matHeaderCellDef> Album</th>
<td mat-cell *matCellDef="let element">
<a [routerLink]="['/album', element.album.id]">{{element.album.name}}</a>
</td>
</ng-container>

<ng-container matColumnDef="artist">
<th mat-header-cell *matHeaderCellDef>Artist</th>
<th mat-header-cell *matHeaderCellDef> Artist</th>
<td mat-cell *matCellDef="let element">
<app-artist-names [artists]="element.artists"></app-artist-names>
<ng-container *ngFor="let artist of element.artists; let last = last">
<a [routerLink]="['/artist', artist.id]">{{artist.name}}</a>
<ng-container *ngIf="!last">,</ng-container>
</ng-container>
</td>
</ng-container>

<ng-container matColumnDef="duration">
<th mat-header-cell *matHeaderCellDef><mat-icon>timer</mat-icon></th>
<th mat-header-cell *matHeaderCellDef>
<mat-icon>timer</mat-icon>
</th>
<td mat-cell *matCellDef="let element">{{element.duration_ms | minutesSeconds}}</td>
</ng-container>

Expand All @@ -63,8 +69,9 @@
</ng-container>

<tr mat-header-row *matHeaderRowDef="columns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: columns;" (dblclick)="rowDoubleClick.emit(row)"></tr>
<tr mat-row *matRowDef="let row; columns: columns;" (dblclick)="onRowClick(row)"></tr>
</table>
</div>
<mat-paginator *ngIf="total > pageSize" [pageSize]="pageSize" [length]="total" (page)="onPageChange($event)" showFirstLastButtons></mat-paginator>
<mat-paginator *ngIf="dataSource" [pageSize]="dataSource.pageSize" [length]="dataSource.total"
(page)="onPageChange($event)" showFirstLastButtons></mat-paginator>

Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { EntityListComponent } from './entity-list.component';
import { VirtualScrollListComponent } from './virtual-scroll-list.component';

describe('EntityListComponent', () => {
let component: EntityListComponent;
let fixture: ComponentFixture<EntityListComponent>;
describe('VirtualScrollListComponent', () => {
let component: VirtualScrollListComponent;
let fixture: ComponentFixture<VirtualScrollListComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EntityListComponent ]
declarations: [ VirtualScrollListComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(EntityListComponent);
fixture = TestBed.createComponent(VirtualScrollListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import {Component, EventEmitter, Input, OnChanges, OnInit, Output} from '@angular/core';
import {SpotifyEntityModel} from '../../store/models/spotify-entity.model';
import {DataSource} from '@angular/cdk/table';
import {PagedDataSource} from '../../datasources/paged-data-source';

@Component({
selector: 'app-virtual-scroll-list',
templateUrl: './virtual-scroll-list.component.html',
styleUrls: ['./virtual-scroll-list.component.scss']
})
export class VirtualScrollListComponent implements OnInit, OnChanges {
/**
* The dataSource this list subscribes to
*/
@Input() dataSource: PagedDataSource<SpotifyEntityModel>;

/**
* The displayed colums.
* Columns that can be used:
* - image
* - album-image
* - name
* - popularity
* - album
* - artist
* - duration
* - saved
*/
@Input() public columns: string[] = ['name'];

/**
* Emits an event containing the row object and the ids of the rest of the page
*/
@Output() public rowDoubleClick = new EventEmitter<{
id: string,
context: string[]
}>();

public ngOnInit(): void {
this.dataSource.openPage(0);
}

public ngOnChanges(): void {
this.dataSource.openPage(0);
}

public onPageChange(event): void {
this.dataSource.openPage(event.pageIndex);
}

public onRowClick(event: SpotifyEntityModel) {
this.rowDoubleClick.emit({
id: event.id,
context: this.dataSource.getIds(),
});
}

public trackBy(index, item) {
return item.id;
}
}
45 changes: 45 additions & 0 deletions src/app/datasources/entity-data-source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {TrackModel} from '../store/models/track.model';
import {CollectionViewer} from '@angular/cdk/collections';
import {BehaviorSubject, Observable} from 'rxjs';
import {PagedDataSource} from './paged-data-source';
import {SpotifyEntityModel} from '../store/models/spotify-entity.model';
import {SpotifyEntityService} from '../store/providers/spotify-entity.service';

export class EntityDataSource extends PagedDataSource<SpotifyEntityModel> {
private entities = [];

private subject = new BehaviorSubject<SpotifyEntityModel[]>(this.entities);
private observable = this.subject.asObservable();

constructor(
private entityService: SpotifyEntityService,
private ids: string[],
public type: string,
public pageSize: number,
) {
super();
this.total = ids.length > 0 ? ids.length : 0;
}

connect(collectionViewer: CollectionViewer): Observable<TrackModel[] | ReadonlyArray<SpotifyEntityModel>> {
return this.observable;
}

disconnect(collectionViewer: CollectionViewer): void {
this.subject.complete();
}

public openPage(page): void {
const start = page * this.pageSize;
const end = start + this.pageSize;
const pageIds = this.ids.slice(start, end);
this.entityService.getEntities(pageIds, this.type, this.pageSize).subscribe((value: any) => {
this.entities = value[this.type + 's'];
this.subject.next(this.entities);
});
}

public getIds(): string[] {
return this.ids;
}
}
43 changes: 43 additions & 0 deletions src/app/datasources/nested-entity-data-source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {BehaviorSubject, Observable} from 'rxjs';
import {SpotifyEntityModel} from '../store/models/spotify-entity.model';
import {SpotifyEntityService} from '../store/providers/spotify-entity.service';
import {PagedDataSource} from './paged-data-source';
import {CollectionViewer} from '@angular/cdk/collections';
import {TrackModel} from '../store/models/track.model';

export class NestedEntityDataSource extends PagedDataSource<SpotifyEntityModel> {
private entities = [];

private subject = new BehaviorSubject<SpotifyEntityModel[]>(this.entities);
private observable = this.subject.asObservable();

constructor(
private entityService: SpotifyEntityService,
private id: string,
private parentType: string,
public type: string,
public pageSize: number,
) {
super();
}

connect(collectionViewer: CollectionViewer): Observable<TrackModel[] | ReadonlyArray<SpotifyEntityModel>> {
return this.observable;
}

disconnect(collectionViewer: CollectionViewer): void {
this.subject.complete();
}

public openPage(page): void {
this.entityService.getNestedEntities(this.id, this.parentType, this.type, page, this.pageSize).subscribe((value: any) => {
this.entities = value.items;
this.total = value.total;
this.subject.next(this.entities);
});
}

public getIds(): string[] {
return this.entities.map(x => x.id);
}
}
Loading