diff --git a/src/js/components/DropdownField.js b/src/js/components/DropdownField.js index 74e42cbe..d2c7ff8c 100755 --- a/src/js/components/DropdownField.js +++ b/src/js/components/DropdownField.js @@ -60,7 +60,7 @@ export default class DropdownField extends React.Component{ return (
this.handleToggle() }> - {this.props.icon ?   : null} + {this.props.icon ?   : null} { this.props.name }
diff --git a/src/js/components/Modal/Modal.js b/src/js/components/Modal/Modal.js index ae0a04ab..751c4f1c 100755 --- a/src/js/components/Modal/Modal.js +++ b/src/js/components/Modal/Modal.js @@ -13,6 +13,7 @@ import SendAuthorizationModal from './SendAuthorizationModal' import EditRadioModal from './EditRadioModal' import ImageZoomModal from './ImageZoomModal' import KioskModeModal from './KioskModeModal' +import SearchSettingsModal from './SearchSettingsModal' import * as uiActions from '../../services/ui/actions' import * as mopidyActions from '../../services/mopidy/actions' @@ -51,6 +52,7 @@ class Modal extends React.Component{ { this.props.modal.name == 'edit_radio' ? : null } { this.props.modal.name == 'image_zoom' ? : null } { this.props.modal.name == 'kiosk_mode' ? : null } + { this.props.modal.name == 'search_settings' ? : null }
@@ -60,6 +62,8 @@ class Modal extends React.Component{ const mapStateToProps = (state, ownProps) => { return { + uri_schemes: (state.mopidy.uri_schemes ? state.mopidy.uri_schemes : null), + search_settings: (state.ui.search_settings ? state.ui.search_settings : null), modal: state.ui.modal, radio: state.ui.radio, tracks: state.ui.tracks, diff --git a/src/js/components/Modal/SearchSettingsModal.js b/src/js/components/Modal/SearchSettingsModal.js new file mode 100755 index 00000000..3f0c721c --- /dev/null +++ b/src/js/components/Modal/SearchSettingsModal.js @@ -0,0 +1,90 @@ + +import React, { PropTypes } from 'react' +import FontAwesome from 'react-fontawesome' + +import Icon from '../Icon' +import * as helpers from '../../helpers' + +export default class SearchSettingsModal extends React.Component{ + + constructor(props){ + super(props) + + this.state = { + spotify: true, + uri_schemes: [] + } + } + + componentDidMount(){ + if (this.props.search_settings){ + this.setState(this.props.search_settings) + } else { + this.setState({ + spotify: true, + uri_schemes: this.props.uri_schemes + }) + } + } + + handleSubmit(e){ + this.props.uiActions.set({search_settings: this.state}) + this.props.uiActions.closeModal() + this.props.uiActions.startSearch(this.props.data.type, this.props.data.query) + } + + handleToggle(scheme){ + var uri_schemes = this.state.uri_schemes + var index = uri_schemes.indexOf(scheme) + + if (index > -1){ + uri_schemes.splice(index,1) + } else { + uri_schemes.push(scheme) + } + + this.setState({uri_schemes: uri_schemes}) + } + + render(){ + return ( +
+

Advanced search settings

+

Customise the providers used when searching

+ +
this.handleSubmit(e)}> +
+ +
+ { + this.props.uri_schemes.map(scheme => { + return ( +
+ +
+ ) + }) + } + +
+ +
+
+
+ ) + } +} \ No newline at end of file diff --git a/src/js/components/SearchForm.js b/src/js/components/SearchForm.js index 6bc1618e..5fb6fc08 100755 --- a/src/js/components/SearchForm.js +++ b/src/js/components/SearchForm.js @@ -7,7 +7,6 @@ import FontAwesome from 'react-fontawesome' import * as helpers from '../helpers' import * as uiActions from '../services/ui/actions' -import * as spotifyActions from '../services/spotify/actions' class SearchForm extends React.Component{ @@ -38,7 +37,7 @@ class SearchForm extends React.Component{ break default: - hashHistory.push(global.baseURL+'search/'+this.state.query) + hashHistory.push(global.baseURL+'search/all/'+this.state.query) break } @@ -58,15 +57,10 @@ class SearchForm extends React.Component{ } } -const mapStateToProps = (state, ownProps) => { - return state; -} - const mapDispatchToProps = (dispatch) => { return { - uiActions: bindActionCreators(uiActions, dispatch), - spotifyActions: bindActionCreators(spotifyActions, dispatch) + uiActions: bindActionCreators(uiActions, dispatch) } } -export default connect(mapStateToProps, mapDispatchToProps)(SearchForm) \ No newline at end of file +export default connect(mapDispatchToProps)(SearchForm) \ No newline at end of file diff --git a/src/js/index.js b/src/js/index.js index ca922a89..010cf572 100755 --- a/src/js/index.js +++ b/src/js/index.js @@ -60,8 +60,7 @@ ReactDOM.render( - - + diff --git a/src/js/services/ui/actions.js b/src/js/services/ui/actions.js index d7aed541..20beda49 100755 --- a/src/js/services/ui/actions.js +++ b/src/js/services/ui/actions.js @@ -29,10 +29,12 @@ export function hideTouchContextMenu(){ } } -export function startSearch( query ){ +export function startSearch(search_type, query, only_mopidy = false){ return { type: 'SEARCH_STARTED', - query: query + search_type: search_type, + query: query, + only_mopidy: only_mopidy } } diff --git a/src/js/services/ui/middleware.js b/src/js/services/ui/middleware.js index 73a17cdc..9c0b1130 100755 --- a/src/js/services/ui/middleware.js +++ b/src/js/services/ui/middleware.js @@ -112,7 +112,26 @@ const UIMiddleware = (function(){ break case 'SEARCH_STARTED': - ReactGA.event({ category: 'Search', action: 'Started', label: action.query }) + ReactGA.event({ category: 'Search', action: 'Started', label: action.type+': '+action.query }) + var state = store.getState() + + // initiate spotify searching + if (!action.only_mopidy){ + if (!state.ui.search_settings || state.ui.search_settings.spotify){ + store.dispatch(spotifyActions.getSearchResults(action.query)) + } + } + + // backend searching (mopidy) + if (state.mopidy.connected){ + if (state.ui.search_settings){ + var uri_schemes = state.ui.search_settings.uri_schemes + } else { + var uri_schemes = state.mopidy.uri_schemes + } + store.dispatch(mopidyActions.getSearchResults(action.query, uri_schemes)) + } + next(action) break diff --git a/src/js/views/Search.js b/src/js/views/Search.js index e36da71c..cb1b4a5c 100755 --- a/src/js/views/Search.js +++ b/src/js/views/Search.js @@ -26,34 +26,19 @@ class Search extends React.Component{ } componentDidMount(){ - this.performSearch() + this.props.uiActions.startSearch(this.props.params.type, this.props.params.query) } componentWillReceiveProps(newProps){ // new query if( this.props.params.query != newProps.params.query ){ - this.performSearch( newProps ) + this.props.uiActions.startSearch(newProps.params.type, newProps.params.query) } // mopidy comes online if( !this.props.mopidy_connected && newProps.mopidy_connected ){ - this.props.mopidyActions.getSearchResults( newProps.params.query, newProps.uri_schemes ) - } - } - - performSearch( props = this.props ){ - var source = props.params.source - var type = props.params.type - - this.props.uiActions.startSearch(props.params.query) - - if (!source || source == 'all' || source == 'spotify'){ - this.props.spotifyActions.getSearchResults( props.params.query ) - } - - if( props.mopidy_connected ){ - this.props.mopidyActions.getSearchResults( props.params.query, props.uri_schemes ) + this.props.uiActions.startSearch(newProps.params.type, newProps.params.query, true) } } @@ -62,14 +47,11 @@ class Search extends React.Component{ } renderResults(){ - var type = (this.props.params.type ? this.props.params.type : 'all') - var source = (this.props.params.source ? this.props.params.source : 'all') - var artists = [] if (this.props.artists_uris){ for (var i = 0; i < this.props.artists_uris.length; i++){ var uri = this.props.artists_uris[i] - if (this.props.artists.hasOwnProperty(uri) && (source == 'all' || helpers.uriSource(uri) == source)){ + if (this.props.artists.hasOwnProperty(uri)){ artists.push(this.props.artists[uri]) } } @@ -79,7 +61,7 @@ class Search extends React.Component{ if (this.props.albums_uris){ for (var i = 0; i < this.props.albums_uris.length; i++){ var uri = this.props.albums_uris[i] - if (this.props.albums.hasOwnProperty(uri) && (source == 'all' || helpers.uriSource(uri) == source)){ + if (this.props.albums.hasOwnProperty(uri)){ albums.push(this.props.albums[uri]) } } @@ -89,7 +71,7 @@ class Search extends React.Component{ if (this.props.playlists_uris){ for (var i = 0; i < this.props.playlists_uris.length; i++){ var uri = this.props.playlists_uris[i] - if (this.props.playlists.hasOwnProperty(uri) && (source == 'all' || helpers.uriSource(uri) == source)){ + if (this.props.playlists.hasOwnProperty(uri)){ playlists.push(this.props.playlists[uri]) } } @@ -97,25 +79,21 @@ class Search extends React.Component{ var tracks = [] if (this.props.tracks){ - if (source == 'all'){ - tracks = this.props.tracks - } else { - for (var i = 0; i < this.props.tracks.length; i++){ - if (helpers.uriSource(this.props.tracks[i].uri) == source){ - tracks.push(this.props.tracks[i]) - } + for (var i = 0; i < this.props.tracks.length; i++){ + if (helpers.uriSource(this.props.tracks[i].uri)){ + tracks.push(this.props.tracks[i]) } } } - switch( type ){ + switch (this.props.params.type){ case 'artists': return (
- this.loadMore('artists') }/> + this.loadMore('artists') }/>
) @@ -126,7 +104,7 @@ class Search extends React.Component{
- this.loadMore('albums') }/> + this.loadMore('albums') }/>
) @@ -137,7 +115,7 @@ class Search extends React.Component{
- this.loadMore('playlists') }/> + this.loadMore('playlists') }/>
) @@ -148,7 +126,7 @@ class Search extends React.Component{
- this.loadMore('tracks') }/> + this.loadMore('tracks') }/>
) @@ -181,7 +159,7 @@ class Search extends React.Component{

Tracks

- this.loadMore('tracks') }/> + this.loadMore('tracks') }/>
@@ -191,14 +169,7 @@ class Search extends React.Component{ handleTypeChange(val){ this.props.uiActions.hideContextMenu() - var source = (this.props.params.source ? this.props.params.source : 'all') - hashHistory.push(global.baseURL+'search/'+this.props.params.query+'/'+source+'/'+val) - } - - handleSourceChange(val){ - this.props.uiActions.hideContextMenu() - var type = (this.props.params.type ? this.props.params.type : 'all') - hashHistory.push(global.baseURL+'search/'+this.props.params.query+'/'+val+'/'+type) + hashHistory.push(global.baseURL+'search/'+val+'/'+this.props.params.query) } render(){ @@ -225,28 +196,13 @@ class Search extends React.Component{ } ] - var source_options = [ - { - value: 'all', - label: 'All' - }, - { - value: 'spotify', - label: 'Spotify' - } - ] - for (var i = 0; i < this.props.uri_schemes.length; i++){ - var scheme = this.props.uri_schemes[i].replace(':','') - source_options.push({ - value: scheme, - label: scheme - }) - } - var options = ( - this.handleTypeChange(val)} /> - this.handleSourceChange(val)} /> + this.handleTypeChange(val)} /> + ) @@ -262,7 +218,7 @@ class Search extends React.Component{ const mapStateToProps = (state, ownProps) => { return { mopidy_connected: state.mopidy.connected, - uri_schemes: state.mopidy.uri_schemes, + search_settings: (state.ui.search_settings ? state.ui.search_settings : null), tracks: (state.ui.search_results ? state.ui.search_results.tracks : []), tracks_more: (state.ui.search_results && state.ui.search_results.tracks_more ? state.ui.search_results.tracks_more : null), artists: state.ui.artists, diff --git a/src/scss/global/_core.scss b/src/scss/global/_core.scss index 897b088e..7c18b355 100755 --- a/src/scss/global/_core.scss +++ b/src/scss/global/_core.scss @@ -100,6 +100,10 @@ h3 { font-weight: 100; font-style: italic; font-size: 20px; + + &.bottom-padding { + padding-bottom: 30px; + } } h4 {