mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-03 20:47:35 +03:00
Remove tracks from playlist
This commit is contained in:
parent
5c95eed517
commit
12cf2f1104
6 changed files with 72 additions and 9 deletions
|
@ -2,8 +2,6 @@ package model
|
|||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/deluan/rest"
|
||||
)
|
||||
|
||||
type Playlist struct {
|
||||
|
@ -41,7 +39,8 @@ type PlaylistTrack struct {
|
|||
type PlaylistTracks []PlaylistTrack
|
||||
|
||||
type PlaylistTrackRepository interface {
|
||||
rest.Repository
|
||||
ResourceRepository
|
||||
Add(mediaFileIds []string) error
|
||||
Update(mediaFileIds []string) error
|
||||
Delete(id string) error
|
||||
}
|
||||
|
|
|
@ -123,12 +123,16 @@ func (r *playlistTrackRepository) Update(mediaFileIds []string) error {
|
|||
}
|
||||
}
|
||||
|
||||
return r.updateStats()
|
||||
}
|
||||
|
||||
func (r *playlistTrackRepository) updateStats() error {
|
||||
// Get total playlist duration and count
|
||||
statsSql := Select("sum(duration) as duration", "count(*) as count").From("media_file").
|
||||
Join("playlist_tracks f on f.media_file_id = media_file.id").
|
||||
Where(Eq{"playlist_id": r.playlistId})
|
||||
var res struct{ Duration, Count float32 }
|
||||
err = r.queryOne(statsSql, &res)
|
||||
err := r.queryOne(statsSql, &res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -142,5 +146,12 @@ func (r *playlistTrackRepository) Update(mediaFileIds []string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (r *playlistTrackRepository) Delete(id string) error {
|
||||
err := r.delete(And{Eq{"playlist_id": r.playlistId}, Eq{"id": id}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return r.updateStats()
|
||||
}
|
||||
|
||||
var _ model.PlaylistTrackRepository = (*playlistTrackRepository)(nil)
|
||||
var _ model.ResourceRepository = (*playlistTrackRepository)(nil)
|
||||
|
|
|
@ -109,6 +109,9 @@ func (app *Router) addPlaylistTrackRoute(r chi.Router) {
|
|||
r.Route("/{id}", func(r chi.Router) {
|
||||
r.Use(UrlParams)
|
||||
r.Get("/", wrapper(rest.Get))
|
||||
r.Delete("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
deleteFromPlaylist(app.ds)(w, r)
|
||||
})
|
||||
})
|
||||
r.With(UrlParams).Post("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
addToPlaylist(app.ds)(w, r)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/deluan/navidrome/log"
|
||||
"github.com/deluan/navidrome/model"
|
||||
"github.com/deluan/navidrome/utils"
|
||||
)
|
||||
|
@ -13,6 +14,29 @@ type addTracksPayload struct {
|
|||
Ids []string `json:"ids"`
|
||||
}
|
||||
|
||||
func deleteFromPlaylist(ds model.DataStore) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
playlistId := utils.ParamString(r, ":playlistId")
|
||||
id := r.URL.Query().Get(":id")
|
||||
tracksRepo := ds.Playlist(r.Context()).Tracks(playlistId)
|
||||
err := tracksRepo.Delete(id)
|
||||
if err == model.ErrNotFound {
|
||||
log.Warn("Track not found in playlist", "playlistId", playlistId, "id", id)
|
||||
http.Error(w, "not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("Error deleting track from playlist", "playlistId", playlistId, "id", id, err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_, err = w.Write([]byte("{}"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addToPlaylist(ds model.DataStore) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
playlistId := utils.ParamString(r, ":playlistId")
|
||||
|
@ -32,7 +56,7 @@ func addToPlaylist(ds model.DataStore) http.HandlerFunc {
|
|||
// Must return an object with an ID, to satisfy ReactAdmin `create` call
|
||||
_, err = w.Write([]byte(fmt.Sprintf(`{"id":"%s"}`, playlistId)))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import React from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { useGetOne } from 'react-admin'
|
||||
import PlaylistDetails from './PlaylistDetails'
|
||||
import { Title } from '../common'
|
||||
import PlaylistSongs from './PlaylistSongs'
|
||||
import PlaylistActions from './PlaylistActions'
|
||||
import PlaylistSongBulkActions from './PlaylistSongBulkActions'
|
||||
|
||||
const PlaylistShow = (props) => {
|
||||
const { data: record, loading, error } = useGetOne('playlist', props.id)
|
||||
const viewVersion = useSelector((s) => s.admin.ui && s.admin.ui.viewVersion)
|
||||
const { data: record, loading, error } = useGetOne('playlist', props.id, {
|
||||
v: viewVersion,
|
||||
})
|
||||
|
||||
if (loading) {
|
||||
return null
|
||||
|
@ -29,8 +34,7 @@ const PlaylistShow = (props) => {
|
|||
exporter={false}
|
||||
perPage={-1}
|
||||
pagination={null}
|
||||
bulkActionButtons={false}
|
||||
// bulkActionButtons={<AlbumSongBulkActions />}
|
||||
bulkActionButtons={<PlaylistSongBulkActions playlistId={props.id} />}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
|
22
ui/src/playlist/PlaylistSongBulkActions.js
Normal file
22
ui/src/playlist/PlaylistSongBulkActions.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import React, { Fragment, useEffect } from 'react'
|
||||
import { BulkDeleteButton, useUnselectAll } from 'react-admin'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const PlaylistSongBulkActions = ({ playlistId, ...rest }) => {
|
||||
const unselectAll = useUnselectAll()
|
||||
useEffect(() => {
|
||||
unselectAll('playlistTrack')
|
||||
// eslint-disable-next-line
|
||||
}, [])
|
||||
return (
|
||||
<Fragment>
|
||||
<BulkDeleteButton {...rest} resource={`playlist/${playlistId}/tracks`} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
PlaylistSongBulkActions.propTypes = {
|
||||
playlistId: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default PlaylistSongBulkActions
|
Loading…
Add table
Add a link
Reference in a new issue