From b0d3cdfc5a579b594edb01fef51ad40a860ff1b8 Mon Sep 17 00:00:00 2001 From: heyarne Date: Fri, 8 Mar 2019 08:47:58 +0100 Subject: [PATCH] Implement drag and drop reordering in current queue --- .../components/audio_player/events.cljs | 5 +++ .../components/current_queue/views.cljs | 16 ++++++-- .../components/sortable/views.cljs | 18 ++++++-- src/sass/app.sass | 41 +++++++++++++++++++ 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/cljs/airsonic_ui/components/audio_player/events.cljs b/src/cljs/airsonic_ui/components/audio_player/events.cljs index 0ddff43..4ce845f 100644 --- a/src/cljs/airsonic_ui/components/audio_player/events.cljs +++ b/src/cljs/airsonic_ui/components/audio_player/events.cljs @@ -56,6 +56,11 @@ (fn [db [_ song]] (update-in db [:audio :current-playlist] #(playlist/enqueue-last % song)))) +(rf/reg-event-db + :audio-player/move-song + (fn [db [_ from-idx to-idx]] + (update-in db [:audio :current-playlist] #(playlist/move-song % from-idx to-idx)))) + (rf/reg-event-fx :audio-player/toggle-play-pause (fn [_ _] diff --git a/src/cljs/airsonic_ui/components/current_queue/views.cljs b/src/cljs/airsonic_ui/components/current_queue/views.cljs index 91b0edf..3f6e512 100644 --- a/src/cljs/airsonic_ui/components/current_queue/views.cljs +++ b/src/cljs/airsonic_ui/components/current_queue/views.cljs @@ -46,14 +46,21 @@ (defn song-table [{:keys [songs current-song]}] [:table.song-listing-table.table.is-fullwidth + [:thead>tr + [:td.is-narrow] + [:td.song-artist "Artist"] + [:td.song-title "Title"] + [:td.song-duration "Duration"] + [:td.is-narrow]] [sortable/sortable-component - {:container [:tbody] - :items songs + {:items songs + :container [:tbody] + :helper-class "sortable-is-moving" :render-item (fn [{[idx song] :value}] [(if (= (:id song) (:id current-song)) :tr.is-playing :tr) - [:td.sort-handle.is-narrow [:> SortHandle]] + [:td.sortable-handle.is-narrow [:> SortHandle]] [:td.song-artist [artist-link song]] [:td.song-title [song-link song idx]] [:td.song-duration (helpers/format-duration (:duration song) :brief? true)] @@ -61,7 +68,8 @@ :on-sort-end (fn [{:keys [old-idx new-idx]}] - )}]]) + (println "moving from" old-idx "to" new-idx) + (dispatch [:audio-player/move-song old-idx new-idx]))}]]) (defn current-queue [] [:section.section>div.container diff --git a/src/cljs/airsonic_ui/components/sortable/views.cljs b/src/cljs/airsonic_ui/components/sortable/views.cljs index 17fd468..0c19d4c 100644 --- a/src/cljs/airsonic_ui/components/sortable/views.cljs +++ b/src/cljs/airsonic_ui/components/sortable/views.cljs @@ -60,13 +60,25 @@ (defonce saved-snapshot (atom nil)) -(defn sortable-component [{:keys [container items render-item on-sort-end]}] +(defn sortable-component + "This function allows us to generate sortable components in a reusable way. + It takes a prop-map with several keys: + + - :container A hiccup-vector that will be used as the container + - :items A seq containing the values we want to render and sort + - :render-item Decides how we render each child; will be passed {:value value} + - :on-sort-end Will be called with a map containing :old-idx & :new-idx + - :helper-class Will be appended to the element that's sorted when it's + appended to the body" + [{:keys [container items render-item on-sort-end helper-class]}] (let [Wrapper (make-wrapper {:container container :render-item render-item})] (r/create-element Wrapper #js {:items items - :helperClass "sortable-is-moving" + :helperClass helper-class + :axis "y" + :lockAxis "y" ;; save the style of all of the rows children :updateBeforeSortStart @@ -75,7 +87,7 @@ :onSortStart (fn [_] ;; the node we get passed as parameter is the original node unfortunately - (restore-snapshot @saved-snapshot (js/document.querySelector "body > tr:last-of-type"))) + (restore-snapshot @saved-snapshot (js/document.querySelector "body > :last-child"))) ;; update the state to reflect the new order :onSortEnd diff --git a/src/sass/app.sass b/src/sass/app.sass index 3df4f2c..911c787 100644 --- a/src/sass/app.sass +++ b/src/sass/app.sass @@ -322,3 +322,44 @@ font-weight: normal display: inline padding-right: 0.375rem + +.song-listing-table + tr.is-playing + background-color: $table-row-active-background-color + color: $table-row-active-color + + a, strong, td.song-duration, td.sort-handle span + color: currentColor + + span.button, div.dropdown + color: $table-color + + td + &.is-narrow + white-space: nowrap + + &.song-duration + text-align: right + + &.sortable-handle + -webkit-touch-callout: none + user-select: none + + tbody .song-duration + color: $grey-light + + tr:hover + .button + +// drag'n'drop +.sortable-handle + span + cursor: grabbing + user-select: none + +tr.sortable-is-moving.is-playing + background-color: $table-row-active-background-color + color: $table-row-active-color + + a, strong, td.song-duration, td.sort-handle span + color: currentColor