From 27538ccd3443ea519ff8b48ba74e2e2dcbfb405b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9lanie=20Chauvel?= <perso@hack-libre.org> Date: Sat, 7 Dec 2019 17:06:24 +0100 Subject: [PATCH] =?UTF-8?q?Add=20field=20to=20filter=20existing=20playlist?= =?UTF-8?q?s=20in=20=E2=80=9Cadd=20to=20playlist=E2=80=A6=E2=80=9D=20dialo?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also fix the duplicate track add confirmation margins Fix #974 --- changes/changelog.d/974.enhancement | 1 + .../components/playlists/PlaylistModal.vue | 69 +++++++++++++------ 2 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 changes/changelog.d/974.enhancement diff --git a/changes/changelog.d/974.enhancement b/changes/changelog.d/974.enhancement new file mode 100644 index 0000000000..0d59fbd0a2 --- /dev/null +++ b/changes/changelog.d/974.enhancement @@ -0,0 +1 @@ +Support filtering playlist by name and several additional UX improvements in playlists modal (#974) diff --git a/front/src/components/playlists/PlaylistModal.vue b/front/src/components/playlists/PlaylistModal.vue index 714d9feba5..7ada395b60 100644 --- a/front/src/components/playlists/PlaylistModal.vue +++ b/front/src/components/playlists/PlaylistModal.vue @@ -1,29 +1,30 @@ <template> <modal @update:show="update" :show="$store.state.playlists.showModal"> <div class="header"> - <translate translate-context="Popup/Playlist/Title/Verb">Manage playlists</translate> - </div> - <div class="scrolling content"> - <div class="description"> - <template v-if="track"> - <h4 class="ui header"><translate translate-context="Popup/Playlist/Title">Current track</translate></h4> - <span + <template v-if="track"> + <h2 class="ui header"> + <translate translate-context="Popup/Playlist/Title/Verb">Add to playlist</translate> + <div + class="ui sub header" translate-context="Popup/Playlist/Paragraph" v-translate="{artist: track.artist.name, title: track.title}" :translate-params="{artist: track.artist.name, title: track.title}"> "%{ title }", by %{ artist } - </span> - <div class="ui divider"></div> - </template> - - <playlist-form :key="formKey"></playlist-form> - <div class="ui divider"></div> + </div> + </h2> + </template> + <translate v-else translate-context="Popup/Playlist/Title/Verb">Manage playlists</translate> + </div> + <div class="scrolling content"> + <playlist-form :key="formKey"></playlist-form> + <div class="ui divider"></div> + <div v-if="playlists.length > 0"> <div v-if="showDuplicateTrackAddConfirmation" class="ui warning message"> <p translate-context="Popup/Playlist/Paragraph" v-translate="{track: track.title, playlist: duplicateTrackAddInfo.playlist_name}" :translate-params="{track: track.title, playlist: duplicateTrackAddInfo.playlist_name}"><strong>%{ track }</strong> is already in <strong>%{ playlist }</strong>.</p> <button - @click="update(false)" + @click="duplicateTrackAddConfirm(false)" class="ui small cancel button"><translate translate-context="*/*/Button.Label/Verb">Cancel</translate> </button> <button @@ -37,10 +38,16 @@ <li v-for="error in errors">{{ error }}</li> </ul> </div> - </div> - <div v-if="playlists.length > 0"> <h4 class="ui header"><translate translate-context="Popup/Playlist/Title">Available playlists</translate></h4> - <table class="ui unstackable very basic table"> + <div class="ui form"> + <div class="fields"> + <div class="field"> + <label for="playlist-name-filter"><translate translate-context="Popup/Playlist/Label">Filter</translate></label> + <input name="playlist-name-filter" v-model="playlistNameFilter" type="text" class="inline" :placeholder="labels.filterPlaylistField" /> + </div> + </div> + </div> + <table v-if="sortedPlaylists.length > 0" class="ui unstackable very basic table"> <thead> <tr> <th></th> @@ -73,6 +80,13 @@ </tr> </tbody> </table> + <template v-else> + <div class="ui small placeholder segment"> + <div class="ui header"> + <translate translate-context="Popup/Playlist/EmptyState">No results matching your filter</translate> + </div> + </div> + </template> </div> <template v-else> <div class="ui placeholder segment"> @@ -93,7 +107,10 @@ </template> <script> -import _ from '@/lodash' +import filter from "lodash/fp/filter"; +import sortBy from "lodash/fp/sortBy"; +import flow from "lodash/fp/flow"; + import axios from 'axios' import {mapState} from 'vuex' @@ -110,6 +127,7 @@ export default { return { formKey: String(new Date()), errors: [], + playlistNameFilter: '', duplicateTrackAddInfo: {}, showDuplicateTrackAddConfirmation: false, lastSelectedPlaylist: -1, @@ -142,6 +160,9 @@ export default { self.showDuplicateTrackAddConfirmation = false } }) + }, + duplicateTrackAddConfirm (v) { + this.showDuplicateTrackAddConfirmation = v } }, computed: { @@ -151,11 +172,16 @@ export default { }), labels () { return { - addToPlaylist: this.$pgettext('Popup/Playlist/Table.Button.Tooltip/Verb', 'Add to this playlist') + addToPlaylist: this.$pgettext('Popup/Playlist/Table.Button.Tooltip/Verb', 'Add to this playlist'), + filterPlaylistField: this.$pgettext('Popup/Playlist/Form/Placeholder', 'Enter playlist name') } }, sortedPlaylists () { - let p = _.sortBy(this.playlists, [(e) => { return e.modification_date }]) + let regexp = new RegExp(this.playlistNameFilter, 'i'); + let p = flow( + filter((e) => e.name.match(regexp) !== null), + sortBy((e) => { return e.modification_date }), + )(this.playlists) p.reverse() return p } @@ -175,4 +201,7 @@ export default { <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> +.ui.small.placeholder.segment { + min-height: auto; +} </style> -- GitLab