refactor(frontend): refactor frontend services code
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {AsyncPipe, CommonModule, NgForOf, NgIf} from "@angular/common";
|
||||
import {TrackListComponent} from "../track-list/track-list.component";
|
||||
import {Playlist, PlaylistService, PlaylistStatusEnum, PlaylistUi} from "../../services/playlist.service";
|
||||
import {PlaylistService, PlaylistStatusEnum, PlaylistUi} from "../../services/playlist.service";
|
||||
import {Observable, map} from "rxjs";
|
||||
import {Playlist} from "../../models/playlist";
|
||||
|
||||
const STATUS2CLASS = {
|
||||
[PlaylistStatusEnum.Completed]: 'is-success',
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {CommonModule, NgFor, NgSwitch, NgSwitchCase} from "@angular/common";
|
||||
import {Track, TrackService, TrackStatusEnum} from "../../services/track.service";
|
||||
import {TrackService} from "../../services/track.service";
|
||||
import {Observable} from "rxjs";
|
||||
import {Track, TrackStatusEnum} from "../../models/track";
|
||||
|
||||
@Component({
|
||||
selector: 'app-track-list',
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export interface Playlist {
|
||||
id: number;
|
||||
name?: string;
|
||||
spotifyUrl: string;
|
||||
error?: string;
|
||||
active: boolean;
|
||||
createdAt: number;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export interface Track {
|
||||
id: number;
|
||||
artist: string;
|
||||
name: string;
|
||||
spotifyUrl: string;
|
||||
youtubeUrl: string;
|
||||
status: TrackStatusEnum;
|
||||
playlistId?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export enum TrackStatusEnum {
|
||||
New,
|
||||
Searching,
|
||||
Queued,
|
||||
Downloading,
|
||||
Completed,
|
||||
Error,
|
||||
}
|
||||
@@ -3,9 +3,7 @@ import {createStore} from "@ngneat/elf";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {
|
||||
deleteEntities,
|
||||
getEntityByPredicate,
|
||||
selectAllEntities, selectEntities, selectEntity,
|
||||
selectEntityByPredicate,
|
||||
setEntities,
|
||||
UIEntitiesRef,
|
||||
unionEntities, updateEntities, upsertEntities,
|
||||
@@ -14,20 +12,17 @@ import {
|
||||
} from "@ngneat/elf-entities";
|
||||
import {joinRequestResult, trackRequestResult} from "@ngneat/elf-requests";
|
||||
import {combineLatest, filter, first, map, Observable, of, switchMap, tap} from "rxjs";
|
||||
import {Track, TrackService} from "./track.service";
|
||||
import {TrackService} from "./track.service";
|
||||
import {Socket} from "ngx-socket-io";
|
||||
import {Playlist} from "../models/playlist";
|
||||
|
||||
const STORE_NAME = 'playlist';
|
||||
const ENDPOINT = '/api/playlist';
|
||||
const CREATE_LOADING = 'CREATE_LOADING';
|
||||
|
||||
export interface Playlist {
|
||||
id: number;
|
||||
name?: string;
|
||||
spotifyUrl: string;
|
||||
error?: string;
|
||||
active: boolean;
|
||||
createdAt: number;
|
||||
enum WsPlaylistOperation {
|
||||
New = 'playlistNew',
|
||||
Update = 'playlistUpdate',
|
||||
Delete = 'playlistDelete',
|
||||
}
|
||||
|
||||
export interface PlaylistUi {
|
||||
@@ -53,26 +48,18 @@ export class PlaylistService {
|
||||
withEntities<Playlist>(),
|
||||
withUIEntities<PlaylistUi>()
|
||||
);
|
||||
|
||||
all$ = this.store.combine({
|
||||
entities: this.store.pipe(selectAllEntities()),
|
||||
UIEntities: this.store.pipe(selectEntities({ ref: UIEntitiesRef })),
|
||||
}).pipe(unionEntities(), map(data => data.sort((a, b) => this.sort(a, b))));
|
||||
|
||||
loading$ = this.store.pipe(joinRequestResult([STORE_NAME]));
|
||||
}).pipe(unionEntities(), map(data => data.sort((a, b) => this.groupActiveAndSortByCreation(a, b))));
|
||||
createLoading$ = this.store.pipe(joinRequestResult([CREATE_LOADING], { initialStatus: 'idle' }));
|
||||
|
||||
constructor(private readonly http: HttpClient,
|
||||
private readonly socket: Socket,
|
||||
private readonly trackService: TrackService,
|
||||
) {
|
||||
this.socket.on('playlistUpdate', (playlist: Playlist) => this.store.update(upsertEntities(playlist)));
|
||||
this.socket.on('playlistDelete', ({id}: {id: number}) => this.store.update(deleteEntities(Number(id))));
|
||||
this.socket.on('playlistNew', (playlist: Playlist) =>
|
||||
this.store.update(
|
||||
upsertEntities(playlist),
|
||||
upsertEntities({id: playlist.id, collapsed: false}, {ref: UIEntitiesRef})
|
||||
)
|
||||
);
|
||||
this.initWsConnection();
|
||||
}
|
||||
|
||||
getById(id: number): Observable<Playlist | undefined> {
|
||||
@@ -133,7 +120,6 @@ export class PlaylistService {
|
||||
setEntities(data.map(item => ({id: item.id, collapsed: false})), {ref: UIEntitiesRef})
|
||||
)),
|
||||
tap((data: Playlist[]) => data.forEach(playlist => this.trackService.fetch(playlist.id))),
|
||||
trackRequestResult([STORE_NAME], { skipCache: true }),
|
||||
).subscribe();
|
||||
}
|
||||
|
||||
@@ -144,17 +130,13 @@ export class PlaylistService {
|
||||
}
|
||||
|
||||
toggleCollapsed(id: number): void {
|
||||
this.store.update(updateEntities(id, old => ({...old, collapsed: !old.collapsed}), { ref: UIEntitiesRef }))
|
||||
this.store.update(updateEntities(id, old => ({...old, collapsed: !old.collapsed}), { ref: UIEntitiesRef }));
|
||||
}
|
||||
|
||||
delete(id: number): void {
|
||||
this.delete$(id).subscribe();
|
||||
}
|
||||
|
||||
private delete$(id: number): Observable<void> {
|
||||
return this.http.delete<void>(`${ENDPOINT}/${id}`);
|
||||
}
|
||||
|
||||
retryFailed(id: number): void {
|
||||
this.http.get<void>(`${ENDPOINT}/retry/${id}`).subscribe();
|
||||
}
|
||||
@@ -163,7 +145,22 @@ export class PlaylistService {
|
||||
this.http.put<void>(`${ENDPOINT}/${id}`, {active}).subscribe();
|
||||
}
|
||||
|
||||
private sort(a: Playlist & PlaylistUi, b: Playlist & PlaylistUi): number {
|
||||
private delete$(id: number): Observable<void> {
|
||||
return this.http.delete<void>(`${ENDPOINT}/${id}`);
|
||||
}
|
||||
|
||||
private groupActiveAndSortByCreation(a: Playlist & PlaylistUi, b: Playlist & PlaylistUi): number {
|
||||
return a.active === b.active ? (b.createdAt - a.createdAt) : (a.active < b.active ? 1 : -1);
|
||||
}
|
||||
|
||||
private initWsConnection(): void {
|
||||
this.socket.on(WsPlaylistOperation.Update, (playlist: Playlist) => this.store.update(upsertEntities(playlist)));
|
||||
this.socket.on(WsPlaylistOperation.Delete, ({id}: {id: number}) => this.store.update(deleteEntities(Number(id))));
|
||||
this.socket.on(WsPlaylistOperation.New, (playlist: Playlist) =>
|
||||
this.store.update(
|
||||
upsertEntities(playlist),
|
||||
upsertEntities({id: playlist.id, collapsed: false}, {ref: UIEntitiesRef})
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,30 +3,15 @@ import {createStore} from "@ngneat/elf";
|
||||
import {deleteEntities, selectManyByPredicate, upsertEntities, withEntities} from "@ngneat/elf-entities";
|
||||
import {Socket} from "ngx-socket-io";
|
||||
import {map, Observable, tap} from "rxjs";
|
||||
import {trackRequestResult} from "@ngneat/elf-requests";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {Track, TrackStatusEnum} from "../models/track";
|
||||
|
||||
const STORE_NAME = 'track';
|
||||
const ENDPOINT = '/api/track';
|
||||
|
||||
export interface Track {
|
||||
id: number;
|
||||
artist: string;
|
||||
name: string;
|
||||
spotifyUrl: string;
|
||||
youtubeUrl: string;
|
||||
status: TrackStatusEnum;
|
||||
playlistId?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export enum TrackStatusEnum {
|
||||
New,
|
||||
Searching,
|
||||
Queued,
|
||||
Downloading,
|
||||
Completed,
|
||||
Error,
|
||||
enum WsTrackOperation {
|
||||
New = 'trackNew',
|
||||
Update = 'trackUpdate',
|
||||
Delete = 'trackDelete',
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
@@ -58,17 +43,12 @@ export class TrackService {
|
||||
private readonly http: HttpClient,
|
||||
private readonly socket: Socket,
|
||||
) {
|
||||
this.socket.on('trackUpdate', (track: Track) => this.store.update(upsertEntities(track)));
|
||||
this.socket.on('trackDelete', ({id}: {id: number}) => this.store.update(deleteEntities(id)));
|
||||
this.socket.on('trackNew', ({track, playlistId}: {track: Track, playlistId: number}) =>
|
||||
this.store.update(upsertEntities([{...track, playlistId}]))
|
||||
);
|
||||
this.initWsConnection();
|
||||
}
|
||||
|
||||
fetch(playlistId: number): void {
|
||||
this.http.get<Track[]>(`${ENDPOINT}/playlist/${playlistId}`).pipe(
|
||||
tap((data: Track[]) => this.store.update(upsertEntities(data.map(track => ({...track, playlistId}))))),
|
||||
trackRequestResult([STORE_NAME], { skipCache: true }),
|
||||
).subscribe();
|
||||
}
|
||||
|
||||
@@ -79,4 +59,12 @@ export class TrackService {
|
||||
retry(id: number): void {
|
||||
this.http.get(`${ENDPOINT}/retry/${id}`).subscribe();
|
||||
}
|
||||
|
||||
private initWsConnection(): void {
|
||||
this.socket.on(WsTrackOperation.Update, (track: Track) => this.store.update(upsertEntities(track)));
|
||||
this.socket.on(WsTrackOperation.Delete, ({id}: {id: number}) => this.store.update(deleteEntities(id)));
|
||||
this.socket.on(WsTrackOperation.New, ({track, playlistId}: {track: Track, playlistId: number}) =>
|
||||
this.store.update(upsertEntities([{...track, playlistId}]))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user