Artist and album following; TODO: move follow to separate component possibly
This commit is contained in:
@ -14,7 +14,7 @@ const localstorageMiddleware = (function(){
|
||||
window._store = store
|
||||
var actions_to_log = null
|
||||
//actions_to_log = 'SPOTIFY'
|
||||
actions_to_log = 'MOPIDY'
|
||||
//actions_to_log = 'MOPIDY'
|
||||
if( action.type.startsWith(actions_to_log) ) console.log(action)
|
||||
|
||||
switch( action.type ){
|
||||
|
||||
@ -219,145 +219,6 @@ export function getTrack( uri ){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a single artist
|
||||
*
|
||||
* @param uri string
|
||||
**/
|
||||
export function getArtist( uri ){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// flush out the previous store value
|
||||
dispatch({ type: 'SPOTIFY_ARTIST_LOADED', data: false });
|
||||
|
||||
var artist = {};
|
||||
|
||||
// get both the artist and the top tracks
|
||||
$.when(
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) )
|
||||
.then( response => {
|
||||
Object.assign(artist, response);
|
||||
}),
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/top-tracks?country='+getState().spotify.country )
|
||||
.then( response => {
|
||||
Object.assign(artist, response);
|
||||
}),
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/related-artists' )
|
||||
.then( response => {
|
||||
Object.assign(artist, { related_artists: response.artists });
|
||||
}),
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/albums' )
|
||||
.then( response => {
|
||||
Object.assign(artist, { albums: response.items, albums_more: response.next });
|
||||
})
|
||||
|
||||
).then( () => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ARTIST_LOADED',
|
||||
data: artist
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getArtists( uris ){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// flush out the previous store value
|
||||
dispatch({ type: 'SPOTIFY_ARTISTS_LOADED', data: false });
|
||||
|
||||
// now get all the artists for this album (full objects)
|
||||
var ids = '';
|
||||
for( var i = 0; i < uris.length; i++ ){
|
||||
if( ids != '' ) ids += ','
|
||||
ids += helpers.getFromUri( 'artistid', uris[i] );
|
||||
}
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/?ids='+ids )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ARTISTS_LOADED',
|
||||
data: response.artists
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Single album
|
||||
*
|
||||
* @oaram uri string
|
||||
**/
|
||||
export function getAlbum( uri ){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// flush out the previous store value
|
||||
dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: false });
|
||||
|
||||
sendRequest( dispatch, getState, 'albums/'+ helpers.getFromUri('albumid', uri) )
|
||||
.then( response => {
|
||||
|
||||
var album = response
|
||||
|
||||
// now get all the artists for this album (full objects)
|
||||
// we do this to get the artist artwork
|
||||
var artist_ids = [];
|
||||
for( var i = 0; i < album.artists.length; i++ ){
|
||||
artist_ids.push( helpers.getFromUri( 'artistid', album.artists[i].uri ) )
|
||||
}
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/?ids='+artist_ids )
|
||||
.then( response => {
|
||||
var artists = response.artists
|
||||
|
||||
// finally dispatch the loaded action
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ALBUM_LOADED',
|
||||
data: Object.assign({}, album, {artists: artists})
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function getLibraryArtists(){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
dispatch({ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', data: false });
|
||||
|
||||
sendRequest( dispatch, getState, 'me/following?type=artist' )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED',
|
||||
data: response.artists
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function getLibraryAlbums(){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
dispatch({ type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', data: false });
|
||||
|
||||
sendRequest( dispatch, getState, 'me/albums' )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED',
|
||||
data: response
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getLibraryTracks(){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
@ -497,10 +358,217 @@ export function getSearchResults( query, type = 'album,artist,playlist,track', l
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* =============================================================== ARTIST(S) ============
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
/**
|
||||
* Get a single artist
|
||||
*
|
||||
* @param uri string
|
||||
**/
|
||||
export function getArtist( uri ){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// flush out the previous store value
|
||||
dispatch({ type: 'SPOTIFY_ARTIST_LOADED', data: false });
|
||||
|
||||
var artist = {};
|
||||
|
||||
// get both the artist and the top tracks
|
||||
$.when(
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) )
|
||||
.then( response => {
|
||||
Object.assign(artist, response);
|
||||
}),
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/top-tracks?country='+getState().spotify.country )
|
||||
.then( response => {
|
||||
Object.assign(artist, response);
|
||||
}),
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/related-artists' )
|
||||
.then( response => {
|
||||
Object.assign(artist, { related_artists: response.artists });
|
||||
}),
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/'+ helpers.getFromUri('artistid', uri) +'/albums' )
|
||||
.then( response => {
|
||||
Object.assign(artist, { albums: response.items, albums_more: response.next });
|
||||
}),
|
||||
|
||||
sendRequest( dispatch, getState, 'me/following/contains?type=artist&ids='+ helpers.getFromUri('artistid', uri) )
|
||||
.then( response => {
|
||||
var is_following = 0
|
||||
if( response.length > 0 ) is_following = response[0]
|
||||
Object.assign(artist, { following: response[0] } );
|
||||
})
|
||||
|
||||
).then( () => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ARTIST_LOADED',
|
||||
data: artist
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getArtists( uris ){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// flush out the previous store value
|
||||
dispatch({ type: 'SPOTIFY_ARTISTS_LOADED', data: false });
|
||||
|
||||
// now get all the artists for this album (full objects)
|
||||
var ids = '';
|
||||
for( var i = 0; i < uris.length; i++ ){
|
||||
if( ids != '' ) ids += ','
|
||||
ids += helpers.getFromUri( 'artistid', uris[i] );
|
||||
}
|
||||
|
||||
sendRequest( dispatch, getState, 'artists/?ids='+ids )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ARTISTS_LOADED',
|
||||
data: response.artists
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function getLibraryArtists(){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
dispatch({ type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED', data: false });
|
||||
|
||||
sendRequest( dispatch, getState, 'me/following?type=artist' )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_LIBRARY_ARTISTS_LOADED',
|
||||
data: response.artists
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function toggleArtistInLibrary( uri, method ){
|
||||
if( method == 'PUT' ) var new_state = 1
|
||||
if( method == 'DELETE' ) var new_state = 0
|
||||
|
||||
return (dispatch, getState) => {
|
||||
sendRequest( dispatch, getState, 'me/following?type=artist&ids='+ helpers.getFromUri('artistid',uri), method, {} )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ARTIST_FOLLOWING',
|
||||
uri: uri,
|
||||
data: new_state
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Playlists
|
||||
* =============================================================== ALBUM(S) =============
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
/**
|
||||
* Single album
|
||||
*
|
||||
* @oaram uri string
|
||||
**/
|
||||
export function getAlbum( uri ){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
// flush out the previous store value
|
||||
dispatch({ type: 'SPOTIFY_ALBUM_LOADED', data: false });
|
||||
|
||||
var album = {}
|
||||
|
||||
$.when(
|
||||
|
||||
// get the album
|
||||
sendRequest( dispatch, getState, 'albums/'+ helpers.getFromUri('albumid', uri) )
|
||||
.then( response => {
|
||||
|
||||
Object.assign(album, response)
|
||||
|
||||
// now get all the artists for this album (full objects)
|
||||
// we do this to get the artist artwork
|
||||
var artist_ids = [];
|
||||
for( var i = 0; i < album.artists.length; i++ ){
|
||||
artist_ids.push( helpers.getFromUri( 'artistid', album.artists[i].uri ) )
|
||||
}
|
||||
|
||||
// get all album artists
|
||||
sendRequest( dispatch, getState, 'artists/?ids='+artist_ids )
|
||||
.then( response => {
|
||||
var artists = response.artists
|
||||
Object.assign(album, {artists: artists})
|
||||
});
|
||||
|
||||
}),
|
||||
|
||||
// TODO: Check if we're authenticated before sending this request, otherwise we get a 403
|
||||
sendRequest( dispatch, getState, 'me/albums/contains?ids='+ helpers.getFromUri('albumid', uri) )
|
||||
.then( response => {
|
||||
var is_following = 0
|
||||
if( response.length > 0 ) is_following = response[0]
|
||||
Object.assign(album, { following: response[0] } );
|
||||
})
|
||||
|
||||
).then( () => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ALBUM_LOADED',
|
||||
data: album
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function getLibraryAlbums(){
|
||||
return (dispatch, getState) => {
|
||||
|
||||
dispatch({ type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED', data: false });
|
||||
|
||||
sendRequest( dispatch, getState, 'me/albums' )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_LIBRARY_ALBUMS_LOADED',
|
||||
data: response
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function toggleAlbumInLibrary( uri, method ){
|
||||
if( method == 'PUT' ) var new_state = 1
|
||||
if( method == 'DELETE' ) var new_state = 0
|
||||
|
||||
return (dispatch, getState) => {
|
||||
sendRequest( dispatch, getState, 'me/albums?ids='+ helpers.getFromUri('albumid',uri), method )
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_ALBUM_FOLLOWING',
|
||||
uri: uri,
|
||||
data: new_state
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* =============================================================== PLAYLIST(S) ==========
|
||||
* ======================================================================================
|
||||
**/
|
||||
|
||||
export function createPlaylist( name, is_public ){
|
||||
@ -609,6 +677,7 @@ export function toggleFollowingPlaylist( uri, method ){
|
||||
.then( response => {
|
||||
dispatch({
|
||||
type: 'SPOTIFY_PLAYLIST_FOLLOWING',
|
||||
uri: uri,
|
||||
data: new_state
|
||||
});
|
||||
});
|
||||
|
||||
@ -134,6 +134,10 @@ export default function reducer(ui = {}, action){
|
||||
})
|
||||
return Object.assign({}, ui, { album: album });
|
||||
|
||||
case 'SPOTIFY_ALBUM_FOLLOWING':
|
||||
var album = Object.assign({}, ui.album, { following: action.data })
|
||||
return Object.assign({}, ui, { album: album });
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -161,6 +165,10 @@ export default function reducer(ui = {}, action){
|
||||
})
|
||||
return Object.assign({}, ui, { artist: artist });
|
||||
|
||||
case 'SPOTIFY_ARTIST_FOLLOWING':
|
||||
var artist = Object.assign({}, ui.artist, { following: action.data })
|
||||
return Object.assign({}, ui, { artist: artist });
|
||||
|
||||
|
||||
/**
|
||||
* Playlists
|
||||
|
||||
@ -64,24 +64,22 @@ class Album extends React.Component{
|
||||
}
|
||||
|
||||
follow(){
|
||||
this.props.spotifyActions.toggleFollowingAlbum( this.props.params.uri, 'PUT' )
|
||||
this.props.spotifyActions.toggleAlbumInLibrary( this.props.params.uri, 'PUT' )
|
||||
}
|
||||
|
||||
// TODO: Once unfollowing occurs, remove playlist from global playlists list
|
||||
unfollow(){
|
||||
this.props.spotifyActions.toggleFollowingAlbum( this.props.params.uri, 'DELETE' )
|
||||
this.props.spotifyActions.toggleAlbumInLibrary( this.props.params.uri, 'DELETE' )
|
||||
}
|
||||
|
||||
renderExtraButtons(){
|
||||
switch( helpers.uriSource( this.props.params.uri ) ){
|
||||
|
||||
case 'spotify':
|
||||
if( !this.props.spotify_authorized ) return null
|
||||
if( this.props.playlist.following ){
|
||||
return <button className="large tertiary" onClick={ e => this.unfollow() }>Unfollow</button>
|
||||
if( this.props.album.following ){
|
||||
return <button className="large tertiary" onClick={ e => this.unfollow() }>Remove from library</button>
|
||||
}
|
||||
return <button className="large tertiary" onClick={ e => this.follow() }>Follow</button>
|
||||
|
||||
return <button className="large tertiary" onClick={ e => this.follow() }>Add to library</button>
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,6 +131,7 @@ class Album extends React.Component{
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
album: state.ui.album,
|
||||
spotify_authorized: state.spotify.authorized,
|
||||
mopidy_connected: state.mopidy.connected
|
||||
};
|
||||
}
|
||||
|
||||
@ -51,6 +51,29 @@ class Artist extends React.Component{
|
||||
this.props.spotifyActions.getURL( this.props.artist.albums_more, 'SPOTIFY_ARTIST_ALBUMS_LOADED_MORE' );
|
||||
}
|
||||
|
||||
play(){
|
||||
alert('Yet to be implemented')
|
||||
}
|
||||
|
||||
follow(){
|
||||
this.props.spotifyActions.toggleArtistInLibrary( this.props.params.uri, 'PUT' )
|
||||
}
|
||||
|
||||
unfollow(){
|
||||
this.props.spotifyActions.toggleArtistInLibrary( this.props.params.uri, 'DELETE' )
|
||||
}
|
||||
|
||||
renderExtraButtons(){
|
||||
switch( helpers.uriSource( this.props.params.uri ) ){
|
||||
case 'spotify':
|
||||
if( !this.props.spotify_authorized ) return null
|
||||
if( this.props.artist.following ){
|
||||
return <button className="large tertiary" onClick={ e => this.unfollow() }>Unfollow</button>
|
||||
}
|
||||
return <button className="large tertiary" onClick={ e => this.follow() }>Follow</button>
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
if( !this.props.artist ) return null
|
||||
var scheme = helpers.uriSource( this.props.params.uri );
|
||||
@ -60,8 +83,16 @@ class Artist extends React.Component{
|
||||
<Parallax images={this.props.artist.images} />
|
||||
|
||||
<div className="intro">
|
||||
|
||||
<Thumbnail size="huge" images={ this.props.artist.images } />
|
||||
|
||||
<h1>{ this.props.artist.name }</h1>
|
||||
|
||||
<div className="actions">
|
||||
<button className="large primary" onClick={ e => this.play() }>Start radio</button>
|
||||
{ this.renderExtraButtons() }
|
||||
</div>
|
||||
|
||||
<ul className="details">
|
||||
{ this.props.artist.followers ? <li>{ this.props.artist.followers.total.toLocaleString() } followers</li> : null }
|
||||
{ this.props.artist.popularity ? <li>{ this.props.artist.popularity }% popularity</li> : null }
|
||||
@ -69,6 +100,7 @@ class Artist extends React.Component{
|
||||
{ scheme == 'spotify' ? <li><FontAwesome name='spotify' /> Spotify artist</li> : null }
|
||||
{ scheme == 'local' ? <li><FontAwesome name='folder' /> Local artist</li> : null }
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="col w70">
|
||||
@ -104,8 +136,9 @@ class Artist extends React.Component{
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
return {
|
||||
mopidy_connected: state.mopidy.connected,
|
||||
artist: state.ui.artist
|
||||
artist: state.ui.artist,
|
||||
spotify_authorized: state.spotify.authorized,
|
||||
mopidy_connected: state.mopidy.connected
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,11 @@
|
||||
padding-top: 30px;
|
||||
padding-bottom: 45px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.artist-list {
|
||||
|
||||
Reference in New Issue
Block a user