Search
This commit is contained in:
@ -3,6 +3,7 @@ import React, { PropTypes } from 'react'
|
||||
import FontAwesome from 'react-fontawesome'
|
||||
|
||||
import Icon from './Icon'
|
||||
import SearchForm from './SearchForm'
|
||||
import SidebarToggleButton from './SidebarToggleButton'
|
||||
import ContextMenuTrigger from './ContextMenuTrigger'
|
||||
|
||||
@ -43,13 +44,24 @@ export default class Header extends React.Component{
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<header className={(this.props.className ? this.props.className : null)}>
|
||||
<Icon name={ this.props.icon } />
|
||||
<SidebarToggleButton />
|
||||
<h2>{ this.props.title }</h2>
|
||||
{this.renderOptions()}
|
||||
</header>
|
||||
);
|
||||
if (this.props.search){
|
||||
return (
|
||||
<header className={(this.props.className ? this.props.className : null)}>
|
||||
<Icon name="search" />
|
||||
<SidebarToggleButton />
|
||||
<SearchForm />
|
||||
{this.renderOptions()}
|
||||
</header>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<header className={(this.props.className ? this.props.className : null)}>
|
||||
<Icon name={this.props.icon} />
|
||||
<SidebarToggleButton />
|
||||
<h2>{ this.props.title }</h2>
|
||||
{this.renderOptions()}
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -49,7 +49,7 @@ class SearchForm extends React.Component{
|
||||
<form className={this.props.context+' search-form'} onSubmit={ e => this.handleSubmit(e) }>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search"
|
||||
placeholder="Start typing..."
|
||||
onChange={ e => this.setState({ query: e.target.value }) }
|
||||
value={ this.state.query } />
|
||||
</form>
|
||||
|
||||
@ -5,7 +5,6 @@ import { bindActionCreators } from 'redux'
|
||||
import { Link } from 'react-router'
|
||||
|
||||
import Icon from './Icon'
|
||||
import SearchForm from './SearchForm'
|
||||
import Dropzones from './Dropzones'
|
||||
import Thumbnail from './Thumbnail'
|
||||
|
||||
@ -22,9 +21,6 @@ class Sidebar extends React.Component{
|
||||
return (
|
||||
<aside>
|
||||
<div className="liner">
|
||||
|
||||
<SearchForm context="sidebar" />
|
||||
|
||||
<nav>
|
||||
|
||||
<section>
|
||||
@ -32,6 +28,10 @@ class Sidebar extends React.Component{
|
||||
<Icon name="play" />
|
||||
Now playing
|
||||
</Link>
|
||||
<Link activeClassName="active" to={global.baseURL+"search"}>
|
||||
<Icon name="search" />
|
||||
Search
|
||||
</Link>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@ -87,10 +87,10 @@ class Sidebar extends React.Component{
|
||||
</section>
|
||||
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
<Dropzones />
|
||||
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
@ -67,13 +67,15 @@ export default class Track extends React.Component{
|
||||
)
|
||||
|
||||
} else if (this.props.context == 'queue'){
|
||||
var type = (track.added_from ? helpers.uriType(track.added_from) : null)
|
||||
|
||||
if (track.added_from && track.added_by){
|
||||
var added = <span>{track.added_by} <span className="grey-text"> (from <Link to={global.baseURL+type+'/'+track.added_from}>{type}</Link>)</span></span>
|
||||
|
||||
} else if (track.added_from){
|
||||
var added = <span className="grey-text"> (from <Link to={global.baseURL+type+'/'+track.added_from}>{type}</Link>)</span>
|
||||
var type = (track.added_from ? helpers.uriType(track.added_from) : null)
|
||||
if (type == 'discover'){
|
||||
var link = <Link to={global.baseURL+'discover/recommendations/'+helpers.getFromUri('seeds',track.added_from)}>discover</Link>
|
||||
} else {
|
||||
var link = <Link to={global.baseURL+type+'/'+track.added_from}>{type}</Link>
|
||||
}
|
||||
var added = <span>{track.added_by} <span className="grey-text"> (from {link})</span></span>
|
||||
|
||||
} else if (track.added_by){
|
||||
var added = track.added_by
|
||||
|
||||
@ -209,6 +209,12 @@ export let getFromUri = function(element,uri){
|
||||
return exploded[2]
|
||||
}
|
||||
break
|
||||
|
||||
case 'seeds':
|
||||
if (exploded[1] == 'discover'){
|
||||
return exploded[2]
|
||||
}
|
||||
break
|
||||
}
|
||||
return null
|
||||
}
|
||||
@ -232,6 +238,7 @@ export let uriType = function( uri ){
|
||||
case 'playlist':
|
||||
case 'search':
|
||||
case 'genre':
|
||||
case 'discover':
|
||||
return exploded[1]
|
||||
break
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ ReactDOM.render(
|
||||
<Route path="settings" component={Settings} />
|
||||
<Route path="settings/debug" component={Debug} />
|
||||
|
||||
<Route path="search/iris::search::type::query" component={Search} />
|
||||
<Route path="search(/iris::search::type::query)" component={Search} />
|
||||
<Route path="album/:uri" component={Album} />
|
||||
<Route path="artist/:uri(/:sub_view)" component={Artist} />
|
||||
<Route path="playlist/:uri" component={Playlist} />
|
||||
|
||||
@ -13,6 +13,7 @@ import ArtistGrid from '../components/ArtistGrid'
|
||||
import AlbumGrid from '../components/AlbumGrid'
|
||||
import PlaylistGrid from '../components/PlaylistGrid'
|
||||
import LazyLoadListener from '../components/LazyLoadListener'
|
||||
import SearchForm from '../components/SearchForm'
|
||||
|
||||
import * as helpers from '../helpers'
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
@ -26,18 +27,26 @@ class Search extends React.Component{
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
this.props.uiActions.startSearch(this.props.params.type, this.props.params.query)
|
||||
|
||||
// Make sure we have search parameters to start with
|
||||
if (this.props.params && this.props.params.type && this.props.params.query){
|
||||
this.props.uiActions.startSearch(this.props.params.type, this.props.params.query)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps){
|
||||
|
||||
// Make sure we have some search parameters
|
||||
if (newProps.params && newProps.params.type && newProps.params.query){
|
||||
|
||||
if (this.props.params.query != newProps.params.query || this.props.params.type != newProps.params.type){
|
||||
this.props.uiActions.startSearch(newProps.params.type, newProps.params.query)
|
||||
}
|
||||
if (this.props.params.query != newProps.params.query || this.props.params.type != newProps.params.type){
|
||||
this.props.uiActions.startSearch(newProps.params.type, newProps.params.query)
|
||||
}
|
||||
|
||||
// mopidy comes online
|
||||
if (!this.props.mopidy_connected && newProps.mopidy_connected){
|
||||
this.props.uiActions.startSearch(newProps.params.type, newProps.params.query, true)
|
||||
// mopidy comes online
|
||||
if (!this.props.mopidy_connected && newProps.mopidy_connected){
|
||||
this.props.uiActions.startSearch(newProps.params.type, newProps.params.query, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,7 +243,7 @@ class Search extends React.Component{
|
||||
|
||||
return (
|
||||
<div className="view search-view">
|
||||
<Header icon="search" title="Search results" options={options} uiActions={this.props.uiActions} />
|
||||
<Header search options={options} uiActions={this.props.uiActions} />
|
||||
<div className="content-wrapper">
|
||||
{ this.renderResults() }
|
||||
</div>
|
||||
|
||||
@ -66,7 +66,11 @@ class Discover extends React.Component{
|
||||
}
|
||||
|
||||
handleURLSeeds(seeds_string = this.props.params.seeds){
|
||||
var seeds = seeds_string.split(',')
|
||||
|
||||
// Rejoin if we've had to uri-encode these as strings
|
||||
// We'd need to do this if our URL has been encoded so the whole URL can become
|
||||
// it's own URI (eg iris:discover:spotify_artist_1234) where we can't use ":"
|
||||
var seeds = seeds_string.split('_').join(':').split(',')
|
||||
|
||||
for (var i = 0; i < seeds.length; i++){
|
||||
switch (helpers.uriType(seeds[i])){
|
||||
@ -198,6 +202,11 @@ class Discover extends React.Component{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var uri = 'iris:discover'
|
||||
if (this.props.params.seeds){
|
||||
uri += ':'+this.props.params.seeds.split(':').join('_')
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="content-wrapper recommendations-results">
|
||||
@ -211,7 +220,7 @@ class Discover extends React.Component{
|
||||
</section>
|
||||
<section className="list-wrapper">
|
||||
<h4>Tracks</h4>
|
||||
{this.props.recommendations.tracks ? <TrackList className="discover-track-list" uri="iris:discover" tracks={this.props.recommendations.tracks} /> : null}
|
||||
{this.props.recommendations.tracks ? <TrackList className="discover-track-list" uri={uri} tracks={this.props.recommendations.tracks} /> : null}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
@import 'components/dragger';
|
||||
@import 'components/images';
|
||||
@import 'components/icon';
|
||||
@import 'components/search-form';
|
||||
@import 'components/slider';
|
||||
@import 'components/playback-controls';
|
||||
@import 'components/sidebar';
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
|
||||
.search-form {
|
||||
z-index: 3;
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
background: transparent;
|
||||
border-bottom: 1px solid $light_grey;
|
||||
padding: 16px 0 8px;
|
||||
width: 100%;
|
||||
color: $black;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
border-color: $turquoise;
|
||||
}
|
||||
}
|
||||
|
||||
&.sidebar {
|
||||
padding: 10px 15px 0 15px;
|
||||
|
||||
.autocomplete-field {
|
||||
.results {
|
||||
top: 42px;
|
||||
}
|
||||
|
||||
&.loading {
|
||||
.input:after {
|
||||
background: $turquoise;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -68,18 +68,18 @@ aside{
|
||||
nav {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
padding-top: 8px;
|
||||
padding-top: 25px;
|
||||
|
||||
a {
|
||||
@include feature_font();
|
||||
@include gradient_overlay();
|
||||
@include gradient_overlay(3px);
|
||||
font-weight: 800;
|
||||
font-size: 15px;
|
||||
color: $darkest_grey;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 8px 10px 6px;
|
||||
margin: 0 15px;
|
||||
margin: 0 20px;
|
||||
border-radius: 3px;
|
||||
|
||||
.icon {
|
||||
@ -116,7 +116,7 @@ aside{
|
||||
}
|
||||
|
||||
section {
|
||||
padding-bottom: 20px;
|
||||
padding-bottom: 25px;
|
||||
|
||||
title {
|
||||
display: block;
|
||||
|
||||
@ -43,7 +43,7 @@ main {
|
||||
min-height: 100vh;
|
||||
|
||||
.content-wrapper {
|
||||
padding: 40px 40px 50px;
|
||||
padding: 40px 40px 80px;
|
||||
}
|
||||
|
||||
a {
|
||||
|
||||
@ -190,8 +190,9 @@ $bp_shallow: 650px;
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
@mixin gradient_overlay(){
|
||||
@mixin gradient_overlay($radius: 0){
|
||||
position: relative;
|
||||
border-radius: $radius;
|
||||
|
||||
&:before {
|
||||
@include animate();
|
||||
|
||||
@ -1,6 +1,18 @@
|
||||
|
||||
.search-view {
|
||||
|
||||
.search-form {
|
||||
display: inline-block;
|
||||
|
||||
input {
|
||||
@include feature_font();
|
||||
padding: 0;
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-sections {
|
||||
section {
|
||||
.inner {
|
||||
|
||||
Reference in New Issue
Block a user