delete functionality

This commit is contained in:
raiper34
2024-07-14 00:20:41 +02:00
parent 208ce466cf
commit 893bc438f8
13 changed files with 64 additions and 17 deletions
@@ -1,4 +1,4 @@
import {Body, Controller, Get, Post} from '@nestjs/common'; import {Body, Controller, Delete, Get, Param, Post} from '@nestjs/common';
import {PlaylistService} from "./playlist.service"; import {PlaylistService} from "./playlist.service";
import {PlaylistModel} from "./playlist.model"; import {PlaylistModel} from "./playlist.model";
@@ -19,4 +19,9 @@ export class PlaylistController {
async create(@Body() playlist: PlaylistModel): Promise<void> { async create(@Body() playlist: PlaylistModel): Promise<void> {
await this.service.create(playlist); await this.service.create(playlist);
} }
@Delete(':id')
remove(@Param('id') id: number): Promise<void> {
return this.service.remove(id);
}
} }
@@ -30,6 +30,7 @@ export class PlaylistService {
async remove(id: number): Promise<void> { async remove(id: number): Promise<void> {
await this.repository.delete(id); await this.repository.delete(id);
this.io.emit('playlistDelete', {id});
} }
async create(playlist: PlaylistEntity): Promise<void> { async create(playlist: PlaylistEntity): Promise<void> {
+6 -1
View File
@@ -1,4 +1,4 @@
import {Controller, Get, Param, Res, StreamableFile} from '@nestjs/common'; import {Controller, Delete, Get, Param, Res, StreamableFile} from '@nestjs/common';
import {TrackService} from "./track.service"; import {TrackService} from "./track.service";
import {TrackModel} from "./track.model"; import {TrackModel} from "./track.model";
import {createReadStream} from "fs"; import {createReadStream} from "fs";
@@ -30,4 +30,9 @@ export class TrackController {
res.set({'Content-Disposition': `attachment; filename="${track.artist} - ${track.song}.mp3"`,}); res.set({'Content-Disposition': `attachment; filename="${track.artist} - ${track.song}.mp3"`,});
return new StreamableFile(file); return new StreamableFile(file);
} }
@Delete(':id')
remove(@Param('id') id: number): Promise<void> {
return this.service.remove(id);
}
} }
+1 -1
View File
@@ -29,6 +29,6 @@ export class TrackEntity {
@Column({default: Date.now()}) @Column({default: Date.now()})
createdAt?: number; createdAt?: number;
@ManyToOne(() => PlaylistEntity, playlist => playlist.tracks) @ManyToOne(() => PlaylistEntity, playlist => playlist.tracks, {onDelete: "CASCADE"})
playlist?: PlaylistEntity; playlist?: PlaylistEntity;
} }
+1
View File
@@ -40,6 +40,7 @@ export class TrackService {
async remove(id: number): Promise<void> { async remove(id: number): Promise<void> {
await this.repository.delete(id); await this.repository.delete(id);
this.io.emit('trackDelete', {id});
} }
async create(track: TrackEntity, playlist?: PlaylistEntity): Promise<void> { async create(track: TrackEntity, playlist?: PlaylistEntity): Promise<void> {
@@ -15,8 +15,9 @@
<i class="fa-brands fa-spotify"></i> <i class="fa-brands fa-spotify"></i>
</a> </a>
</span> </span>
<span *ngIf="!playlist.error"> <span>
<span class="is-size-6 has-text-weight-medium">{{trackCompletedCount$ | async}}/{{trackCount$ | async}}</span>&nbsp; <i class="fa-solid fa-xmark is-clickable hover-icon" title="Remove track from list" (click)="delete(playlist.id)"></i>&nbsp;
<span *ngIf="!playlist.error" class="is-size-6 has-text-weight-medium">{{trackCompletedCount$ | async}}/{{trackCount$ | async}}</span>&nbsp;
</span> </span>
</p> </p>
<ng-container *ngIf="playlist.collapsed"> <ng-container *ngIf="playlist.collapsed">
@@ -1,6 +1,14 @@
.hover-icon {
display: none;
}
.panel-heading { .panel-heading {
padding: 5px 10px; padding: 5px 10px;
border-radius: 10px; border-radius: 10px;
&:hover .hover-icon {
display: inline;
}
} }
.panel { .panel {
@@ -29,9 +29,9 @@ export class PlaylistBoxComponent {
@Input() set playlist(val: Playlist & PlaylistUi) { @Input() set playlist(val: Playlist & PlaylistUi) {
this._playlist = val; this._playlist = val;
this.trackCount$ = this.playlistService.getTrackCount(val.id); this.trackCount$ = this.service.getTrackCount(val.id);
this.trackCompletedCount$ = this.playlistService.getCompletedTrackCount(val.id); this.trackCompletedCount$ = this.service.getCompletedTrackCount(val.id);
this.statusClass$ = this.playlistService.getStatus$(val.id).pipe( this.statusClass$ = this.service.getStatus$(val.id).pipe(
map(status => STATUS2CLASS[status]) map(status => STATUS2CLASS[status])
); );
} }
@@ -43,10 +43,14 @@ export class PlaylistBoxComponent {
trackCompletedCount$!: Observable<number>; trackCompletedCount$!: Observable<number>;
statusClass$!: Observable<string>; statusClass$!: Observable<string>;
constructor(private readonly playlistService: PlaylistService) { } constructor(private readonly service: PlaylistService) { }
toggleCollapse(playlistId: number): void { toggleCollapse(playlistId: number): void {
this.playlistService.toggleCollapsed(playlistId); this.service.toggleCollapsed(playlistId);
}
delete(id: number): void {
this.service.delete(id);
} }
} }
@@ -20,6 +20,7 @@
</a> </a>
</div> </div>
<div> <div>
<i class="fa-solid fa-xmark hover-icon" title="Remove track from list" (click)="delete(track.id)"></i>&nbsp;
<ng-container [ngSwitch]="track.status"> <ng-container [ngSwitch]="track.status">
<span *ngSwitchCase="trackStatuses.New" class="tag is-info">New</span> <span *ngSwitchCase="trackStatuses.New" class="tag is-info">New</span>
<span *ngSwitchCase="trackStatuses.Searching" class="tag is-warning">Searching</span> <span *ngSwitchCase="trackStatuses.Searching" class="tag is-warning">Searching</span>
@@ -1,3 +1,11 @@
.hover-icon {
display: none;
}
.panel-block { .panel-block {
padding: 5px 10px; padding: 5px 10px;
&:hover .hover-icon {
display: inline;
}
} }
@@ -13,7 +13,6 @@ import {Observable} from "rxjs";
export class TrackListComponent { export class TrackListComponent {
@Input() set playlistId(value: number) { @Input() set playlistId(value: number) {
console.log(value);
this.tracks$ = this.service.getAllByPlaylist(value); this.tracks$ = this.service.getAllByPlaylist(value);
} }
tracks$!: Observable<Track[]>; tracks$!: Observable<Track[]>;
@@ -21,6 +20,9 @@ export class TrackListComponent {
constructor( constructor(
private readonly service: TrackService, private readonly service: TrackService,
) { ) { }
delete(id: number): void {
this.service.delete(id);
} }
} }
@@ -2,8 +2,9 @@ import { Injectable } from '@angular/core';
import {createStore} from "@ngneat/elf"; import {createStore} from "@ngneat/elf";
import {HttpClient} from "@angular/common/http"; import {HttpClient} from "@angular/common/http";
import { import {
deleteEntities,
getEntityByPredicate, getEntityByPredicate,
selectAllEntities, selectEntities, selectAllEntities, selectEntities, selectEntity,
selectEntityByPredicate, selectEntityByPredicate,
setEntities, setEntities,
UIEntitiesRef, UIEntitiesRef,
@@ -64,6 +65,7 @@ export class PlaylistService {
private readonly trackService: TrackService, private readonly trackService: TrackService,
) { ) {
this.socket.on('playlistUpdate', (playlist: Playlist) => this.store.update(upsertEntities(playlist))); 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.socket.on('playlistNew', (playlist: Playlist) =>
this.store.update( this.store.update(
upsertEntities(playlist), upsertEntities(playlist),
@@ -72,8 +74,8 @@ export class PlaylistService {
); );
} }
getById(playlistId: number): Observable<Playlist | undefined> { getById(id: number): Observable<Playlist | undefined> {
return this.store.pipe(selectEntityByPredicate(({id}) => id === playlistId)); return this.store.pipe(selectEntity(id));
} }
getTrackCount(id: number): Observable<number> { getTrackCount(id: number): Observable<number> {
@@ -126,4 +128,8 @@ export class PlaylistService {
toggleCollapsed(id: number): void { 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.http.delete(`${ENDPOINT}/${id}`).subscribe();
}
} }
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import {createStore} from "@ngneat/elf"; import {createStore} from "@ngneat/elf";
import {selectManyByPredicate, upsertEntities, withEntities} from "@ngneat/elf-entities"; import {deleteEntities, selectManyByPredicate, upsertEntities, withEntities} from "@ngneat/elf-entities";
import {Socket} from "ngx-socket-io"; import {Socket} from "ngx-socket-io";
import {map, Observable, tap} from "rxjs"; import {map, Observable, tap} from "rxjs";
import {trackRequestResult} from "@ngneat/elf-requests"; import {trackRequestResult} from "@ngneat/elf-requests";
@@ -41,7 +41,7 @@ export class TrackService {
getAllByPlaylist(id: number, status?: TrackStatusEnum): Observable<Track[]> { getAllByPlaylist(id: number, status?: TrackStatusEnum): Observable<Track[]> {
return this.store.pipe( return this.store.pipe(
selectManyByPredicate(({playlistId}) => playlistId === id), selectManyByPredicate((track) => track?.playlistId === id),
map(data => data.filter(item => status === undefined || item.status === status)), map(data => data.filter(item => status === undefined || item.status === status)),
); );
} }
@@ -59,6 +59,7 @@ export class TrackService {
private readonly socket: Socket, private readonly socket: Socket,
) { ) {
this.socket.on('trackUpdate', (track: Track) => this.store.update(upsertEntities(track))); 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.socket.on('trackNew', ({track, playlistId}: {track: Track, playlistId: number}) =>
this.store.update(upsertEntities([{...track, playlistId}])) this.store.update(upsertEntities([{...track, playlistId}]))
); );
@@ -70,4 +71,8 @@ export class TrackService {
trackRequestResult([STORE_NAME], { skipCache: true }), trackRequestResult([STORE_NAME], { skipCache: true }),
).subscribe(); ).subscribe();
} }
delete(id: number): void {
this.http.delete(`${ENDPOINT}/${id}`).subscribe();
}
} }