More of a spotify-esque design
This commit is contained in:
@ -31,7 +31,7 @@ class FollowButton extends React.Component{
|
||||
render(){
|
||||
if( !this.props.spotify_authorized || !this.props.uri ) return false
|
||||
|
||||
var className = 'tertiary'
|
||||
var className = ''
|
||||
if (this.props.className) className += ' '+this.props.className
|
||||
|
||||
if( this.props.is_following === true ){
|
||||
|
||||
@ -97,37 +97,36 @@ class Album extends React.Component{
|
||||
return (
|
||||
<div className="view album-view">
|
||||
<SidebarToggleButton />
|
||||
<div className="intro">
|
||||
<Thumbnail size="large" canZoom images={ this.props.album.images } />
|
||||
<ArtistGrid artists={artists} />
|
||||
|
||||
<div className="actions">
|
||||
<button className="large primary" onClick={ e => this.play() }>Play</button>
|
||||
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton uri={this.props.params.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.album.is_following} /> : null }
|
||||
<Thumbnail size="large" canZoom images={ this.props.album.images } />
|
||||
|
||||
<div className="title">
|
||||
<div className="source grey-text">
|
||||
<FontAwesome name={helpers.sourceIcon( this.props.params.uri )} /> {helpers.uriSource( this.props.params.uri )} album
|
||||
</div>
|
||||
|
||||
<h1>{ this.props.album.name }</h1>
|
||||
|
||||
<ul className="details">
|
||||
{ artists.length > 0 ? <li><ArtistSentence artists={artists} /></li> : null }
|
||||
{ this.props.album.release_date ? <li><Dater type="date" data={ this.props.album.release_date } /></li> : null }
|
||||
<li>
|
||||
{ this.props.album.tracks_total } tracks,
|
||||
{ this.props.album.tracks ? <Dater type="total-time" data={this.props.album.tracks} /> : null }
|
||||
{ this.props.album.tracks_total ? this.props.album.tracks_total : '0' } tracks,
|
||||
{ this.props.album.tracks ? <Dater type="total-time" data={this.props.album.tracks} /> : '0 mins' }
|
||||
</li>
|
||||
{ this.props.album.release_date ? <li>Released <Dater type="date" data={ this.props.album.release_date } /></li> : null }
|
||||
<li><FontAwesome name={helpers.sourceIcon( this.props.params.uri )} /> {helpers.uriSource( this.props.params.uri )} playlist</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="main">
|
||||
|
||||
<div className="title">
|
||||
<h1>{ this.props.album.name }</h1>
|
||||
<h3><ArtistSentence artists={artists} /></h3>
|
||||
</div>
|
||||
|
||||
<section className="list-wrapper">
|
||||
{ this.props.album.tracks ? <TrackList tracks={ this.props.album.tracks } /> : null }
|
||||
<LazyLoadListener enabled={this.props.album.tracks_more} loadMore={ () => this.loadMore() }/>
|
||||
</section>
|
||||
|
||||
<div className="actions">
|
||||
<button className="rounded primary" onClick={e => this.play()}>Play</button>
|
||||
{ helpers.uriSource(this.props.params.uri) == 'spotify' ? <FollowButton className="outline rounded" uri={this.props.params.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.album.is_following} /> : null }
|
||||
</div>
|
||||
|
||||
<section className="list-wrapper">
|
||||
{ this.props.album.tracks ? <TrackList tracks={ this.props.album.tracks } /> : null }
|
||||
<LazyLoadListener enabled={this.props.album.tracks_more} loadMore={ () => this.loadMore() }/>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ class Artist extends React.Component{
|
||||
}
|
||||
|
||||
componentWillUpdate( nextProps, nextState ){
|
||||
if( nextState.sub_view != this.state.sub_view && nextState.sub_view == 'biography' ){
|
||||
if( nextState.sub_view != this.state.sub_view && nextState.sub_view == 'about' ){
|
||||
if( this.props.artist && !this.props.artist.bio ){
|
||||
this.props.lastfmActions.getArtist( this.props.params.uri, this.props.artist.name.replace('&','and') )
|
||||
}
|
||||
@ -91,8 +91,8 @@ class Artist extends React.Component{
|
||||
Overview
|
||||
</span>
|
||||
{this.props.artist.related_artists_uris ? <span className={'option '+( this.state.sub_view == 'related_artists' ? 'active' : null)} onClick={() => this.setState({ sub_view: 'related_artists' })}>Related artists</span> : null}
|
||||
<span className={'option '+( this.state.sub_view == 'biography' ? 'active' : null)} onClick={() => this.setState({ sub_view: 'biography' })}>
|
||||
Biography
|
||||
<span className={'option '+( this.state.sub_view == 'about' ? 'active' : null)} onClick={() => this.setState({ sub_view: 'about' })}>
|
||||
About
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
@ -130,9 +130,9 @@ class Artist extends React.Component{
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}else if( this.state.sub_view == 'biography' ){
|
||||
}else if( this.state.sub_view == 'about' ){
|
||||
return (
|
||||
<div className="body biography">
|
||||
<div className="body about">
|
||||
<h4 className="left-padding">Biography</h4>
|
||||
|
||||
<ul className="details">
|
||||
@ -195,8 +195,8 @@ class Artist extends React.Component{
|
||||
<div className="liner">
|
||||
<h1>{ this.props.artist.name }</h1>
|
||||
<div className="actions">
|
||||
<button className="primary rounded" onClick={e => this.props.pusherActions.startRadio([this.props.artist.uri])}>Start radio</button>
|
||||
{ scheme == 'spotify' ? <FollowButton className="rounded" uri={this.props.params.uri} removeText="Unfollow" addText="Follow" is_following={this.props.artist.is_following} /> : null }
|
||||
{ scheme == 'spotify' ? <button className="primary rounded" onClick={e => this.props.pusherActions.startRadio([this.props.artist.uri])}>Start radio</button> : null }
|
||||
{ scheme == 'spotify' ? <FollowButton className="outline rounded white" uri={this.props.params.uri} removeText="Unfollow" addText="Follow" is_following={this.props.artist.is_following} /> : null }
|
||||
</div>
|
||||
{ this.renderSubViewMenu() }
|
||||
</div>
|
||||
|
||||
@ -95,8 +95,8 @@ class Playlist extends React.Component{
|
||||
case 'm3u':
|
||||
return (
|
||||
<span>
|
||||
<button className="large tertiary" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name }) }>Edit</button>
|
||||
<ConfirmationButton className="large tertiary" content="Delete" confirmingContent="Are you sure?" onConfirm={ e => this.delete() } />
|
||||
<button className="rounded outline" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name }) }>Edit</button>
|
||||
<ConfirmationButton className="rounded destructive" content="Delete" confirmingContent="Are you sure?" onConfirm={ e => this.delete() } />
|
||||
</span>
|
||||
)
|
||||
|
||||
@ -104,12 +104,12 @@ class Playlist extends React.Component{
|
||||
if( this.props.playlist.can_edit ){
|
||||
return (
|
||||
<span>
|
||||
<button className="large tertiary" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name, is_public: this.props.playlist.public }) }>Edit</button>
|
||||
<ConfirmationButton className="large tertiary" content="Delete" confirmingContent="Are you sure?" onConfirm={ e => this.unfollow() } />
|
||||
<button className="outline rounded" onClick={ e => this.props.uiActions.openModal('edit_playlist', { uri: this.props.playlist.uri, name: this.props.playlist.name, is_public: this.props.playlist.public }) }>Edit</button>
|
||||
<ConfirmationButton className="rounded destructive" content="Delete" confirmingContent="Are you sure?" onConfirm={ e => this.unfollow() } />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
return <FollowButton uri={this.props.playlist.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.playlist.is_following} />
|
||||
return <FollowButton className="rounded outline" uri={this.props.playlist.uri} addText="Add to library" removeText="Remove from library" is_following={this.props.playlist.is_following} />
|
||||
|
||||
}
|
||||
}
|
||||
@ -126,41 +126,38 @@ class Playlist extends React.Component{
|
||||
|
||||
<SidebarToggleButton />
|
||||
|
||||
<div className="intro">
|
||||
<Thumbnail size="large" canZoom images={ this.props.playlist.images } />
|
||||
|
||||
<Thumbnail size="large" canZoom images={ this.props.playlist.images } />
|
||||
|
||||
<div className="actions">
|
||||
<button className="large primary" onClick={ e => this.play() }>Play</button>
|
||||
{ this.renderExtraButtons() }
|
||||
<div className="title">
|
||||
<div className="source grey-text">
|
||||
<FontAwesome name={helpers.sourceIcon( this.props.params.uri )} /> {helpers.uriSource( this.props.params.uri )} playlist
|
||||
</div>
|
||||
<h1>{ this.props.playlist.name }</h1>
|
||||
{ this.props.playlist.description ? <div className="description grey-text" dangerouslySetInnerHTML={{__html: this.props.playlist.description}}></div> : null }
|
||||
|
||||
<ul className="details">
|
||||
<li>
|
||||
{ this.props.playlist.tracks_total } tracks,
|
||||
{ this.props.playlist.tracks ? <Dater type="total-time" data={this.props.playlist.tracks} /> : null }
|
||||
</li>
|
||||
{ this.props.playlist.last_modified ? <li>Updated <Dater type="ago" data={this.props.playlist.last_modified} /> ago</li> : null }
|
||||
{ this.props.playlist.owner ? <li><Link to={'/user/'+this.props.playlist.owner.uri}>{this.props.playlist.owner.id}</Link></li> : null }
|
||||
|
||||
{ this.props.playlist.followers ? <li>{this.props.playlist.followers.total.toLocaleString()} followers</li> : null }
|
||||
{ scheme == 'spotify' && this.props.playlist.owner ? <li>By <Link to={'/user/'+this.props.playlist.owner.uri}>{this.props.playlist.owner.id}</Link> { !this.props.playlist.public ? <FontAwesome name="lock" /> : null }</li> : null }
|
||||
{ scheme == 'spotify' ? <li><FontAwesome name="spotify" /> Spotify playlist</li> : null }
|
||||
{ scheme == 'm3u' ? <li><FontAwesome name="folder" /> Local playlist</li> : null }
|
||||
|
||||
{ this.props.playlist.last_modified ? <li><Dater type="ago" data={this.props.playlist.last_modified} /></li> : null }
|
||||
|
||||
<li>
|
||||
{ this.props.playlist.tracks_total ? this.props.playlist.tracks_total : '0'} tracks,
|
||||
{ this.props.playlist.tracks ? <Dater type="total-time" data={this.props.playlist.tracks} /> : '0 mins' }
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div className="main">
|
||||
|
||||
<div className="title">
|
||||
<h1>{ this.props.playlist.name }</h1>
|
||||
{ this.props.playlist.description ? <h3 className="grey-text" dangerouslySetInnerHTML={{__html: this.props.playlist.description}}></h3> : null }
|
||||
</div>
|
||||
|
||||
<section className="list-wrapper">
|
||||
{ this.props.playlist.tracks ? <TrackList tracklist_uri={this.props.params.uri} context={context} tracks={this.props.playlist.tracks} removeTracks={ tracks_indexes => this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null }
|
||||
<LazyLoadListener enabled={this.props.playlist.tracks_more} loadMore={ () => this.loadMore() }/>
|
||||
</section>
|
||||
|
||||
<div className="actions">
|
||||
<button className="rounded primary" onClick={ e => this.play() }>Play</button>
|
||||
{ this.renderExtraButtons() }
|
||||
</div>
|
||||
|
||||
<section className="list-wrapper">
|
||||
{ this.props.playlist.tracks ? <TrackList tracklist_uri={this.props.params.uri} context={context} tracks={this.props.playlist.tracks} removeTracks={ tracks_indexes => this.removeTracks(tracks_indexes) } reorderTracks={ (indexes, index) => this.reorderTracks(indexes, index) } /> : null }
|
||||
<LazyLoadListener enabled={this.props.playlist.tracks_more} loadMore={ () => this.loadMore() }/>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -181,10 +181,20 @@ footer {
|
||||
.details {
|
||||
list-style-type: none;
|
||||
color: $mid_grey;
|
||||
text-transform: uppercase;
|
||||
|
||||
li {
|
||||
padding-bottom: 4px;
|
||||
display: inline-block;
|
||||
|
||||
&:not(:first-child){
|
||||
padding-left: 14px;
|
||||
|
||||
&::before {
|
||||
display: inline-block;
|
||||
content: '•';
|
||||
margin-left: -8px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +62,29 @@ input[type="submit"] {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
&.outline {
|
||||
color: #FFFFFF;
|
||||
padding: 9px 19px;
|
||||
border: 1px solid $darkest_grey;
|
||||
background: transparent;
|
||||
color: $darkest_grey;
|
||||
|
||||
&.white {
|
||||
border-color: #FFFFFF;
|
||||
color: #FFFFFF;
|
||||
background: rgba(0,0,0,0.2);
|
||||
|
||||
&:hover {
|
||||
background: rgba(0,0,0,0.4);
|
||||
border-color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $turquoise;
|
||||
}
|
||||
}
|
||||
|
||||
&.primary {
|
||||
background: $turquoise;
|
||||
color: #FFFFFF;
|
||||
|
||||
@ -1,105 +1,29 @@
|
||||
|
||||
.album-view {
|
||||
.main {
|
||||
padding-left: 300px;
|
||||
|
||||
.title {
|
||||
padding: 30px 40px;
|
||||
.title {
|
||||
padding: 30px 40px;
|
||||
|
||||
h3 {
|
||||
color: $mid_grey;
|
||||
a:hover {
|
||||
color: darken($mid_grey, 20%);
|
||||
}
|
||||
h3 {
|
||||
color: $mid_grey;
|
||||
a:hover {
|
||||
color: darken($mid_grey, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
background: $faint_grey;
|
||||
|
||||
.thumbnail {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.details {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.artist-grid {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
.grid-item {
|
||||
margin: 0;
|
||||
width: 50%;
|
||||
position: relative;
|
||||
background: #000000;
|
||||
|
||||
.name {
|
||||
@include animate();
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
color: #FFFFFF;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
font-weight: bold;;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.thumbnail {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.name {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.source {
|
||||
text-transform: uppercase;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
@include responsive( $bp_medium ){
|
||||
.actions {
|
||||
@include clearfix();
|
||||
}
|
||||
|
||||
.main {
|
||||
padding-left: 0;
|
||||
|
||||
.title {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
position: static;
|
||||
width: auto;
|
||||
|
||||
.artist-grid {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.details {
|
||||
padding: 20px;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.thumbnail {
|
||||
float: left;
|
||||
max-width: 230px;
|
||||
margin: 0 30px 30px 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
.liner {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 15vh 40px 20px 40px;
|
||||
padding: 20vh 40px 0 40px;
|
||||
|
||||
h1 {
|
||||
color: #FFFFFF;
|
||||
@ -26,21 +26,20 @@
|
||||
}
|
||||
|
||||
.actions {
|
||||
.button {
|
||||
margin-right: 30px;
|
||||
padding-bottom: 15px;
|
||||
|
||||
button {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-views {
|
||||
color: #FFFFFF;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 30px;
|
||||
|
||||
.option {
|
||||
display: inline-block;
|
||||
padding: 8px 0;
|
||||
margin: 0 10px;
|
||||
margin: 0 25px 0 0;
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
border-bottom: 4px solid transparent;
|
||||
|
||||
@ -1,103 +1,33 @@
|
||||
|
||||
.playlist-view {
|
||||
.main {
|
||||
padding-left: 300px;
|
||||
|
||||
.title {
|
||||
padding: 30px 40px;
|
||||
.title {
|
||||
padding: 30px 40px;
|
||||
|
||||
h3 {
|
||||
color: $mid_grey;
|
||||
a:hover {
|
||||
color: darken($mid_grey, 20%);
|
||||
}
|
||||
h3 {
|
||||
color: $mid_grey;
|
||||
a:hover {
|
||||
color: darken($mid_grey, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
background: $faint_grey;
|
||||
|
||||
> .thumbnail {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.details {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.artist-grid {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
.grid-item {
|
||||
margin: 0;
|
||||
width: 50%;
|
||||
position: relative;
|
||||
|
||||
.thumbnail .image {
|
||||
background-color: $secondary_grey;
|
||||
}
|
||||
|
||||
.name {
|
||||
@include animate();
|
||||
position: absolute;
|
||||
top: 35%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
color: #FFFFFF;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.name {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.owner {
|
||||
padding: 30px;
|
||||
}
|
||||
.source {
|
||||
text-transform: uppercase;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
@include responsive( $bp_medium ){
|
||||
.actions {
|
||||
@include clearfix();
|
||||
}
|
||||
|
||||
.main {
|
||||
padding-left: 0px;
|
||||
.description {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.intro {
|
||||
width: auto;
|
||||
position: static;
|
||||
|
||||
.details {
|
||||
padding: 20px;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.thumbnail {
|
||||
float: left;
|
||||
max-width: 230px;
|
||||
margin: 0 30px 30px 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user