Merge branch 'add-filter-in-add-to-playlist' into 'develop'
Add field to filter existing playlists in “add to playlist…” dialog Closes #974 See merge request funkwhale/funkwhale!966
This commit is contained in:
		
						commit
						4fc54fcc1e
					
				|  | @ -0,0 +1 @@ | |||
| Support filtering playlist by name and several additional UX improvements in playlists modal (#974) | ||||
|  | @ -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> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Eliot Berriot
						Eliot Berriot