Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
funkwhale
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Paul Walko
funkwhale
Commits
1e64f3db
Verified
Commit
1e64f3db
authored
7 years ago
by
Eliot Berriot
Browse files
Options
Downloads
Patches
Plain Diff
Playlist detail page and editor
parent
bed66db5
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
front/src/components/playlists/Editor.vue
+149
-0
149 additions, 0 deletions
front/src/components/playlists/Editor.vue
front/src/router/index.js
+2
-1
2 additions, 1 deletion
front/src/router/index.js
front/src/views/playlists/Detail.vue
+88
-0
88 additions, 0 deletions
front/src/views/playlists/Detail.vue
with
239 additions
and
1 deletion
front/src/components/playlists/Editor.vue
0 → 100644
+
149
−
0
View file @
1e64f3db
<
template
>
<div
class=
"ui text container"
>
<h2
class=
"ui header"
>
Playlist editor
</h2>
<p>
Drag and drop rows to reorder tracks in the playlist
</p>
<div
class=
"ui buttons"
>
<div
@
click=
"insertMany(queueTracks)"
:disabled=
"queueTracks.length === 0"
:class=
"['ui',
{disabled: queueTracks.length === 0}, 'button']"
title="Copy tracks from current queue to playlist">Insert from queue (
{{
queueTracks
.
length
}}
tracks)
</div>
</div>
<h5
class=
"ui header"
>
Status
</h5>
<div>
<template
v-if=
"status === 'loading'"
>
<div
class=
"ui active tiny inline loader"
></div>
Syncing changes to server...
</
template
>
<
template
v-else-if=
"status === 'errored'"
>
<i
class=
"red x icon"
></i>
An error occured while saving your changes
<div
v-if=
"errors.length > 0"
class=
"ui negative message"
>
<ul
class=
"list"
>
<li
v-for=
"error in errors"
>
{{
error
}}
</li>
</ul>
</div>
</
template
>
<
template
v-else-if=
"status === 'saved'"
>
<i
class=
"green check icon"
></i>
Changes synced with server
</
template
>
</div>
<table
class=
"ui compact very basic fixed single line unstackable table"
>
<draggable
v-model=
"plts"
element=
"tbody"
@
update=
"reorder"
>
<tr
v-for=
"(plt, index) in plts"
:key=
"plt.id"
>
<td
class=
"left aligned"
>
{{ plt.index + 1}}
</td>
<td
class=
"center aligned"
>
<img
class=
"ui mini image"
v-if=
"plt.track.album.cover"
:src=
"plt.track.album.cover"
>
<img
class=
"ui mini image"
v-else
src=
"../../assets/audio/default-cover.png"
>
</td>
<td
colspan=
"4"
>
<strong>
{{ plt.track.title }}
</strong><br
/>
{{ plt.track.artist.name }}
</td>
<td
class=
"right aligned"
>
<i
@
click.stop=
"removePlt(index)"
class=
"circular red trash icon"
></i>
</td>
</tr>
</draggable>
</table>
</div>
</template>
<
script
>
import
{
mapState
}
from
'
vuex
'
import
axios
from
'
axios
'
import
draggable
from
'
vuedraggable
'
export
default
{
components
:
{
draggable
},
props
:
[
'
playlist
'
,
'
playlistTracks
'
],
data
()
{
return
{
plts
:
this
.
playlistTracks
,
isLoading
:
false
,
errors
:
[]
}
},
methods
:
{
success
()
{
this
.
isLoading
=
false
this
.
errors
=
[]
},
errored
(
errors
)
{
this
.
isLoading
=
false
this
.
errors
=
errors
},
reorder
({
oldIndex
,
newIndex
})
{
let
self
=
this
self
.
isLoading
=
true
let
plt
=
this
.
plts
[
newIndex
]
let
url
=
'
playlist-tracks/
'
+
plt
.
id
+
'
/
'
axios
.
patch
(
url
,
{
index
:
newIndex
}).
then
((
response
)
=>
{
self
.
success
()
},
error
=>
{
self
.
errored
(
error
.
backendErrors
)
})
},
removePlt
(
index
)
{
let
plt
=
this
.
plts
[
index
]
this
.
plts
.
splice
(
index
,
1
)
let
self
=
this
self
.
isLoading
=
true
let
url
=
'
playlist-tracks/
'
+
plt
.
id
+
'
/
'
axios
.
delete
(
url
).
then
((
response
)
=>
{
self
.
success
()
},
error
=>
{
self
.
errored
(
error
.
backendErrors
)
})
},
insertMany
(
tracks
)
{
let
self
=
this
let
ids
=
tracks
.
map
(
t
=>
{
return
t
.
id
})
self
.
isLoading
=
true
let
url
=
'
playlists/
'
+
this
.
playlist
.
id
+
'
/add/
'
axios
.
post
(
url
,
{
tracks
:
ids
}).
then
((
response
)
=>
{
response
.
data
.
results
.
forEach
(
r
=>
{
self
.
plts
.
push
(
r
)
})
self
.
success
()
},
error
=>
{
self
.
errored
(
error
.
backendErrors
)
})
}
},
computed
:
{
...
mapState
({
queueTracks
:
state
=>
state
.
queue
.
tracks
}),
status
()
{
if
(
this
.
isLoading
)
{
return
'
loading
'
}
if
(
this
.
errors
.
length
>
0
)
{
return
'
errored
'
}
return
'
saved
'
}
},
watch
:
{
plts
:
{
handler
(
newValue
)
{
newValue
.
forEach
((
e
,
i
)
=>
{
e
.
index
=
i
})
this
.
$emit
(
'
tracks-updated
'
,
newValue
)
},
deep
:
true
}
}
}
</
script
>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<
style
scoped
>
</
style
>
This diff is collapsed.
Click to expand it.
front/src/router/index.js
+
2
−
1
View file @
1e64f3db
...
...
@@ -21,7 +21,7 @@ import RadioBuilder from '@/components/library/radios/Builder'
import
BatchList
from
'
@/components/library/import/BatchList
'
import
BatchDetail
from
'
@/components/library/import/BatchDetail
'
import
RequestsList
from
'
@/components/requests/RequestsList
'
import
PlaylistDetail
from
'
@/views/playlists/Detail
'
import
Favorites
from
'
@/components/favorites/List
'
Vue
.
use
(
Router
)
...
...
@@ -110,6 +110,7 @@ export default new Router({
},
{
path
:
'
radios/build
'
,
name
:
'
library.radios.build
'
,
component
:
RadioBuilder
,
props
:
true
},
{
path
:
'
radios/build/:id
'
,
name
:
'
library.radios.edit
'
,
component
:
RadioBuilder
,
props
:
true
},
{
path
:
'
playlists/:id
'
,
name
:
'
library.playlists.detail
'
,
component
:
PlaylistDetail
,
props
:
true
},
{
path
:
'
artists/:id
'
,
name
:
'
library.artists.detail
'
,
component
:
LibraryArtist
,
props
:
true
},
{
path
:
'
albums/:id
'
,
name
:
'
library.albums.detail
'
,
component
:
LibraryAlbum
,
props
:
true
},
{
path
:
'
tracks/:id
'
,
name
:
'
library.tracks.detail
'
,
component
:
LibraryTrack
,
props
:
true
},
...
...
This diff is collapsed.
Click to expand it.
front/src/views/playlists/Detail.vue
0 → 100644
+
88
−
0
View file @
1e64f3db
<
template
>
<div
v-if=
"playlist"
>
<div
class=
"ui head vertical center aligned stripe segment"
>
<div
class=
"segment-content"
>
<h2
class=
"ui center aligned icon header"
>
<i
class=
"circular inverted list yellow icon"
></i>
<div
class=
"content"
>
{{
playlist
.
name
}}
<div
class=
"sub header"
>
Playlist containing
{{
playlistTracks
.
length
}}
tracks,
by
<username
:username=
"playlist.user.username"
></username>
</div>
</div>
</h2>
<div
class=
"ui hidden divider"
></div>
</button>
<play-button
class=
"orange"
:tracks=
"tracks"
>
Play all
</play-button>
<button
class=
"ui icon button"
v-if=
"playlist.user.id === $store.state.auth.profile.id"
@
click=
"edit = !edit"
>
<i
class=
"pencil icon"
></i>
<template
v-if=
"edit"
>
End edition
</
template
>
<
template
v-else
>
Edit...
</
template
>
</button>
</div>
</div>
<div
v-if=
"tracks.length > 0"
class=
"ui vertical stripe segment"
>
<
template
v-if=
"edit"
>
<playlist-editor
@
tracks-updated=
"updatePlts"
:playlist=
"playlist"
:playlist-tracks=
"playlistTracks"
></playlist-editor>
</
template
>
<
template
v-else
>
<h2>
Tracks
</h2>
<track-table
:display-position=
"true"
:tracks=
"tracks"
></track-table>
</
template
>
</div>
</div>
</template>
<
script
>
import
axios
from
'
axios
'
import
TrackTable
from
'
@/components/audio/track/Table
'
import
RadioButton
from
'
@/components/radios/Button
'
import
PlayButton
from
'
@/components/audio/PlayButton
'
import
PlaylistEditor
from
'
@/components/playlists/Editor
'
export
default
{
props
:
{
id
:
{
required
:
true
}
},
components
:
{
PlaylistEditor
,
TrackTable
,
PlayButton
,
RadioButton
},
data
:
function
()
{
return
{
edit
:
false
,
playlist
:
null
,
tracks
:
[],
playlistTracks
:
[]
}
},
created
:
function
()
{
this
.
fetch
()
},
methods
:
{
updatePlts
(
v
)
{
this
.
playlistTracks
=
v
this
.
tracks
=
v
.
map
((
e
,
i
)
=>
{
let
track
=
e
.
track
track
.
position
=
i
+
1
return
track
})
},
fetch
:
function
()
{
let
self
=
this
let
url
=
'
playlists/
'
+
this
.
id
+
'
/
'
axios
.
get
(
url
).
then
((
response
)
=>
{
self
.
playlist
=
response
.
data
axios
.
get
(
url
+
'
tracks
'
).
then
((
response
)
=>
{
self
.
updatePlts
(
response
.
data
.
results
)
})
})
}
}
}
</
script
>
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment