Work on artists

This commit is contained in:
nelsonlaquet 2013-07-31 21:47:21 -05:00
parent 70dccafa9c
commit 1aac8a8f64
25 changed files with 324 additions and 129 deletions

View file

@ -93,23 +93,7 @@
$albums = [];
foreach ($query->get() as $album) {
$albums[] = [
'id' => $album->id,
'track_count' => $album->tracks->count(),
'title' => $album->title,
'slug' => $album->slug,
'created_at' => $album->created_at,
'covers' => [
'small' => $album->getCoverUrl(Image::SMALL),
'normal' => $album->getCoverUrl(Image::NORMAL)
],
'url' => $album->url,
'user' => [
'id' => $album->user->id,
'name' => $album->user->display_name,
'url' => $album->user->url,
]
];
$albums[] = Album::mapPublicAlbumSummary($album);
}
return Response::json(["albums" => $albums, "current_page" => $page, "total_pages" => ceil($count / $perPage)], 200);

View file

@ -17,11 +17,49 @@
use Illuminate\Support\Facades\Response;
class ArtistsController extends \ApiControllerBase {
public function getContent($slug) {
$user = User::whereSlug($slug)->first();
if (!$user)
App::abort(404);
$query = Track::summary()->whereUserId($user->id)->whereNotNull('published_at');
$tracks = [];
$singles = [];
foreach ($query->get() as $track) {
if ($track->album_id != null)
$tracks[] = Track::mapPublicTrackSummary($track);
else
$singles[] = Track::mapPublicTrackSummary($track);
}
$query = Album::summary()
->with('tracks', 'user')
->orderBy('created_at', 'desc')
->whereRaw('(SELECT COUNT(id) FROM tracks WHERE tracks.album_id = albums.id) > 0')
->whereUserId($user->id);
$albums = [];
foreach ($query->get() as $album) {
$albums[] = Album::mapPublicAlbumSummary($album);
}
return Response::json(['singles' => $singles, 'albumTracks' => $tracks, 'albums' => $albums], 200);
}
public function getShow($slug) {
$user = User::whereSlug($slug)->first();
if (!$user)
App::abort(404);
$trackQuery = Track::summary()->whereUserId($user->id)->whereNotNull('published_at')->orderBy('created_at', 'desc')->take(10);
$latestTracks = [];
foreach ($trackQuery->get() as $track) {
$latestTracks[] = Track::mapPublicTrackSummary($track);
}
return Response::json([
'artist' => [
'id' => $user->id,
@ -31,7 +69,13 @@
'small' => $user->getAvatarUrl(Image::SMALL),
'normal' => $user->getAvatarUrl(Image::NORMAL)
],
'created_at' => $user->created_at
'created_at' => $user->created_at,
'followers' => [],
'following' => [],
'latest_tracks' => $latestTracks,
'comments' => ['count' => 0, 'list' => []],
'bio' => $user->bio,
'mlpforums_username' => $user->mlpforums_name
]
], 200);
}

View file

@ -30,6 +30,26 @@
return $this->hasMany('Entities\Track')->orderBy('track_number', 'asc');
}
public static function mapPublicAlbumSummary($album) {
return [
'id' => $album->id,
'track_count' => $album->tracks->count(),
'title' => $album->title,
'slug' => $album->slug,
'created_at' => $album->created_at,
'covers' => [
'small' => $album->getCoverUrl(Image::SMALL),
'normal' => $album->getCoverUrl(Image::NORMAL)
],
'url' => $album->url,
'user' => [
'id' => $album->user->id,
'name' => $album->user->display_name,
'url' => $album->user->url,
]
];
}
public function hasCover() {
return $this->cover_id != null;
}

View file

@ -53,7 +53,9 @@
Route::get('/albums/{id}', 'Api\Web\AlbumsController@getShow')->where('id', '\d+');
Route::get('/artists', 'Api\Web\ArtistsController@getIndex');
Route::get('/artists/{slug}', 'Api\Web\ArtistsController@getShow')->where('id', '[-\w]');
Route::get('/artists/{slug}', 'Api\Web\ArtistsController@getShow');
Route::get('/artists/{slug}/content', 'Api\Web\ArtistsController@getContent');
Route::get('/artists/{slug}/favourites', 'Api\Web\ArtistsController@getFavourites');
Route::get('/dashboard', 'Api\Web\DashboardController@getIndex');
@ -113,6 +115,8 @@
Route::get('u{id}', 'ArtistsController@getShortlink')->where('id', '\d+');
Route::get('users/{id}-{slug}', 'ArtistsController@getShortlink')->where('id', '\d+');
Route::get('{slug}', 'ArtistsController@getProfile')->where('id', '[-\w]');
Route::get('{slug}', 'ArtistsController@getProfile');
Route::get('{slug}/content', 'ArtistsController@getProfile');
Route::get('{slug}/favourites', 'ArtistsController@getProfile');
Route::get('/', 'HomeController@getIndex');

View file

@ -174,9 +174,25 @@ angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable'],
# Final catch-all for aritsts
state.state 'artist',
url: '^/:slug'
templateUrl: '/templates/artists/show.html'
templateUrl: '/templates/artists/_show_layout.html'
abstract: true
controller: 'artist'
state.state 'artist.profile',
url: ''
templateUrl: '/templates/artists/profile.html'
controller: 'artist-profile'
state.state 'artist.content',
url: '/content'
templateUrl: '/templates/artists/content.html'
controller: 'artist-content'
state.state 'artist.favourites',
url: '/favourites'
templateUrl: '/templates/artists/favourites.html'
controller: 'artist-favourites'
route.otherwise '/'
location.html5Mode(true);

View file

@ -0,0 +1,12 @@
window.pfm.preloaders['artist-content'] = [
'artists', '$state'
(artists, $state) ->
$.when.all [artists.fetch($state.params.slug, true), artists.fetchContent($state.params.slug, true)]
]
angular.module('ponyfm').controller "artist-content", [
'$scope', 'artists', '$state'
($scope, artists, $state) ->
artists.fetchContent($state.params.slug).done (artistResponse) ->
$scope.content = artistResponse
]

View file

@ -0,0 +1,12 @@
window.pfm.preloaders['artist-favourites'] = [
'artists', '$state'
(artists, $state) ->
artists.fetch $state.params.slug, true
]
angular.module('ponyfm').controller "artist-favourites", [
'$scope', 'artists', '$state'
($scope, artists, $state) ->
artists.fetch($state.params.slug).done (artistResponse) ->
$scope.artist = artistResponse.artist
]

View file

@ -0,0 +1,10 @@
window.pfm.preloaders['artist-profile'] = [
'artists', '$state'
(artists, $state) ->
artists.fetch $state.params.slug, true
]
angular.module('ponyfm').controller "artist-profile", [
'$scope', 'artists', '$state'
($scope, artists, $state) ->
]

View file

@ -1,7 +1,7 @@
window.pfm.preloaders['artist'] = [
'artists', '$state'
(artists, $state) ->
artists.fetch $state.params.slug
artists.fetch $state.params.slug, true
]
angular.module('ponyfm').controller "artist", [

View file

@ -0,0 +1,11 @@
angular.module('ponyfm').directive 'pfmAlbumsList', () ->
restrict: 'E'
templateUrl: '/templates/directives/albums-list.html'
scope:
albums: '=albums',
class: '@class'
controller: [
'$scope'
($scope) ->
]

View file

@ -0,0 +1,11 @@
angular.module('ponyfm').directive 'pfmTracksList', () ->
restrict: 'E'
templateUrl: '/templates/directives/tracks-list.html'
scope:
tracks: '=tracks',
class: '@class'
controller: [
'$scope'
($scope) ->
]

View file

@ -3,6 +3,7 @@ angular.module('ponyfm').factory('artists', [
($rootScope, $http) ->
artistPage = []
artists = {}
artistContent = {}
self =
filters: {}
@ -28,5 +29,15 @@ angular.module('ponyfm').factory('artists', [
artists[slug] = artistsDef.promise()
fetchContent: (slug, force) ->
force = force || false
slug = 1 if !slug
return artistContent[slug] if !force && artistContent[slug]
artistsDef = new $.Deferred()
$http.get('/api/web/artists/' + slug + '/content').success (albums) ->
artistsDef.resolve albums
artistContent[slug] = artistsDef.promise()
self
])

View file

@ -442,8 +442,10 @@ header {
border-bottom: 2px solid #ddd;
margin-bottom: 2px;
}
}
> div > .tabs {
html {
.tabs {
.clearfix();
list-style: none;
border-bottom: 4px solid #ddd;

View file

@ -24,6 +24,16 @@
padding: 0px;
list-style: none;
&.no-artist {
li {
.info {
.artist {
display: none;
}
}
}
}
&.two-column {
li {
.box-sizing(border-box);
@ -35,6 +45,17 @@
}
}
&.four-column {
li {
.box-sizing(border-box);
width: 25%;
float: left;
margin: 0px;
padding: 5px;
}
}
li {
overflow: hidden;
margin: 10px 0px;
@ -127,13 +148,25 @@
}
}
.track-details, .album-details {
h1 {
.user-details {
.header {
.box-shadow(0px 2px 3px rgba(0, 0, 0, .3));
background: #eee;
h1 {
padding: 5px;
}
.tabs {
background: #f0f0f0;
margin: 0px;
border: none;
border-top: 1px solid #ddd;
}
}
}
.user-details, .track-details, .album-details {
.comments {
.alert {
.border-radius(0px);
@ -177,6 +210,14 @@
}
}
}
}
.track-details, .album-details {
h1 {
.box-shadow(0px 2px 3px rgba(0, 0, 0, .3));
background: #eee;
padding: 5px;
}
.lyrics {
font-size: 10pt;

View file

@ -1,14 +1,3 @@
<ul class="albums-listing stretch-to-bottom">
<li ng-repeat="album in albums">
<a href="{{album.url}}">
<img class="image" ng-src="{{album.covers.normal}}" />
<span class="title">{{album.title}}</span>
<span class="published">
by {{album.user.name}}
</span>
</a>
</li>
<li ng-show="!albums.length" class="empty">
No albums found...
</li>
</ul>
<div class="stretch-to-bottom">
<pfm-albums-list albums="albums" />
</div>

View file

@ -34,26 +34,7 @@
</div>
<h2>Tracks</h2>
<ul class="tracks-listing">
<li ng-repeat="track in album.tracks">
<div class="image">
<a href="#" class="play-button"><i class="icon-play"></i></a>
<img ng-src="{{track.covers.thumbnail}}" />
</div>
<div class="icons">
<span><i ng-class="{'icon-microphone-off': !track.is_vocal, 'icon-microphone': track.is_vocal}"></i></span>
<a href="#"><i class="icon-star-empty"></i></a>
</div>
<a class="info" href="{{track.url}}">
<span class="title">{{track.title}}</span>
<span class="metadata">
by: <span class="artist">{{track.user.name}}</span> /
<span class="genre">{{track.genre.name}}</span> /
{{track.published_at.date | momentFromNow}}
</span>
</a>
</li>
</ul>
<pfm-tracks-list tracks="album.tracks" />
<h2>Comments</h2>
<div class="comments">

View file

@ -0,0 +1,34 @@
<div class="user-details">
<ul class="breadcrumb">
<li><a href="/artists">Artist Directory</a> <span class="divider">/</span></li>
<li class="active">{{artist.name}}</li>
</ul>
<div class="track-toolbar btn-group pull-right">
<a href="#" class="btn btn-small">
Follow
</a>
<a href="#" class="btn btn-small">
Send a Message
</a>
<a href="#" class="btn btn-small">
MLP Forums Profile
</a>
</div>
<div class="header">
<h1>
{{artist.name}}
</h1>
<ul class="tabs">
<li ng-class="{active: $state.includes('artist.profile')}"><a href="{{artist.slug}}">Profile</a></li>
<li ng-class="{active: $state.includes('artist.content')}"><a href="{{artist.slug}}/content">Content</a></li>
<li ng-class="{active: $state.includes('artist.favourites')}"><a href="{{artist.slug}}/favourites">Favourites</a></li>
</ul>
</div>
<div class="stretch-to-bottom">
<ui-view></ui-view>
</div>
</div>

View file

@ -0,0 +1,14 @@
<div ng-show="content.albums.length">
<h2>Albums</h2>
<pfm-albums-list albums="content.albums" />
</div>
<div ng-show="content.singles.length">
<h2>Singles</h2>
<pfm-tracks-list tracks="content.singles" class="four-column no-artist" />
</div>
<div ng-show="content.albumTracks.length">
<h2>Part of an Album</h2>
<pfm-tracks-list tracks="content.albumTracks" class="four-column no-artist" />
</div>

View file

@ -0,0 +1 @@
favourites!

View file

@ -0,0 +1,27 @@
<div class="row-fluid">
<div class="span6">
<div ng-show="artist.bio.trim().length">
<h2>Bio</h2>
<div class="description">
<p ng-bind-html-unsafe="artist.bio | noHTML | newlines"></p>
</div>
</div>
<h2>Comments</h2>
<div class="comments">
<div class="alert alert-info" ng-show="artist.comments.count == 0">
There are no comments yet!
</div>
<form class="pfm-form">
<div class="form-row">
<textarea></textarea>
</div>
<button type="submit" class="btn disabled">Post Comment</button>
</form>
</div>
</div>
<div class="span6 cover-image">
<h2>Recent Tracks</h2>
<pfm-tracks-list tracks="artist.latest_tracks" class="two-column no-artist" />
</div>
</div>

View file

@ -1,8 +0,0 @@
<div>
<ul class="breadcrumb">
<li><a href="/artists">Artist Directory</a> <span class="divider">/</span></li>
<li class="active">{{artist.name}}</li>
</ul>
<h1>{{artist.name}}</h1>
</div>

View file

@ -5,26 +5,7 @@
<a href="#"><i class="icon-music"></i> see more</a>
The Newest Tunes
</h1>
<ul class="tracks-listing stretch-to-bottom">
<li ng-repeat="track in recentTracks">
<div class="image">
<a href="#" class="play-button"><i class="icon-play"></i></a>
<img ng-src="{{track.covers.thumbnail}}" />
</div>
<div class="icons">
<span><i ng-class="{'icon-microphone-off': !track.is_vocal, 'icon-microphone': track.is_vocal}"></i></span>
<a href="#"><i class="icon-star-empty"></i></a>
</div>
<a class="info" href="{{track.url}}">
<span class="title">{{track.title}}</span>
<span class="metadata">
by: <span class="artist">{{track.user.name}}</span> /
<span class="genre">{{track.genre.name}}</span> /
{{track.published_at.date | momentFromNow}}
</span>
</a>
</li>
</ul>
<pfm-tracks-list tracks="recentTracks" />
</div>
</section>
<section class="popular">
@ -33,26 +14,7 @@
<a href="#"><i class="icon-star"></i> see more</a>
What's Popular Today
</h1>
<ul class="tracks-listing stretch-to-bottom">
<li ng-repeat="track in recentTracks">
<div class="image">
<a href="#" class="play-button"><i class="icon-play"></i></a>
<img ng-src="{{track.covers.thumbnail}}" />
</div>
<div class="icons">
<span><i ng-class="{'icon-microphone-off': !track.is_vocal, 'icon-microphone': track.is_vocal}"></i></span>
<a href="#"><i class="icon-star-empty"></i></a>
</div>
<a class="info" href="{{track.url}}">
<span class="title">{{track.title}}</span>
<span class="metadata">
by: <span class="artist">{{track.user.name}}</span> /
<span class="genre">{{track.genre.name}}</span> /
{{track.published_at.date | momentFromNow}}
</span>
</a>
</li>
</ul>
<pfm-tracks-list tracks="recentTracks" />
</div>
</section>
</div>

View file

@ -0,0 +1,14 @@
<ul class="albums-listing {{class}}">
<li ng-repeat="album in albums">
<a href="{{album.url}}">
<img class="image" ng-src="{{album.covers.normal}}" />
<span class="title">{{album.title}}</span>
<span class="published">
by {{album.user.name}}
</span>
</a>
</li>
<li ng-show="!albums.length" class="empty">
No albums found...
</li>
</ul>

View file

@ -0,0 +1,20 @@
<ul class="tracks-listing {{class}}">
<li ng-repeat="track in tracks">
<div class="image">
<a href="#" class="play-button"><i class="icon-play"></i></a>
<img ng-src="{{track.covers.thumbnail}}" />
</div>
<div class="icons">
<span><i ng-class="{'icon-microphone-off': !track.is_vocal, 'icon-microphone': track.is_vocal}"></i></span>
<a href="#"><i class="icon-star-empty"></i></a>
</div>
<a class="info" href="{{track.url}}">
<span class="title">{{track.title}}</span>
<span class="metadata">
<span class="artist">by: {{track.user.name}} /</span>
<span class="genre">{{track.genre.name}}</span> /
{{track.published_at.date | momentFromNow}}
</span>
</a>
</li>
</ul>

View file

@ -1,20 +1,3 @@
<ul class="tracks-listing two-column stretch-to-bottom">
<li ng-repeat="track in tracks">
<div class="image">
<a href="#" class="play-button"><i class="icon-play"></i></a>
<img ng-src="{{track.covers.thumbnail}}" />
<div class="stretch-to-bottom">
<pfm-tracks-list tracks="tracks" class="two-column" />
</div>
<div class="icons">
<span><i ng-class="{'icon-microphone-off': !track.is_vocal, 'icon-microphone': track.is_vocal}"></i></span>
<a href="#"><i class="icon-star-empty"></i></a>
</div>
<a class="info" href="{{track.url}}">
<span class="title">{{track.title}}</span>
<span class="metadata">
by: <span class="artist">{{track.user.name}}</span> /
<span class="genre">{{track.genre.name}}</span> /
{{track.published_at.date | momentFromNow}}
</span>
</a>
</li>
</ul>