Verified Commit 4428d740 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Fixed #344: Implemented a basic but functionnal Github-like search on federated tracks list

parent d713ad17
import django_filters import django_filters
from funkwhale_api.common import fields from funkwhale_api.common import fields
from funkwhale_api.common import search
from . import models from . import models
...@@ -23,8 +24,21 @@ class LibraryFilter(django_filters.FilterSet): ...@@ -23,8 +24,21 @@ class LibraryFilter(django_filters.FilterSet):
class LibraryTrackFilter(django_filters.FilterSet): class LibraryTrackFilter(django_filters.FilterSet):
library = django_filters.CharFilter("library__uuid") library = django_filters.CharFilter("library__uuid")
status = django_filters.CharFilter(method="filter_status") status = django_filters.CharFilter(method="filter_status")
q = fields.SearchFilter( q = fields.SmartSearchFilter(
search_fields=["artist_name", "title", "album_title", "library__actor__domain"] config=search.SearchConfig(
search_fields={
"domain": {"to": "library__actor__domain"},
"artist": {"to": "artist_name"},
"album": {"to": "album_title"},
"title": {"to": "title"},
},
filter_fields={
"domain": {"to": "library__actor__domain"},
"artist": {"to": "artist_name__iexact"},
"album": {"to": "album_title__iexact"},
"title": {"to": "title__iexact"},
},
)
) )
def filter_status(self, queryset, field_name, value): def filter_status(self, queryset, field_name, value):
......
Implemented a basic but functionnal Github-like search on federated tracks list (#344)
Improved search on federated tracks list
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Having a powerful but easy-to-use search is important but difficult to achieve, especially
if you do not want to have a real complex search interface.
Github does a pretty good job with that, using a structured but simple query system
(See https://help.github.com/articles/searching-issues-and-pull-requests/#search-only-issues-or-pull-requests).
This release implements a limited but working subset of this query system. You can use it only on the federated
tracks list (/manage/federation/tracks) at the moment, but depending on feedback it will be rolled-out on other pages as well.
This is the type of query you can run:
- ``hello world``: search for "hello" and "world" in all the available fields
- ``hello in:artist`` search for results where artist name is "hello"
- ``spring in:artist,album`` search for results where artist name or album title contain "spring"
- ``artist:hello`` search for results where artist name equals "hello"
- ``artist:"System of a Down" domain:instance.funkwhale`` search for results where artist name equals "System of a Down" and inside "instance.funkwhale" library
...@@ -236,6 +236,7 @@ html, body { ...@@ -236,6 +236,7 @@ html, body {
.discrete.link { .discrete.link {
color: rgba(0, 0, 0, 0.87); color: rgba(0, 0, 0, 0.87);
cursor: pointer;
} }
.floated.buttons .button ~ .dropdown { .floated.buttons .button ~ .dropdown {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div> <div>
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui field"> <div class="ui six wide field">
<label><translate>Search</translate></label> <label><translate>Search</translate></label>
<input type="text" v-model="search" :placeholder="labels.searchPlaceholder" /> <input type="text" v-model="search" :placeholder="labels.searchPlaceholder" />
</div> </div>
...@@ -56,16 +56,16 @@ ...@@ -56,16 +56,16 @@
<span :title="scope.obj.title">{{ scope.obj.title|truncate(30) }}</span> <span :title="scope.obj.title">{{ scope.obj.title|truncate(30) }}</span>
</td> </td>
<td> <td>
<span :title="scope.obj.artist_name">{{ scope.obj.artist_name|truncate(30) }}</span> <span class="discrete link" @click="updateSearch({key: 'artist', value: scope.obj.artist_name})" :title="scope.obj.artist_name">{{ scope.obj.artist_name|truncate(30) }}</span>
</td> </td>
<td> <td>
<span :title="scope.obj.album_title">{{ scope.obj.album_title|truncate(20) }}</span> <span class="discrete link" @click="updateSearch({key: 'album', value: scope.obj.album_title})" :title="scope.obj.album_title">{{ scope.obj.album_title|truncate(20) }}</span>
</td> </td>
<td> <td>
<human-date :date="scope.obj.published_date"></human-date> <human-date :date="scope.obj.published_date"></human-date>
</td> </td>
<td v-if="showLibrary"> <td v-if="showLibrary">
{{ scope.obj.library.actor.domain }} <span class="discrete link" @click="updateSearch({key: 'domain', value: scope.obj.library.actor.domain})">{{ scope.obj.library.actor.domain }}</span>
</td> </td>
</template> </template>
</action-table> </action-table>
...@@ -120,6 +120,12 @@ export default { ...@@ -120,6 +120,12 @@ export default {
this.fetchData() this.fetchData()
}, },
methods: { methods: {
updateSearch ({key, value}) {
if (value.indexOf(' ') > -1) {
value = `"${value}"`
}
this.search = `${key}:${value}`
},
fetchData () { fetchData () {
let params = _.merge({ let params = _.merge({
'page': this.page, 'page': this.page,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment