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