Moving search context to URI component

This commit is contained in:
James Barnsley
2018-01-05 21:31:59 +13:00
parent 90eda428c2
commit 910f03a8c8
7 changed files with 134 additions and 76 deletions

View File

@ -21,14 +21,14 @@ class SearchForm extends React.Component{
componentDidMount(){
if (this.props.query){
this.setState({query: this.props.query})
var query = this.props.query.replace("search:","");
this.setState({query: query});
}
}
componentWillReceiveProps(newProps){
if (newProps.query && newProps.query != this.state.query && !this.state.in_focus){
this.setState({query: newProps.query});
console.log(newProps.query);
this.setState({query: newProps.query.replace("search:","")});
}
}
@ -51,7 +51,21 @@ class SearchForm extends React.Component{
break
default:
hashHistory.push(global.baseURL+'search/search:'+this.props.view+':'+encodeURIComponent(this.state.query));
var available_views = ["artist","album","playlist","track"];
var view_defined = false;
var query = this.state.query;
for (var i = 0; i < available_views.length; i++){
if (query.startsWith(available_views[i]+':')){
view_defined = true;
}
}
if (!view_defined){
query = "all:"+query;
}
hashHistory.push(global.baseURL+'search/search:'+query);
break
}

View File

@ -380,7 +380,7 @@ export let sourceIcon = function(uri,source = null){
* @param element = string, the element we wish to extract
* @param uri = string
**/
export let getFromUri = function(element,uri){
export let getFromUri = function(element, uri = ""){
var exploded = uri.split(':');
var namespace = exploded[0]
@ -439,6 +439,22 @@ export let getFromUri = function(element,uri){
return exploded[2]
}
break
case 'searchcontext':
if (exploded[0] == "search"){
var available_views = ["all","artist","album","playlist","track"];
var view = available_views.indexOf(exploded[1]);
if (view > -1){
return exploded[1];
}
}
break
case 'searchterm':
if (exploded[0] == "search"){
return exploded[2];
}
break
}
return null
}

View File

@ -67,7 +67,7 @@ ReactDOM.render(
<Route path="settings/debug" component={Debug} />
<Route path="settings(/:sub_view)" component={Settings} />
<Route path="search(/search::view::query)" component={Search} />
<Route path="search(/:query)" component={Search} />
<Route path="album/:uri" component={Album} />
<Route path="artist/:uri(/:sub_view)" component={Artist} />
<Route path="playlist/:uri" component={Playlist} />

View File

@ -218,7 +218,7 @@ class Artist extends React.Component{
<div className="col w5"></div>
{related_artists.length > 0 ? <div className="col w25 related-artists"><h4>Related artists</h4><div className="list-wrapper"><RelatedArtists artists={related_artists.slice(0,6)} /></div><Link to={global.baseURL+'artist/'+this.props.params.uri+'/related-artists'} className="button">All related artists</Link></div> : null}
{related_artists.length > 0 ? <div className="col w25 related-artists"><h4>Related artists</h4><div className="list-wrapper"><RelatedArtists artists={related_artists.slice(0,6)} /></div><Link to={global.baseURL+'artist/'+this.props.params.uri+'/related-artists'} className="button grey">All related artists</Link></div> : null}
<div className="cf"></div>

View File

@ -29,63 +29,64 @@ class Search extends React.Component{
}
componentDidMount(){
var view = 'all';
if (this.props.params && this.props.params.view){
view = this.props.params.view;
}
var query = false;
var context = "all";
var term = null;
if (this.props.params && this.props.params.query && this.props.params.query !== ''){
query = this.props.params.query;
context = helpers.getFromUri("searchcontext",this.props.params.query);
term = helpers.getFromUri("searchterm",this.props.params.query);
}
// Auto-focus on the input field
//$(document).find('.search-form input').focus();
$(document).find('.search-form input').focus();
if (query){
if (context && term){
if (this.props.mopidy_connected && this.props.search_uri_schemes){
this.props.mopidyActions.getSearchResults(view, query)
this.props.mopidyActions.getSearchResults(context, term)
}
if (this.props.spotify_connected && this.props.search_uri_schemes && this.props.search_uri_schemes.includes('spotify:')){
this.props.spotifyActions.getSearchResults(view, query)
this.props.spotifyActions.getSearchResults(context, term)
}
}
}
componentWillReceiveProps(newProps){
if (newProps.params && newProps.params.view){
var view = newProps.params.view;
if (this.props.params && this.props.params.query && this.props.params.query !== ''){
var old_context = helpers.getFromUri("searchcontext",this.props.params.query);
var old_term = helpers.getFromUri("searchterm",this.props.params.query);
} else {
var view = 'all';
var old_context = "all";
var old_term = null;
}
if (newProps.params && newProps.params.query && newProps.params.query !== ''){
var query = newProps.params.query;
var context = helpers.getFromUri("searchcontext",newProps.params.query);
var term = helpers.getFromUri("searchterm",newProps.params.query);
} else {
var query = null;
var context = "all";
var term = null;
}
if (query && !this.props.mopidy_connected && newProps.mopidy_connected){
this.props.mopidyActions.getSearchResults(view, query)
if (term && !this.props.mopidy_connected && newProps.mopidy_connected){
this.props.mopidyActions.getSearchResults(context, term);
}
if (query && !this.props.spotify_connected && newProps.spotify_connected && newProps.search_uri_schemes.includes('spotify:')){
this.props.spotifyActions.getSearchResults(view, query)
if (term && !this.props.spotify_connected && newProps.spotify_connected && newProps.search_uri_schemes.includes('spotify:')){
this.props.spotifyActions.getSearchResults(context, term);
}
// Search changed
if (query && query !== this.props.params.query){
if (term && context && term !== old_term){
this.props.mopidyActions.clearSearchResults();
this.props.spotifyActions.clearSearchResults();
if (this.props.mopidy_connected && this.props.search_uri_schemes){
this.props.mopidyActions.getSearchResults(view, query)
this.props.mopidyActions.getSearchResults(context, term)
}
if (this.props.mopidy_connected && this.props.search_uri_schemes && this.props.search_uri_schemes.includes('spotify:')){
this.props.spotifyActions.getSearchResults(view, query)
this.props.spotifyActions.getSearchResults(context, term)
}
}
}
@ -108,6 +109,12 @@ class Search extends React.Component{
renderResults(){
var context = helpers.getFromUri("searchcontext",this.props.params.query);
var term = helpers.getFromUri("searchterm",this.props.params.query);
if (!context){
context = "all";
}
var spotify_search_enabled = (this.props.search_settings && this.props.search_settings.spotify);
if (this.props.sort == 'uri'){
@ -152,16 +159,17 @@ class Search extends React.Component{
}
tracks = helpers.sortItems(tracks, this.props.sort, this.props.sort_reverse, sort_map);
switch (this.props.params.view){
switch (context){
case 'artist':
return (
<div>
<h4>
Artists
<URILink unencoded type="search" uri={"search:all:"+this.props.params.query}>
Back to all
<URILink unencoded type="search" uri={"search:all:"+term}>
Search
</URILink>
&nbsp; <FontAwesome name="angle-right" />&nbsp;
Artists
</h4>
<section className="grid-wrapper">
<ArtistGrid artists={artists} show_source_icon />
@ -175,10 +183,11 @@ class Search extends React.Component{
return (
<div>
<h4>
Albums
<URILink unencoded type="search" uri={"search:all:"+this.props.params.query}>
Back to all
<URILink unencoded type="search" uri={"search:all:"+term}>
Search
</URILink>
&nbsp; <FontAwesome name="angle-right" />&nbsp;
Albums
</h4>
<section className="grid-wrapper">
<AlbumGrid albums={albums} show_source_icon />
@ -192,10 +201,11 @@ class Search extends React.Component{
return (
<div>
<h4>
Playlists
<URILink unencoded type="search" uri={"search:all:"+this.props.params.query}>
Back to all
<URILink unencoded type="search" uri={"search:all:"+term}>
Search
</URILink>
&nbsp; <FontAwesome name="angle-right" />&nbsp;
Playlists
</h4>
<section className="grid-wrapper">
<PlaylistGrid playlists={playlists} show_source_icon />
@ -209,13 +219,14 @@ class Search extends React.Component{
return (
<div>
<h4>
Tracks
<URILink unencoded type="search" uri={"search:all:"+this.props.params.query}>
Back to all
<URILink unencoded type="search" uri={"search:all:"+term}>
Search
</URILink>
&nbsp; <FontAwesome name="angle-right" />&nbsp;
Tracks
</h4>
<section className="list-wrapper">
<TrackList tracks={tracks} uri={'iris:search:'+this.props.params.query} show_source_icon />
<TrackList tracks={tracks} uri={this.props.params.query} show_source_icon />
<LazyLoadListener enabled={this.props['tracks_more'] && spotify_search_enabled} loadMore={ () => this.loadMore('tracks') }/>
</section>
</div>
@ -228,14 +239,14 @@ class Search extends React.Component{
if (artists.length > 0){
var artists_section = (
<section>
<div className="inner">
<h4>
Artists
<URILink unencoded type="search" uri={"search:artist:"+this.props.params.query}>
More
</URILink>
</h4>
<ArtistGrid show_source_icon single_row artists={artists.slice(0,5)} />
<div className="inner">
<URILink unencoded type="search" uri={"search:artist:"+term}>
<h4>Artists</h4>
</URILink>
<ArtistGrid show_source_icon artists={artists.slice(0,5)} />
{artists.length > 4 ? <URILink unencoded type="search" uri={"search:artist:"+term} className="button grey">
All artists ({artists.length})
</URILink> : null}
</div>
</section>
)
@ -246,14 +257,14 @@ class Search extends React.Component{
if (albums.length > 0){
var albums_section = (
<section>
<div className="inner">
<h4>
Albums
<URILink unencoded type="search" uri={"search:album:"+this.props.params.query}>
More
</URILink>
</h4>
<AlbumGrid show_source_icon single_row albums={albums.slice(0,5)} />
<div className="inner">
<URILink unencoded type="search" uri={"search:album:"+term}>
<h4>Albums</h4>
</URILink>
<AlbumGrid show_source_icon albums={albums.slice(0,5)} />
{albums.length > 4 ? <URILink unencoded type="search" uri={"search:album:"+term} className="button grey">
All albums ({albums.length})
</URILink> : null}
</div>
</section>
)
@ -264,14 +275,14 @@ class Search extends React.Component{
if (playlists.length > 0){
var playlists_section = (
<section>
<div className="inner">
<h4>
Playlists
<URILink unencoded type="search" uri={"search:playlist:"+this.props.params.query}>
More
</URILink>
</h4>
<PlaylistGrid show_source_icon single_row playlists={playlists.slice(0,5)} />
<div className="inner">
<URILink unencoded type="search" uri={"search:playlist:"+term}>
<h4>Playlists</h4>
</URILink>
<PlaylistGrid show_source_icon playlists={playlists.slice(0,5)} />
{playlists.length > 4 ? <URILink unencoded type="search" uri={"search:playlist:"+term} className="button grey">
All playlists ({playlists.length})
</URILink> : null}
</div>
</section>
)
@ -282,8 +293,7 @@ class Search extends React.Component{
if (tracks.length > 0){
var tracks_section = (
<section className="list-wrapper">
<h4>Tracks</h4>
<TrackList tracks={tracks} uri={'iris:search:'+this.props.params.query} show_source_icon />
<TrackList tracks={tracks} uri={this.props.params.query} show_source_icon />
<LazyLoadListener loading={this.props['tracks_more'] && spotify_search_enabled} loadMore={ () => this.loadMore('tracks') }/>
</section>
)

View File

@ -112,6 +112,11 @@ input[type="submit"] {
background: $white;
}
&.grey {
color: $white;
background: $grey;
}
&.confirming,
&.destructive {
background: $red;

View File

@ -15,7 +15,7 @@
font-weight: 700;
height: 3.1rem;
background: transparent;
border-bottom: 2px solid transparent;
border-bottom: 2px solid $grey;
border-radius: 0;
/* handle Safari's ridiculous non-vertical centering */
@ -31,12 +31,25 @@
}
}
h4 {
margin-bottom: 20px;
.search-result-sections {
padding-bottom: 30px;
a {
font-size: 14px;
margin-left: 10px;
section {
width: 31%;
float: left;
margin-right: 3.5%;
&:last-child {
margin-right: 0;
}
.grid-item {
@include grid_item(2);
&:nth-child(1n+5){
display: none;
}
}
}
}