local artists

This commit is contained in:
James Barnsley
2016-11-01 19:27:59 +13:00
parent 1738c2a29b
commit 4fdbef2b4e
17 changed files with 6258 additions and 5931 deletions

View File

@ -3066,6 +3066,10 @@ main .left-padding {
width: 95%;
}
.col.w100 {
width: 100%;
}
.cf::after {
content: '';
clear: both;
@ -3497,12 +3501,6 @@ aside .player .controls a:hover {
display: block;
}
.list-item .col {
width: 10%;
min-height: 1px;
float: left;
}
.list-item.selected {
background: #FFF39C !important;
}
@ -3510,6 +3508,7 @@ aside .player .controls a:hover {
.list-item:not(.header):hover {
background: #EEEEEE;
cursor: pointer;
border-color: #EEEEEE;
}
.list-item.header {

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

45
src/js/components/List.js Executable file
View File

@ -0,0 +1,45 @@
import React, { PropTypes } from 'react'
import { Link } from 'react-router'
export default class List extends React.Component{
constructor(props) {
super(props);
}
renderHeader(){
if( !this.props.columns ) return null
return (
<div className="list-item header cf">
{
this.props.columns.map( (col, col_index) => {
return <div className={'col w'+col.width} key={col_index}>{ col.name }</div>
})
}
</div>
)
}
render(){
return (
<div className="list">
{ this.renderHeader() }
{
this.props.rows.map( (row, row_index) => {
return (
<Link to={ this.props.link_prefix + encodeURIComponent(row.uri)} className="list-item cf" key={row_index}>
{
this.props.columns.map( (col, col_index) => {
return <div className={'col w'+col.width} key={col_index}>{ row[col.name] }</div>
})
}
</Link>
)
})
}
</div>
);
}
}

View File

@ -24,7 +24,7 @@ export default class Parallax extends React.Component{
}
componentDidMount(){
var url = helpers.SizedImages( this.props.images ).huge;
var url = helpers.sizedImages( this.props.images ).huge;
this.loadImage( url )
.then(
response => {

View File

@ -34,7 +34,7 @@ export default class Thumbnail extends React.Component{
huge: require('../../images/no-image.svg')
}
}else{
state = helpers.SizedImages( images );
state = helpers.sizedImages( images );
}
this.setState( state );

View File

@ -1,6 +1,6 @@
export let SizedImages = function( images ){
export let sizedImages = function( images ){
var sizes = {
small: false,
@ -14,7 +14,7 @@ export let SizedImages = function( images ){
for( var i = 0; i < images.length; i++ ){
// spotify-styled images
if( images[i].height ){
if( typeof(images[i].height) !== 'undefined' ){
if( images[i].height > 800 ){
sizes.huge = images[i].url;
}else if( images[i].height > 600 ){

View File

@ -31,6 +31,7 @@ import LibraryTracks from './views/library/LibraryTracks'
import LibraryPlaylists from './views/library/LibraryPlaylists'
import LibraryLocal from './views/library/LibraryLocal'
import LibraryLocalDirectory from './views/library/LibraryLocalDirectory'
import LibraryLocalArtists from './views/library/LibraryLocalArtists'
ReactDOM.render(
<Provider store={store}>
@ -52,6 +53,7 @@ ReactDOM.render(
<Route path="library/playlists" component={LibraryPlaylists} />
<Route path="library/local" component={LibraryLocal} />
<Route path="library/local/directory/:uri" component={LibraryLocalDirectory} />
<Route path="library/local/artists" component={LibraryLocalArtists} />
<Route path="album/:uri" component={Album} />
<Route path="artist/:uri" component={Artist} />

View File

@ -124,3 +124,9 @@ export function getArtist( uri ){
}
}
export function getArtists(){
return {
type: 'MOPIDY_ARTISTS'
}
}

View File

@ -155,6 +155,7 @@ const MopidyMiddleware = (function(){
break;
case 'MOPIDY_PLAYLIST':
store.dispatch({ type: 'MOPIDY_PLAYLIST_LOADED', data: false });
instruct( socket, store, 'playlists.lookup', action.data )
.then( response => {
var playlist = response;
@ -196,6 +197,7 @@ const MopidyMiddleware = (function(){
break;
case 'MOPIDY_ALBUM':
store.dispatch({ type: 'MOPIDY_ALBUM_LOADED', data: false });
instruct( socket, store, 'library.lookup', action.data )
.then( response => {
var album = response[0].album;
@ -238,14 +240,13 @@ const MopidyMiddleware = (function(){
break;
case 'MOPIDY_ARTIST':
store.dispatch({ type: 'MOPIDY_ARTIST_LOADED', data: false });
instruct( socket, store, 'library.lookup', action.data )
.then( response => {
var artist = {
name: 'yeah',
images: [],
albums: [],
tracks: response.slice(0,10)
}
var artist = response[0].artists[0];
artist.images = [];
artist.albums = [];
artist.tracks = response.slice(0,10);
for( var i = 0; i < response.length; i++ ){
var album = response[i].album;
@ -263,6 +264,16 @@ const MopidyMiddleware = (function(){
})
break;
case 'MOPIDY_ARTISTS':
store.dispatch({ type: 'MOPIDY_ARTISTS_LOADED', data: false });
instruct( socket, store, 'library.browse', { uri: 'local:directory?type=artist' } )
.then( response => {
var artists = response;
store.dispatch({ type: 'MOPIDY_ARTISTS_LOADED', data: artists });
})
break;
// This action is irrelevant to us, pass it on to the next middleware
default:
return next(action);

View File

@ -92,6 +92,11 @@ export default function reducer(mopidy = {}, action){
artist: action.data
});
case 'MOPIDY_ARTISTS_LOADED':
return Object.assign({}, mopidy, {
artists: action.data
});
default:
return mopidy
}

View File

@ -98,19 +98,8 @@ class Artist extends React.Component{
<h1>{ artist.name }</h1>
</div>
<div className="col w70">
<h4 className="left-padding">Top tracks</h4>
{ artist.tracks ? <TrackList tracks={ artist.tracks } /> : null }
</div>
<div className="col w5"></div>
<div className="col w25">
<h4>Related artists</h4>
{ artist.related_artists ? <ArtistList artists={ artist.artist.related_artists.slice(0,6) } /> : null }
</div>
<div className="cf"></div>
<h4 className="left-padding">Top tracks</h4>
{ artist.tracks ? <TrackList tracks={ artist.tracks } /> : null }
<h4 className="left-padding">Albums</h4>
{ artist.albums ? <AlbumGrid className="no-top-padding" albums={ artist.albums } /> : null }

View File

@ -17,6 +17,7 @@ export default class LibraryLocal extends React.Component{
<div className="view library-local-view">
<Header icon="folder" title="Local" />
<Link to="/library/local/directory/local:directory">Folders</Link>
<Link to="/library/local/artists">Artists</Link>
</div>
);
}

View File

@ -0,0 +1,67 @@
import React, { PropTypes } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import Header from '../../components/Header'
import List from '../../components/List'
import * as mopidyActions from '../../services/mopidy/actions'
import * as spotifyActions from '../../services/spotify/actions'
class LibraryLocalArtists extends React.Component{
constructor(props) {
super(props);
}
// on render
componentDidMount(){
this.loadArtists()
}
componentWillReceiveProps( nextProps ){
if( !this.props.mopidy.connected && nextProps.mopidy.connected ){
this.loadArtists(nextProps);
}
}
loadArtists(props = this.props){
if( props.mopidy.connected ){
this.props.mopidyActions.getArtists();
}
}
render(){
if( !this.props.mopidy.artists ) return null
return (
<div className="view library-local-view">
<Header icon="music" title="Local" />
<div>
<List columns={[{ name: 'name', width: '100'}]} rows={this.props.mopidy.artists} link_prefix="/artist/" />
</div>
</div>
);
}
}
/**
* Export our component
*
* We also integrate our global store, using connect()
**/
const mapStateToProps = (state, ownProps) => {
return state;
}
const mapDispatchToProps = (dispatch) => {
return {
mopidyActions: bindActionCreators(mopidyActions, dispatch),
spotifyActions: bindActionCreators(spotifyActions, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LibraryLocalArtists)

View File

@ -11,24 +11,19 @@
display: block;
position: relative;
padding: 9px 10px 9px 40px;
border-top: 1px solid #EEEEEE;
border-bottom: 1px solid #EEEEEE;
border-top: 1px solid $faint_grey;
border-bottom: 1px solid $faint_grey;
margin-bottom: -1px;
@include clearfix;
.col {
width: 10%;
min-height: 1px;
float: left;
}
&.selected {
background: #FFF39C !important;
}
&:not(.header):hover {
background: #EEEEEE;
background: $faint_grey;
cursor: pointer;
border-color: $faint_grey;
}
&.header {

View File

@ -103,6 +103,7 @@ main {
&.w85 { width: 85%; }
&.w90 { width: 90%; }
&.w95 { width: 95%; }
&.w100 { width: 100%; }
}
.cf{