diff --git a/src/js/components/ArtistGrid.js b/src/js/components/ArtistGrid.js
index 4747183e..9088c1f2 100755
--- a/src/js/components/ArtistGrid.js
+++ b/src/js/components/ArtistGrid.js
@@ -14,9 +14,12 @@ class ArtistGrid extends React.Component{
super(props);
}
- handleContextMenu(e,uri){
+ handleContextMenu(e,item){
e.preventDefault()
- var data = { uris: [uri] }
+ var data = {
+ uris: [item.uri],
+ item: item
+ }
this.props.uiActions.showContextMenu( e, data, 'artist', 'click' )
}
@@ -34,7 +37,7 @@ class ArtistGrid extends React.Component{
className="grid-item"
to={global.baseURL+'artist/'+artist.uri}
key={index}
- onContextMenu={e => this.handleContextMenu(e,artist.uri)}>
+ onContextMenu={e => this.handleContextMenu(e,artist)}>
diff --git a/src/js/components/ContextMenu.js b/src/js/components/ContextMenu.js
index 4a728f5c..2b940d56 100755
--- a/src/js/components/ContextMenu.js
+++ b/src/js/components/ContextMenu.js
@@ -1,5 +1,6 @@
import React, { PropTypes } from 'react'
+import { Link } from 'react-router'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import FontAwesome from 'react-fontawesome'
@@ -7,6 +8,7 @@ import FontAwesome from 'react-fontawesome'
import TrackList from './TrackList'
import * as helpers from '../helpers'
import * as uiActions from '../services/ui/actions'
+import * as pusherActions from '../services/pusher/actions'
import * as mopidyActions from '../services/mopidy/actions'
import * as spotifyActions from '../services/spotify/actions'
@@ -86,6 +88,11 @@ class ContextMenu extends React.Component{
this.props.uiActions.hideContextMenu();
}
+ startRadio(){
+ this.props.pusherActions.startRadio(this.props.context_menu.data.uris)
+ this.props.uiActions.hideContextMenu();
+ }
+
copyURIs(e){
var temp = $("
");
$("body").append(temp);
@@ -126,7 +133,7 @@ class ContextMenu extends React.Component{
)
}
- getItems(trigger){
+ getItems(){
switch (this.props.context_menu.context) {
case 'queue':
@@ -138,22 +145,12 @@ class ContextMenu extends React.Component{
]
break
- case 'editable-playlist':
- var items = [
- { handleClick: 'playURIs', label: 'Play', icon: 'play' },
- { handleClick: 'playURIsNext', label: 'Play next', icon: 'play' },
- { handleClick: 'addToQueue', label: 'Add to queue', icon: 'plus' },
- { handleClick: 'addToPlaylist', label: 'Add to playlist', icon: 'plus', playlists: true },
- { handleClick: 'copyURIs', label: 'Copy URIs', icon: 'copy' },
- { handleClick: 'removeFromPlaylist', label: 'Remove', icon: 'trash' }
- ]
- break
-
case 'album':
var items = [
{ handleClick: 'playURIs', label: 'Play', icon: 'play' },
{ handleClick: 'playURIsNext', label: 'Play next', icon: 'play' },
{ handleClick: 'addToQueue', label: 'Add to queue', icon: 'plus' },
+ { handleClick: 'startRadio', label: 'Start radio', icon: 'spotify' },
{ handleClick: 'copyURIs', label: 'Copy URI', icon: 'copy' }
]
break
@@ -174,12 +171,25 @@ class ContextMenu extends React.Component{
]
break
+ case 'editable-playlist-track':
+ var items = [
+ { handleClick: 'playURIs', label: 'Play', icon: 'play' },
+ { handleClick: 'playURIsNext', label: 'Play next', icon: 'play' },
+ { handleClick: 'addToQueue', label: 'Add to queue', icon: 'plus' },
+ { handleClick: 'addToPlaylist', label: 'Add to playlist', icon: 'plus', playlists: true },
+ { handleClick: 'startRadio', label: 'Start radio', icon: 'spotify' },
+ { handleClick: 'copyURIs', label: 'Copy URIs', icon: 'copy' },
+ { handleClick: 'removeFromPlaylist', label: 'Remove', icon: 'trash' }
+ ]
+ break
+
default:
var items = [
{ handleClick: 'playURIs', label: 'Play', icon: 'play' },
{ handleClick: 'playURIsNext', label: 'Play next', icon: 'play' },
{ handleClick: 'addToQueue', label: 'Add to queue', icon: 'plus' },
{ handleClick: 'addToPlaylist', label: 'Add to playlist', icon: 'plus', playlists: true },
+ { handleClick: 'startRadio', label: 'Start radio', icon: 'spotify' },
{ handleClick: 'copyURIs', label: 'Copy URIs', icon: 'copy' }
]
break
@@ -189,31 +199,23 @@ class ContextMenu extends React.Component{
}
renderTitle(){
- var style = {}
var item = this.props.context_menu.data.item
- var image = null
+ var style = null
if (item && item.images){
- image = helpers.sizedImages(item.images).medium
+ style = {
+ backgroundImage: 'url('+helpers.sizedImages(item.images).medium+')'
+ }
}
return (
-
- {image ?

: null}
- {this.props.context_menu.data.item.name}
-
+
+ {style ?
: null}
+
{item.name}
+
)
}
- renderItems(trigger){
- var items = this.getItems(trigger)
-
- var closeItem = (
-
- this.closeAndDeselectTracks(e) }>
-
- Cancel
-
-
- )
+ renderItems(){
+ var items = this.getItems()
return (
)
}
@@ -277,7 +278,7 @@ class ContextMenu extends React.Component{
return (
- {this.renderTitle()}
+ {this.props.context_menu.data.item ? this.renderTitle() : null}
{this.renderItems(trigger)}
);
@@ -298,6 +299,7 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = (dispatch) => {
return {
uiActions: bindActionCreators(uiActions, dispatch),
+ pusherActions: bindActionCreators(pusherActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch),
mopidyActions: bindActionCreators(mopidyActions, dispatch)
}
diff --git a/src/js/components/GridSlider.js b/src/js/components/GridSlider.js
index 79d85320..0098b95c 100755
--- a/src/js/components/GridSlider.js
+++ b/src/js/components/GridSlider.js
@@ -1,9 +1,16 @@
import React, { PropTypes } from 'react'
+import { connect } from 'react-redux'
+import { createStore, bindActionCreators } from 'redux'
+import { Link } from 'react-router'
import FontAwesome from 'react-fontawesome'
-import GridItem from './GridItem'
-export default class GridSlider extends React.Component{
+import ArtistSentence from './ArtistSentence'
+import Thumbnail from './Thumbnail'
+
+import * as uiActions from '../services/ui/actions'
+
+class GridSlider extends React.Component{
constructor(props) {
super(props)
@@ -15,6 +22,21 @@ export default class GridSlider extends React.Component{
}
}
+ handleClick(e,link){
+ if( e.target.tagName.toLowerCase() !== 'a' ){
+ hashHistory.push(link)
+ }
+ }
+
+ handleContextMenu(e,item){
+ e.preventDefault()
+ var data = {
+ uris: [item.uri],
+ item: item
+ }
+ this.props.uiActions.showContextMenu( e, data, 'album', 'click' )
+ }
+
next(){
if (this.state.page >= this._pagelimit) return false
this.setState({ page: this.state.page + 1 })
@@ -47,8 +69,19 @@ export default class GridSlider extends React.Component{
{
this.props.tracks.map(
(track, index) => {
- var item = Object.assign({}, track.album, { artists: track.artists })
- return
+ var album = Object.assign({}, track.album, { artists: track.artists })
+ return (
+
this.handleClick(e,global.baseURL+'album/'+album.uri) }
+ onContextMenu={e => this.handleContextMenu(e,album)}>
+
+
{ album.name }
+
+ { album.artists ?
:
- }
+
+
+ )
}
)
}
@@ -61,3 +94,15 @@ export default class GridSlider extends React.Component{
}
}
+const mapStateToProps = (state, ownProps) => {
+ return {}
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ uiActions: bindActionCreators(uiActions, dispatch)
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(GridSlider)
+
diff --git a/src/js/components/List.js b/src/js/components/List.js
index 88f2de74..43f5c8cb 100755
--- a/src/js/components/List.js
+++ b/src/js/components/List.js
@@ -25,10 +25,13 @@ class List extends React.Component{
}
}
- handleContextMenu(e,uri){
+ handleContextMenu(e,item){
e.preventDefault()
- var data = { uris: [uri] }
- this.props.uiActions.showContextMenu(e, data, helpers.uriType(uri), 'click')
+ var data = {
+ uris: [item.uri],
+ item: item
+ }
+ this.props.uiActions.showContextMenu(e, data, helpers.uriType(item.uri), 'click')
}
renderHeader(){
@@ -82,7 +85,7 @@ class List extends React.Component{
return (
this.handleClick(e, row.uri)}
- onContextMenu={e => this.handleContextMenu(e,row.uri)}
+ onContextMenu={e => this.handleContextMenu(e,row)}
className={className}
key={row_index}>
{
diff --git a/src/js/components/Sidebar.js b/src/js/components/Sidebar.js
index 0f8af507..2115136f 100755
--- a/src/js/components/Sidebar.js
+++ b/src/js/components/Sidebar.js
@@ -39,7 +39,7 @@ class Sidebar extends React.Component{
Discover
-
+
Discover
diff --git a/src/js/services/pusher/middleware.js b/src/js/services/pusher/middleware.js
index 588f2372..eb8082fe 100755
--- a/src/js/services/pusher/middleware.js
+++ b/src/js/services/pusher/middleware.js
@@ -214,7 +214,7 @@ const PusherMiddleware = (function(){
})
.then(
response => {
- uiActions.createNotification('Starting radio...')
+ store.dispatch(uiActions.createNotification('Starting radio...'))
}
)
@@ -252,11 +252,11 @@ const PusherMiddleware = (function(){
})
.then(
response => {
- uiActions.createNotification('Stopping radio')
+ store.dispatch(uiActions.createNotification('Stopping radio'))
}
)
- store.dispatch( uiActions.createNotification('Stopping radio') )
+ store.dispatch(uiActions.createNotification('Stopping radio'))
var data = {
action: 'stop_radio',
seed_artists: [],
diff --git a/src/js/services/spotify/actions.js b/src/js/services/spotify/actions.js
index d5431a51..c71d15c8 100755
--- a/src/js/services/spotify/actions.js
+++ b/src/js/services/spotify/actions.js
@@ -532,10 +532,9 @@ export function resolveRadioSeeds( radio ){
// add to our list of async requests
requests.push(
- sendRequest( dispatch, getState, 'tracks/'+ track_ids )
+ sendRequest( dispatch, getState, 'tracks?ids='+ track_ids )
.then( response => {
- if (!(response instanceof Array)) response = [response]
- Object.assign(resolved_seeds.seed_tracks, response);
+ Object.assign(resolved_seeds.seed_tracks, response.tracks);
})
)
}
diff --git a/src/js/services/spotify/middleware.js b/src/js/services/spotify/middleware.js
index 78214047..6aca393c 100755
--- a/src/js/services/spotify/middleware.js
+++ b/src/js/services/spotify/middleware.js
@@ -94,7 +94,7 @@ const SpotifyMiddleware = (function(){
// only resolve if radio is enabled
if( action.data.radio.enabled ){
- store.dispatch( spotifyActions.resolveRadioSeeds( action.data.radio ) )
+ store.dispatch(spotifyActions.resolveRadioSeeds(action.data.radio))
}
break
diff --git a/src/js/views/Playlist.js b/src/js/views/Playlist.js
index c94477ed..91228e00 100755
--- a/src/js/views/Playlist.js
+++ b/src/js/views/Playlist.js
@@ -153,7 +153,7 @@ class Playlist extends React.Component{
- { this.props.playlist.tracks ? this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null }
+ { this.props.playlist.tracks ? this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null }
this.loadMore() }/>
diff --git a/src/js/views/Queue.js b/src/js/views/Queue.js
index db32cb7f..7c7197d5 100755
--- a/src/js/views/Queue.js
+++ b/src/js/views/Queue.js
@@ -67,7 +67,7 @@ class Queue extends React.Component{
}
}
if (this.props.radio.seed_genres.length > 0) seed_sentence =this.props.radio.seed_artists.length+' genres'
- if (this.props.radio.seed_tracks.length > 0) seed_sentence =this.props.radio.seed_artists.length+' tracks'
+ if (this.props.radio.seed_tracks.length > 0) seed_sentence =this.props.radio.seed_tracks.length+' tracks'
return (
diff --git a/src/scss/components/_context-menu.scss b/src/scss/components/_context-menu.scss
index 31142f8d..c3bed4a3 100755
--- a/src/scss/components/_context-menu.scss
+++ b/src/scss/components/_context-menu.scss
@@ -25,21 +25,38 @@
cursor: pointer;
display: block;
padding: 8px 12px;
- width: 100%;
+ width: 140px;
font-weight: bold;
box-sizing: border-box;
position: relative;
overflow: hidden;
+ text-decoration: none;
+ background: $darkest_grey;
- img {
+ .background {
@include blur(5px);
background-size: cover;
- background-position: 50% 0%;
- opacity: 0.2;
+ background-position: 50% 20%;
+ opacity: 0.5;
position: absolute;
- top: 0;
- left: 0;
- right: 0;
+ top: -10px;
+ left: -10px;
+ bottom: -10px;
+ right: -10px;
+ z-index: 1;
+ }
+
+ .text {
+ @include one_line_text();
+ position: relative;
+ z-index: 2;
+ color: #FFFFFF;
+ }
+
+ &:hover{
+ .background {
+ opacity: 0.7;
+ }
}
}
@@ -87,7 +104,7 @@
opacity: 0.5;
}
- &:not(:first-child) .menu-item {
+ .menu-item {
border-top: 1px solid lighten($dark_grey, 8%);
}