From 6a9a34d244ddc4c4298e5c5364bb214f420691cf Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Wed, 21 Mar 2018 12:19:07 +0100
Subject: [PATCH] Can now clear playlist

---
 api/funkwhale_api/playlists/views.py          |  8 ++++++
 api/tests/playlists/test_views.py             | 12 ++++++++
 .../src/components/common/DangerousButton.vue | 10 +++++--
 front/src/components/playlists/Editor.vue     | 28 +++++++++++++++++--
 4 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/api/funkwhale_api/playlists/views.py b/api/funkwhale_api/playlists/views.py
index 4880b1886d..7b2e7651d3 100644
--- a/api/funkwhale_api/playlists/views.py
+++ b/api/funkwhale_api/playlists/views.py
@@ -75,6 +75,14 @@ class PlaylistViewSet(
         }
         return Response(data, status=201)
 
+    @detail_route(methods=['delete'])
+    @transaction.atomic
+    def clear(self, request, *args, **kwargs):
+        playlist = self.get_object()
+        playlist.playlist_tracks.all().delete()
+        playlist.save(update_fields=['modification_date'])
+        return Response(status=204)
+
     def get_queryset(self):
         return self.queryset.filter(
             fields.privacy_level_query(self.request.user))
diff --git a/api/tests/playlists/test_views.py b/api/tests/playlists/test_views.py
index ae3fd00740..e70fef6f0d 100644
--- a/api/tests/playlists/test_views.py
+++ b/api/tests/playlists/test_views.py
@@ -170,3 +170,15 @@ def test_can_add_multiple_tracks_at_once_via_api(
     for plt in playlist.playlist_tracks.order_by('index'):
         assert response.data['results'][plt.index]['id'] == plt.id
         assert plt.track == tracks[plt.index]
+
+
+def test_can_clear_playlist_from_api(
+        factories, mocker, logged_in_api_client):
+    playlist = factories['playlists.Playlist'](user=logged_in_api_client.user)
+    plts = factories['playlists.PlaylistTrack'].create_batch(
+        size=5, playlist=playlist)
+    url = reverse('api:v1:playlists-clear', kwargs={'pk': playlist.pk})
+    response = logged_in_api_client.delete(url)
+
+    assert response.status_code == 204
+    assert playlist.playlist_tracks.count() == 0
diff --git a/front/src/components/common/DangerousButton.vue b/front/src/components/common/DangerousButton.vue
index 03a579d296..525b4c48ff 100644
--- a/front/src/components/common/DangerousButton.vue
+++ b/front/src/components/common/DangerousButton.vue
@@ -1,5 +1,5 @@
 <template>
-  <div @click="showModal = true" class="ui red button">
+  <div @click="showModal = true" :class="['ui', color, {disabled: disabled}, 'button']" :disabled="disabled">
     <slot></slot>
 
     <modal class="small" :show.sync="showModal">
@@ -13,7 +13,7 @@
       </div>
       <div class="actions">
         <div class="ui cancel button">Cancel</div>
-        <div class="ui confirm red button" @click="confirm">
+        <div :class="['ui', 'confirm', color, 'button']" @click="confirm">
           <slot name="modal-confirm">Confirm</slot>
         </div>
       </div>
@@ -25,7 +25,11 @@
 import Modal from '@/components/semantic/Modal'
 
 export default {
-  props: ['action'],
+  props: {
+    action: {type: Function, required: true},
+    disabled: {type: Boolean, default: false},
+    color: {type: String, default: 'red'}
+  },
   components: {
     Modal
   },
diff --git a/front/src/components/playlists/Editor.vue b/front/src/components/playlists/Editor.vue
index 6f9ddfcd4b..b4354be6aa 100644
--- a/front/src/components/playlists/Editor.vue
+++ b/front/src/components/playlists/Editor.vue
@@ -2,12 +2,20 @@
   <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>
       <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>
+        :class="['ui', {disabled: queueTracks.length === 0}, 'labeled', 'icon', 'button']"
+        title="Copy tracks from current queue to playlist">
+          <i class="plus icon"></i> Insert from queue ({{ queueTracks.length }} tracks)</div>
+
+      <dangerous-button :disabled="plts.length === 0" class="labeled right floated icon" color='yellow' :action="clearPlaylist">
+        <i class="eraser icon"></i> Clear playlist
+        <p slot="modal-header">Do you want to clear the playlist "{{ playlist.name }}"?</p>
+        <p slot="modal-content">This will remove all tracks from this playlist and cannot be undone.</p>
+        <p slot="modal-confirm">Clear playlist</p>
+      </dangerous-button>
     </div>
     <h5 class="ui header">Status</h5>
     <div>
@@ -95,6 +103,19 @@ export default {
       let url = 'playlist-tracks/' + plt.id + '/'
       axios.delete(url).then((response) => {
         self.success()
+        self.$store.dispatch('playlists/fetchOwn')
+      }, error => {
+        self.errored(error.backendErrors)
+      })
+    },
+    clearPlaylist () {
+      this.plts = []
+      let self = this
+      self.isLoading = true
+      let url = 'playlists/' + this.playlist.id + '/clear'
+      axios.delete(url).then((response) => {
+        self.success()
+        self.$store.dispatch('playlists/fetchOwn')
       }, error => {
         self.errored(error.backendErrors)
       })
@@ -111,6 +132,7 @@ export default {
           self.plts.push(r)
         })
         self.success()
+        self.$store.dispatch('playlists/fetchOwn')
       }, error => {
         self.errored(error.backendErrors)
       })
-- 
GitLab