Discover moved to recommendations; URL handles context loading
This commit is contained in:
@ -6,6 +6,7 @@ import { Link, hashHistory } from 'react-router'
|
||||
|
||||
import ArtistSentence from './ArtistSentence'
|
||||
import * as helpers from '../helpers'
|
||||
import * as uiActions from '../services/ui/actions'
|
||||
import * as spotifyActions from '../services/spotify/actions'
|
||||
|
||||
class AddSeedField extends React.Component{
|
||||
@ -59,8 +60,20 @@ class AddSeedField extends React.Component{
|
||||
|
||||
handleSelect(e,item){
|
||||
this.setState({value: ''})
|
||||
this.props.onSelect(e,item)
|
||||
this.props.onSelect(e,item.uri)
|
||||
this.props.spotifyActions.clearAutocompleteResults(this.id)
|
||||
|
||||
// Add our selected item to our global index
|
||||
switch (helpers.uriType(item.uri)){
|
||||
|
||||
case 'artist':
|
||||
this.props.uiActions.albumLoaded(item.uri,item)
|
||||
break
|
||||
|
||||
case 'track':
|
||||
this.props.uiActions.trackLoaded(item.uri,item)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
results(){
|
||||
@ -123,13 +136,14 @@ class AddSeedField extends React.Component{
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
genres: (state.spotify.genres ? state.spotify.genres : null),
|
||||
genres: (state.ui.genres ? state.ui.genres : null),
|
||||
results: (state.spotify.autocomplete_results ? state.spotify.autocomplete_results : {})
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
uiActions: bindActionCreators(uiActions, dispatch),
|
||||
spotifyActions: bindActionCreators(spotifyActions, dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,6 +194,11 @@ class ContextMenu extends React.Component{
|
||||
this.props.pusherActions.startRadio(this.props.menu.uris)
|
||||
}
|
||||
|
||||
goToRecommendations(e){
|
||||
this.props.uiActions.hideContextMenu()
|
||||
hashHistory.push( global.baseURL +'discover/recommendations/'+ this.props.menu.items[0].uri )
|
||||
}
|
||||
|
||||
goToArtist(e){
|
||||
if (!this.props.menu.items || this.props.menu.items.length <= 0 || !this.props.menu.items[0].artists || this.props.menu.items[0].artists.length <= 0){
|
||||
return null
|
||||
@ -399,6 +404,14 @@ class ContextMenu extends React.Component{
|
||||
</span>
|
||||
)
|
||||
|
||||
var go_to_recommendations = (
|
||||
<span className="menu-item-wrapper">
|
||||
<a className="menu-item" onClick={e => this.goToRecommendations(e)}>
|
||||
<span className="label">More like this</span>
|
||||
</a>
|
||||
</span>
|
||||
)
|
||||
|
||||
var start_radio = (
|
||||
<span className="menu-item-wrapper">
|
||||
<a className="menu-item" onClick={e => this.startRadio(e)}>
|
||||
@ -451,6 +464,7 @@ class ContextMenu extends React.Component{
|
||||
<div>
|
||||
{start_radio}
|
||||
{this.canBeInLibrary() ? toggle_in_library : null}
|
||||
{go_to_recommendations}
|
||||
{copy_uris}
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -39,7 +39,7 @@ class Sidebar extends React.Component{
|
||||
|
||||
<section>
|
||||
<title>Discover</title>
|
||||
<Link activeClassName="active" to={global.baseURL+"discover"}>
|
||||
<Link activeClassName="active" to={global.baseURL+"discover/recommendations"}>
|
||||
<Icon name="compass" className="white" />
|
||||
Discover
|
||||
</Link>
|
||||
|
||||
@ -23,7 +23,7 @@ import Settings from './views/Settings'
|
||||
import Debug from './views/Debug'
|
||||
import Search from './views/Search'
|
||||
|
||||
import Discover from './views/discover/Discover'
|
||||
import DiscoverRecommendations from './views/discover/DiscoverRecommendations'
|
||||
import DiscoverFeatured from './views/discover/DiscoverFeatured'
|
||||
import DiscoverCategories from './views/discover/DiscoverCategories'
|
||||
import DiscoverCategory from './views/discover/DiscoverCategory'
|
||||
@ -66,7 +66,7 @@ ReactDOM.render(
|
||||
<Route path="playlist/:uri" component={Playlist} />
|
||||
<Route path="user/:uri" component={User} />
|
||||
|
||||
<Route path="discover" component={Discover} />
|
||||
<Route path="discover/recommendations(/:seeds)" component={DiscoverRecommendations} />
|
||||
<Route path="discover/featured" component={DiscoverFeatured} />
|
||||
<Route path="discover/categories" component={DiscoverCategories} />
|
||||
<Route path="discover/categories/:id" component={DiscoverCategory} />
|
||||
|
||||
@ -498,14 +498,16 @@ export function getAutocompleteResults(field_id, query, types = ['album','artist
|
||||
.then(response => {
|
||||
var genres = []
|
||||
if (genre_included){
|
||||
var available_genres = getState().spotify.genres
|
||||
for (var i = 0; i < available_genres.length; i++){
|
||||
if (available_genres[i].includes(query)){
|
||||
var genre = available_genres[i]
|
||||
genres.push({
|
||||
name: (genre.charAt(0).toUpperCase()+genre.slice(1)).replace('-',' '),
|
||||
uri: 'spotify:genre:'+genre
|
||||
})
|
||||
var available_genres = getState().ui.genres
|
||||
if (available_genres){
|
||||
for (var i = 0; i < available_genres.length; i++){
|
||||
if (available_genres[i].includes(query)){
|
||||
var genre = available_genres[i]
|
||||
genres.push({
|
||||
name: (genre.charAt(0).toUpperCase()+genre.slice(1)).replace('-',' '),
|
||||
uri: 'spotify:genre:'+genre
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,6 +273,32 @@ const SpotifyMiddleware = (function(){
|
||||
});
|
||||
break
|
||||
|
||||
case 'SPOTIFY_FAVORITES_LOADED':
|
||||
if (action.artists.length > 0){
|
||||
store.dispatch({
|
||||
type: 'ARTISTS_LOADED',
|
||||
artists: action.artists
|
||||
})
|
||||
action.artists_uris = helpers.asURIs(action.artists)
|
||||
}
|
||||
if (action.tracks.length > 0){
|
||||
store.dispatch({
|
||||
type: 'TRACKS_LOADED',
|
||||
tracks: action.tracks
|
||||
})
|
||||
action.tracks_uris = helpers.asURIs(action.tracks)
|
||||
}
|
||||
next(action)
|
||||
break
|
||||
|
||||
case 'SPOTIFY_TRACK_LOADED':
|
||||
store.dispatch({
|
||||
type: 'TRACK_LOADED',
|
||||
key: action.data.uri,
|
||||
track: action.data
|
||||
});
|
||||
break
|
||||
|
||||
case 'SPOTIFY_SEARCH_RESULTS_LOADED_MORE_TRACKS':
|
||||
store.dispatch({
|
||||
type: 'SEARCH_RESULTS_LOADED',
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
|
||||
import * as helpers from '../../helpers'
|
||||
|
||||
export default function reducer(spotify = {}, action){
|
||||
switch (action.type) {
|
||||
|
||||
@ -179,9 +181,6 @@ export default function reducer(spotify = {}, action){
|
||||
if( !action.data ) return Object.assign({}, spotify, { discover: [] })
|
||||
return Object.assign({}, spotify, { discover: [...spotify.discover, ...[action.data]] })
|
||||
|
||||
case 'SPOTIFY_GENRES_LOADED':
|
||||
return Object.assign({}, spotify, {genres: action.genres})
|
||||
|
||||
case 'SPOTIFY_RECOMMENDATIONS_LOADED':
|
||||
return Object.assign(
|
||||
{},
|
||||
@ -199,8 +198,8 @@ export default function reducer(spotify = {}, action){
|
||||
{},
|
||||
spotify,
|
||||
{
|
||||
favorite_artists: action.artists,
|
||||
favorite_tracks: action.tracks
|
||||
favorite_artists: action.artists_uris,
|
||||
favorite_tracks: action.tracks_uris
|
||||
})
|
||||
|
||||
case 'SPOTIFY_AUTOCOMPLETE_LOADING':
|
||||
|
||||
@ -210,6 +210,57 @@ export function addTracksToPlaylist( uri, tracks_uris ){
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assets loaded
|
||||
**/
|
||||
|
||||
export function albumLoaded(key,album){
|
||||
return {
|
||||
type: 'ALBUM_LOADED',
|
||||
key: key,
|
||||
album: album
|
||||
}
|
||||
}
|
||||
|
||||
export function albumsLoaded(albums){
|
||||
return {
|
||||
type: 'ALBUMS_LOADED',
|
||||
albums: albums
|
||||
}
|
||||
}
|
||||
|
||||
export function artistLoaded(key,artist){
|
||||
return {
|
||||
type: 'ARTIST_LOADED',
|
||||
key: key,
|
||||
artist: artist
|
||||
}
|
||||
}
|
||||
|
||||
export function artistsLoaded(artists){
|
||||
return {
|
||||
type: 'ALBUMS_LOADED',
|
||||
artists: artists
|
||||
}
|
||||
}
|
||||
|
||||
export function trackLoaded(key,track){
|
||||
return {
|
||||
type: 'TRACK_LOADED',
|
||||
key: key,
|
||||
track: track
|
||||
}
|
||||
}
|
||||
|
||||
export function tracksLoaded(tracks){
|
||||
return {
|
||||
type: 'TRACKS_LOADED',
|
||||
tracks: tracks
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Modal
|
||||
*
|
||||
@ -268,6 +319,7 @@ export function removeNotification(key){
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Loaders
|
||||
**/
|
||||
|
||||
@ -105,12 +105,6 @@ export default function reducer(ui = {}, action){
|
||||
|
||||
return Object.assign({}, ui, { current_tracklist: tracklist });
|
||||
|
||||
case 'SPOTIFY_TRACK_LOADED':
|
||||
if( !action.data ) return ui
|
||||
|
||||
var current_track = Object.assign({}, ui.current_track, action.data)
|
||||
return Object.assign({}, ui, { current_track: current_track });
|
||||
|
||||
case 'MOPIDY_CURRENTTLTRACK':
|
||||
if( !action.data ) return ui
|
||||
|
||||
@ -605,6 +599,14 @@ export default function reducer(ui = {}, action){
|
||||
return Object.assign({}, ui, { library_playlists: items });
|
||||
|
||||
|
||||
/**
|
||||
* Genres
|
||||
**/
|
||||
|
||||
case 'SPOTIFY_GENRES_LOADED':
|
||||
return Object.assign({}, ui, {genres: action.genres})
|
||||
|
||||
|
||||
/**
|
||||
* Search results
|
||||
**/
|
||||
|
||||
@ -23,10 +23,7 @@ class Discover extends React.Component{
|
||||
|
||||
this.state = {
|
||||
seeds: [
|
||||
{
|
||||
uri: 'spotify:genre:chill',
|
||||
name: 'Chill'
|
||||
}
|
||||
'spotify:genre:chill'
|
||||
],
|
||||
add_seed: '',
|
||||
adding_seed: false
|
||||
@ -34,10 +31,36 @@ class Discover extends React.Component{
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
if (this.props.authorized){
|
||||
this.props.spotifyActions.getFavorites()
|
||||
|
||||
// We have seeds provided in the URL
|
||||
if (this.props.params.seeds){
|
||||
|
||||
var seeds = this.props.params.seeds.split(',')
|
||||
// TODO: lookup these seeds
|
||||
|
||||
for (var i = 0; i < seeds.length; i++){
|
||||
switch (helpers.uriType(seeds[i])){
|
||||
|
||||
case 'artist':
|
||||
this.props.spotifyActions.getArtist(seeds[i])
|
||||
break
|
||||
|
||||
case 'track':
|
||||
this.props.spotifyActions.getTrack(seeds[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({seeds: seeds})
|
||||
this.getRecommendations(seeds)
|
||||
|
||||
// BAU
|
||||
} else {
|
||||
this.getRecommendations()
|
||||
if (this.props.authorized){
|
||||
this.props.spotifyActions.getFavorites()
|
||||
} else {
|
||||
this.getRecommendations()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,8 +80,7 @@ class Discover extends React.Component{
|
||||
|
||||
getRecommendations(seeds = this.state.seeds){
|
||||
if (seeds.length > 0){
|
||||
var uris = helpers.asURIs(seeds)
|
||||
this.props.spotifyActions.getRecommendations(uris, 50)
|
||||
this.props.spotifyActions.getRecommendations(seeds, 50)
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,32 +91,70 @@ class Discover extends React.Component{
|
||||
this.getRecommendations(seeds)
|
||||
}
|
||||
|
||||
handleSelect(e,item){
|
||||
handleSelect(e,uri){
|
||||
var seeds = this.state.seeds
|
||||
seeds.push(item)
|
||||
seeds.push(uri)
|
||||
this.setState({seeds: seeds})
|
||||
this.getRecommendations(seeds)
|
||||
}
|
||||
|
||||
renderSeeds(){
|
||||
var seeds_objects = []
|
||||
|
||||
if (this.state.seeds.length > 0){
|
||||
for (var i = 0; i < this.state.seeds.length; i++){
|
||||
var uri = this.state.seeds[i]
|
||||
|
||||
switch (helpers.uriType(uri)){
|
||||
|
||||
case 'track':
|
||||
if (typeof(this.props.tracks[uri]) !== 'undefined'){
|
||||
seeds_objects.push(this.props.tracks[uri])
|
||||
} else {
|
||||
seeds_objects.push({
|
||||
name: 'Loading...',
|
||||
uri: uri
|
||||
})
|
||||
}
|
||||
break
|
||||
|
||||
case 'artist':
|
||||
if (typeof(this.props.artists[uri]) !== 'undefined'){
|
||||
seeds_objects.push(this.props.artists[uri])
|
||||
} else {
|
||||
seeds_objects.push({
|
||||
name: 'Loading...',
|
||||
uri: uri
|
||||
})
|
||||
}
|
||||
break
|
||||
|
||||
case 'genre':
|
||||
var name = helpers.getFromUri('genreid',uri)
|
||||
seeds_objects.push({
|
||||
name: (name.charAt(0).toUpperCase() + name.slice(1)).replace('-',' '),
|
||||
uri: uri
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="seeds">
|
||||
{
|
||||
this.state.seeds.map((seed,index) => {
|
||||
seeds_objects.map((seed,index) => {
|
||||
var type = helpers.uriType(seed.uri)
|
||||
if (!type){
|
||||
type = 'genre'
|
||||
}
|
||||
return (
|
||||
<span className="seed" key={seed.uri}>
|
||||
{seed.name}
|
||||
<span className="type">({type})</span>
|
||||
<FontAwesome name="close" className="remove" onClick={() => this.removeSeed(index)} />
|
||||
<FontAwesome name="close" className="remove" onClick={() => this.removeSeed(seed.uri)} />
|
||||
</span>
|
||||
)
|
||||
})
|
||||
}
|
||||
<AddSeedField onSelect={(e,item) => this.handleSelect(e,item)} />
|
||||
<AddSeedField onSelect={(e,uri) => this.handleSelect(e,uri)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -180,8 +240,10 @@ class Discover extends React.Component{
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
albums: state.ui.albums,
|
||||
artists: state.ui.artists,
|
||||
albums: (state.ui.albums ? state.ui.albums : []),
|
||||
artists: (state.ui.artists ? state.ui.artists : []),
|
||||
tracks: (state.ui.tracks ? state.ui.tracks : []),
|
||||
genres: (state.ui.genres ? state.ui.genres : []),
|
||||
authorized: state.spotify.authorized,
|
||||
load_queue: state.ui.load_queue,
|
||||
quick_search_results: (state.spotify.quick_search_results ? state.spotify.quick_search_results : {artists: [], tracks: []}),
|
||||
Reference in New Issue
Block a user