From 1dff7cb36f91c0a34a2216fb0bd4db8dab373187 Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Wed, 28 Aug 2013 22:19:24 -0500 Subject: [PATCH] Mega commit... Following, design changes, share/embed code and more. --- app/controllers/Api/Web/AlbumsController.php | 16 +++- app/controllers/Api/Web/ArtistsController.php | 29 ++++-- .../Api/Web/DashboardController.php | 20 ++-- app/controllers/Api/Web/FollowController.php | 13 +++ .../Api/Web/PlaylistsController.php | 8 +- app/controllers/Api/Web/TracksController.php | 21 +--- .../2013_08_18_041928_create_user_tables.php | 10 +- .../2013_08_29_025516_create_followers.php | 25 +++++ .../Commands/ToggleFollowingCommand.php | 57 +++++++++++ app/models/Entities/Album.php | 9 +- app/models/Entities/Follower.php | 9 ++ app/models/Entities/Playlist.php | 9 +- app/models/Entities/Track.php | 56 ++++++++++- app/models/Entities/User.php | 23 ++++- app/routes.php | 3 +- app/views/shared/_app_layout.blade.php | 27 +++++- public/.htaccess | 2 +- public/scripts/app/controllers/album.coffee | 13 ++- public/scripts/app/controllers/albums.coffee | 1 + .../app/controllers/artist-favourites.coffee | 1 - public/scripts/app/controllers/artist.coffee | 8 +- public/scripts/app/controllers/artists.coffee | 1 + .../scripts/app/controllers/playlist.coffee | 17 +++- .../scripts/app/controllers/playlists.coffee | 1 + public/scripts/app/controllers/track.coffee | 9 ++ .../app/directives/share-buttons.coffee | 6 ++ .../scripts/app/directives/tracks-list.coffee | 1 + public/scripts/app/filters/pfm-date.js | 7 +- public/scripts/app/services/follow.coffee | 13 +++ public/styles/app.less | 3 +- public/styles/body.less | 8 ++ public/styles/components.less | 11 +++ public/styles/content.less | 95 ++++++++++++++++--- public/styles/dashboard.less | 23 +++++ public/templates/albums/show.html | 10 +- public/templates/artists/_show_layout.html | 46 ++++----- public/templates/artists/content.html | 6 +- public/templates/artists/favourites.html | 2 +- public/templates/artists/list.html | 12 ++- public/templates/artists/profile.html | 7 +- public/templates/dashboard/index.html | 29 ++++-- public/templates/directives/albums-list.html | 17 +++- public/templates/directives/comments.html | 8 +- .../templates/directives/playlists-list.html | 17 +++- .../partials/album-share-dialog.html | 13 +++ .../partials/playlist-share-dialog.html | 13 +++ .../partials/track-share-dialog.html | 19 ++++ public/templates/playlists/show.html | 11 ++- public/templates/tracks/show.html | 10 +- vendor/autoload.php | 2 +- vendor/composer/autoload_classmap.php | 7 ++ vendor/composer/autoload_real.php | 6 +- 52 files changed, 636 insertions(+), 154 deletions(-) create mode 100644 app/controllers/Api/Web/FollowController.php create mode 100644 app/database/migrations/2013_08_29_025516_create_followers.php create mode 100644 app/models/Commands/ToggleFollowingCommand.php create mode 100644 app/models/Entities/Follower.php create mode 100644 public/scripts/app/directives/share-buttons.coffee create mode 100644 public/scripts/app/services/follow.coffee create mode 100644 public/styles/dashboard.less create mode 100644 public/templates/partials/album-share-dialog.html create mode 100644 public/templates/partials/playlist-share-dialog.html create mode 100644 public/templates/partials/track-share-dialog.html diff --git a/app/controllers/Api/Web/AlbumsController.php b/app/controllers/Api/Web/AlbumsController.php index c57499bf..6545323f 100644 --- a/app/controllers/Api/Web/AlbumsController.php +++ b/app/controllers/Api/Web/AlbumsController.php @@ -28,7 +28,17 @@ } public function getShow($id) { - $album = Album::with(['tracks' => function($query) { $query->details(); }, 'tracks.cover', 'tracks.genre', 'tracks.user', 'user', 'comments' => function($query) { $query->with('user'); }])->details()->find($id); + $album = Album::with([ + 'tracks' => function($query) { $query->userDetails(); }, + 'tracks.cover', + 'tracks.genre', + 'tracks.user', + 'user', + 'comments', + 'comments.user']) + ->userDetails() + ->find($id); + if (!$album) App::abort(404); @@ -49,12 +59,12 @@ $query = Album::summary() ->with('user', 'user.avatar', 'cover') - ->details() + ->userDetails() ->orderBy('created_at', 'desc') ->where('track_count', '>', 0); $count = $query->count(); - $perPage = 18; + $perPage = 40; $query->skip(($page - 1) * $perPage)->take($perPage); $albums = []; diff --git a/app/controllers/Api/Web/ArtistsController.php b/app/controllers/Api/Web/ArtistsController.php index e4cbc773..dd3e0017 100644 --- a/app/controllers/Api/Web/ArtistsController.php +++ b/app/controllers/Api/Web/ArtistsController.php @@ -30,8 +30,8 @@ 'track.user', 'album.cover', 'album.user', - 'track' => function($query) { $query->details(); }, - 'album' => function($query) { $query->details(); }])->get(); + 'track' => function($query) { $query->userDetails(); }, + 'album' => function($query) { $query->userDetails(); }])->get(); $tracks = []; $albums = []; @@ -56,7 +56,7 @@ if (!$user) App::abort(404); - $query = Track::summary()->with('genre', 'cover', 'user')->details()->whereUserId($user->id)->whereNotNull('published_at'); + $query = Track::summary()->with('genre', 'cover', 'user')->userDetails()->whereUserId($user->id)->whereNotNull('published_at'); $tracks = []; $singles = []; @@ -83,11 +83,11 @@ } public function getShow($slug) { - $user = User::whereSlug($slug)->with(['comments' => function ($query) { $query->with('user'); }])->first(); + $user = User::whereSlug($slug)->userDetails()->with(['comments' => function ($query) { $query->with('user'); }])->first(); if (!$user) App::abort(404); - $trackQuery = Track::summary()->with('genre', 'cover', 'user')->details()->whereUserId($user->id)->whereNotNull('published_at')->orderBy('created_at', 'desc')->take(20); + $trackQuery = Track::summary()->with('genre', 'cover', 'user')->userDetails()->whereUserId($user->id)->whereNotNull('published_at')->orderBy('created_at', 'desc')->take(20); $latestTracks = []; foreach ($trackQuery->get() as $track) { @@ -99,6 +99,17 @@ $comments[] = Comment::mapPublic($comment); } + $userData = [ + 'is_following' => false + ]; + + if ($user->users->count()) { + $userRow = $user->users[0]; + $userData = [ + 'is_following' => $userRow->is_followed + ]; + } + return Response::json([ 'artist' => [ 'id' => $user->id, @@ -112,9 +123,11 @@ 'followers' => [], 'following' => [], 'latest_tracks' => $latestTracks, - 'comments' => ['count' => count($comments), 'list' => $comments], + 'comments' => $comments, 'bio' => $user->bio, - 'mlpforums_username' => $user->mlpforums_name + 'mlpforums_username' => $user->mlpforums_name, + 'message_url' => $user->message_url, + 'user_data' => $userData ] ], 200); } @@ -128,7 +141,7 @@ ->where('track_count', '>', 0); $count = $query->count(); - $perPage = 18; + $perPage = 40; $query->skip(($page - 1) * $perPage)->take($perPage); $users = []; diff --git a/app/controllers/Api/Web/DashboardController.php b/app/controllers/Api/Web/DashboardController.php index 4a687794..4a9936e4 100644 --- a/app/controllers/Api/Web/DashboardController.php +++ b/app/controllers/Api/Web/DashboardController.php @@ -14,18 +14,22 @@ class DashboardController extends \ApiControllerBase { public function getIndex() { - $query = Track::summary()->with(['genre', 'user', 'cover'])->details()->whereNotNull('published_at')->orderBy('published_at', 'desc')->take(30); - if (!Auth::check() || !Auth::user()->can_see_explicit_content) - $query->whereIsExplicit(false); + $recentQuery = Track::summary() + ->with(['genre', 'user', 'cover', 'user.avatar']) + ->userDetails() + ->explicitFilter() + ->published() + ->orderBy('published_at', 'desc') + ->take(30); - $tracks = []; + $recentTracks = []; - foreach ($query->get() as $track) { - $tracks[] = Track::mapPublicTrackSummary($track); + foreach ($recentQuery->get() as $track) { + $recentTracks[] = Track::mapPublicTrackSummary($track); } return Response::json([ - 'recent_tracks' => $tracks, - 'popular_tracks' => $tracks], 200); + 'recent_tracks' => $recentTracks, + 'popular_tracks' => Track::popular(30, Auth::check() && Auth::user()->can_see_explicit_content)], 200); } } \ No newline at end of file diff --git a/app/controllers/Api/Web/FollowController.php b/app/controllers/Api/Web/FollowController.php new file mode 100644 index 00000000..3f859f72 --- /dev/null +++ b/app/controllers/Api/Web/FollowController.php @@ -0,0 +1,13 @@ +execute(new ToggleFollowingCommand(Input::get('type'), Input::get('id'))); + } + } \ No newline at end of file diff --git a/app/controllers/Api/Web/PlaylistsController.php b/app/controllers/Api/Web/PlaylistsController.php index dd951f69..99c24034 100644 --- a/app/controllers/Api/Web/PlaylistsController.php +++ b/app/controllers/Api/Web/PlaylistsController.php @@ -40,13 +40,13 @@ $query = Playlist::summary() ->with('user', 'user.avatar', 'tracks', 'tracks.cover') - ->details() + ->userDetails() ->orderBy('created_at', 'desc') ->where('track_count', '>', 0) ->whereIsPublic(true); $count = $query->count(); - $perPage = 18; + $perPage = 40; $query->skip(($page - 1) * $perPage)->take($perPage); $playlists = []; @@ -59,7 +59,7 @@ } public function getShow($id) { - $playlist = Playlist::with(['tracks.user', 'tracks.genre', 'tracks.cover', 'tracks.album', 'tracks' => function($query) { $query->details(); }, 'comments', 'comments.user'])->details()->find($id); + $playlist = Playlist::with(['tracks.user', 'tracks.genre', 'tracks.cover', 'tracks.album', 'tracks' => function($query) { $query->userDetails(); }, 'comments', 'comments.user'])->userDetails()->find($id); if (!$playlist || !$playlist->canView(Auth::user())) App::abort('404'); @@ -73,7 +73,7 @@ public function getPinned() { $query = Playlist - ::details() + ::userDetails() ->with('tracks', 'tracks.cover', 'tracks.user', 'user') ->join('pinned_playlists', function($join) { $join->on('playlist_id', '=', 'playlists.id'); diff --git a/app/controllers/Api/Web/TracksController.php b/app/controllers/Api/Web/TracksController.php index 68e03084..d1c09f34 100644 --- a/app/controllers/Api/Web/TracksController.php +++ b/app/controllers/Api/Web/TracksController.php @@ -31,7 +31,7 @@ } public function getShow($id) { - $track = Track::details()->withComments()->find($id); + $track = Track::userDetails()->withComments()->find($id); if (!$track || !$track->canView(Auth::user())) return $this->notFound('Track not found!'); @@ -43,20 +43,6 @@ return Response::json(['track' => Track::mapPublicTrackShow($track)], 200); } - public function getRecent() { - $query = Track::summary()->details()->with(['genre', 'user', 'cover'])->whereNotNull('published_at')->orderBy('published_at', 'desc')->take(30); - if (!Auth::check() || !Auth::user()->can_see_explicit_content) - $query->whereIsExplicit(false); - - $tracks = []; - - foreach ($query->get() as $track) { - $tracks[] = Track::mapPublicTrackSummary($track); - } - - return Response::json($tracks, 200); - } - public function getIndex() { $page = 1; $perPage = 45; @@ -65,8 +51,9 @@ $page = Input::get('page'); $query = Track::summary() - ->details() - ->whereNotNull('published_at') + ->userDetails() + ->explicitFilter() + ->published() ->with('user', 'genre', 'cover', 'album', 'album.user'); $this->applyFilters($query); diff --git a/app/database/migrations/2013_08_18_041928_create_user_tables.php b/app/database/migrations/2013_08_18_041928_create_user_tables.php index e258497e..c6c1d9c9 100644 --- a/app/database/migrations/2013_08_18_041928_create_user_tables.php +++ b/app/database/migrations/2013_08_18_041928_create_user_tables.php @@ -11,6 +11,7 @@ class CreateUserTables extends Migration { $table->integer('track_id')->unsigned()->nullable()->index(); $table->integer('album_id')->unsigned()->nullable()->index(); $table->integer('playlist_id')->unsigned()->nullable()->index(); + $table->integer('artist_id')->unsigned()->nullable()->index(); $table->boolean('is_followed'); $table->boolean('is_favourited'); @@ -20,12 +21,13 @@ class CreateUserTables extends Migration { $table->integer('play_count'); $table->integer('download_count'); + $table->foreign('artist_id')->references('id')->on('users')->on_delete('cascade'); $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); - $table->foreign('track_id')->references('id')->on('tracks'); - $table->foreign('album_id')->references('id')->on('albums'); - $table->foreign('playlist_id')->references('id')->on('playlists'); + $table->foreign('track_id')->references('id')->on('tracks')->on_delete('cascade');; + $table->foreign('album_id')->references('id')->on('albums')->on_delete('cascade');; + $table->foreign('playlist_id')->references('id')->on('playlists')->on_delete('cascade');; - $table->unique(['user_id', 'track_id', 'album_id', 'playlist_id']); + $table->unique(['user_id', 'track_id', 'album_id', 'playlist_id', 'artist_id']); }); Schema::create('resource_log_items', function($table){ diff --git a/app/database/migrations/2013_08_29_025516_create_followers.php b/app/database/migrations/2013_08_29_025516_create_followers.php new file mode 100644 index 00000000..d9604534 --- /dev/null +++ b/app/database/migrations/2013_08_29_025516_create_followers.php @@ -0,0 +1,25 @@ +increments('id'); + $table->integer('user_id')->unsigned()->index(); + + $table->integer('artist_id')->unsigned()->nullable()->index(); + $table->integer('playlist_id')->unsigned()->nullable()->index(); + + $table->timestamp('created_at'); + + $table->foreign('user_id')->references('id')->on('users')->on_delete('cascade'); + $table->foreign('artist_id')->references('id')->on('users')->on_delete('cascade'); + $table->foreign('playlist_id')->references('id')->on('playlists'); + }); + } + + public function down() { + Schema::drop('followers'); + } +} \ No newline at end of file diff --git a/app/models/Commands/ToggleFollowingCommand.php b/app/models/Commands/ToggleFollowingCommand.php new file mode 100644 index 00000000..b8273e90 --- /dev/null +++ b/app/models/Commands/ToggleFollowingCommand.php @@ -0,0 +1,57 @@ +_resourceId = $resourceId; + $this->_resourceType = $resourceType; + } + + /** + * @return bool + */ + public function authorize() { + $user = Auth::user(); + return $user != null; + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() { + $typeId = $this->_resourceType . '_id'; + $existing = Follower::where($typeId, '=', $this->_resourceId)->whereUserId(Auth::user()->id)->first(); + $isFollowed = false; + + if ($existing) { + $existing->delete(); + } else { + $follow = new Follower(); + $follow->$typeId = $this->_resourceId; + $follow->user_id = Auth::user()->id; + $follow->created_at = time(); + $follow->save(); + $isFollowed = true; + } + + $resourceUser = ResourceUser::get(Auth::user()->id, $this->_resourceType, $this->_resourceId); + $resourceUser->is_followed = $isFollowed; + $resourceUser->save(); + + return CommandResponse::succeed(['is_followed' => $isFollowed]); + } + } \ No newline at end of file diff --git a/app/models/Entities/Album.php b/app/models/Entities/Album.php index 367ba119..0bc03100 100644 --- a/app/models/Entities/Album.php +++ b/app/models/Entities/Album.php @@ -19,7 +19,7 @@ return self::select('id', 'title', 'user_id', 'slug', 'created_at', 'cover_id', 'comment_count', 'download_count', 'view_count', 'favourite_count'); } - public function scopeDetails($query) { + public function scopeUserDetails($query) { if (Auth::check()) { $query->with(['users' => function($query) { $query->whereUserId(Auth::user()->id); @@ -52,7 +52,7 @@ } public function comments(){ - return $this->hasMany('Entities\Comment'); + return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc'); } public static function mapPublicAlbumShow($album) { @@ -81,6 +81,11 @@ $data['comments'] = $comments; $data['formats'] = $formats; $data['description'] = $album->description; + $data['share'] = [ + 'url' => URL::to('/a' . $album->id), + 'tumblrUrl' => 'http://www.tumblr.com/share/link?url=' . urlencode($album->url) . '&name=' . urlencode($album->title) . '&description=' . urlencode($album->description), + 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $album->title . ' by ' . $album->user->display_name . ' on Pony.fm' + ]; return $data; } diff --git a/app/models/Entities/Follower.php b/app/models/Entities/Follower.php new file mode 100644 index 00000000..0d95e8c4 --- /dev/null +++ b/app/models/Entities/Follower.php @@ -0,0 +1,9 @@ +with(['users' => function($query) { $query->whereUserId(Auth::user()->id); @@ -53,6 +53,11 @@ $data['tracks'] = $tracks; $data['comments'] = $comments; $data['formats'] = $formats; + $data['share'] = [ + 'url' => URL::to('/p' . $playlist->id), + 'tumblrUrl' => 'http://www.tumblr.com/share/link?url=' . urlencode($playlist->url) . '&name=' . urlencode($playlist->title) . '&description=' . urlencode($playlist->description), + 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $playlist->title . ' by ' . $playlist->user->display_name . ' on Pony.fm' + ]; return $data; } @@ -117,7 +122,7 @@ } public function comments(){ - return $this->hasMany('Entities\Comment'); + return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc'); } public function pins() { diff --git a/app/models/Entities/Track.php b/app/models/Entities/Track.php index 5aaa593c..ebb1d8e7 100644 --- a/app/models/Entities/Track.php +++ b/app/models/Entities/Track.php @@ -8,6 +8,7 @@ use Helpers; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; + use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\URL; use Illuminate\Support\Str; @@ -31,7 +32,7 @@ return self::select('id', 'title', 'user_id', 'slug', 'is_vocal', 'is_explicit', 'created_at', 'published_at', 'duration', 'is_downloadable', 'genre_id', 'track_type_id', 'cover_id', 'album_id', 'comment_count', 'download_count', 'view_count', 'play_count', 'favourite_count'); } - public function scopeDetails($query) { + public function scopeUserDetails($query) { if (Auth::check()) { $query->with(['users' => function($query) { $query->whereUserId(Auth::user()->id); @@ -41,10 +42,52 @@ return !$query; } + public function scopePublished($query) { + $query->whereNotNull('published_at'); + } + + public function scopeExplicitFilter($query) { + if (!Auth::check() || !Auth::user()->can_see_explicit_content) + $query->whereIsExplicit(false); + } + public function scopeWithComments($query) { $query->with(['comments' => function($query) { $query->with('user'); }]); } + public static function popular($count, $allowExplicit = false) { + $tracks = Cache::remember('popular_tracks-' . ($allowExplicit ? 'explicit' : 'safe'), 5, function() use ($allowExplicit) { + $query = static + ::with(['user', 'genre', 'cover', 'user.avatar']) + ->published() + ->whereIsExplicit($allowExplicit) + ->join(DB::raw(' + ( SELECT `track_id`, `created_at` + FROM `resource_log_items` + WHERE `created_at` > now() - INTERVAL 1 DAY + ) AS ranged_plays'), + 'tracks.id', '=', 'ranged_plays.track_id') + ->groupBy('id') + ->orderBy('plays', 'desc') + ->take(20); + return $query->get(['*', DB::raw('count(*) as plays')]); + }); + + $results = []; + $i = 0; + + foreach($tracks as $track) { + if ($i < $count) { + $results[] = self::mapPublicTrackSummary($track); + $i++; + } else { + break; + } + } + + return $results; + } + public static function mapPublicTrackShow($track) { $returnValue = self::mapPublicTrackSummary($track); $returnValue['description'] = $track->description; @@ -76,6 +119,15 @@ ]; } + $returnValue['share'] = [ + 'url' => URL::to('/t' . $track->id), + 'html' => '', + 'bbcode' => '[url=' . $track->url . '][img]' . $track->getCoverUrl() . '[/img][/url]', + 'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text=' . $track->title . ' by ' . $track->user->display_name . ' on Pony.fm' + ]; + + $returnValue['share']['tumblrUrl'] = 'http://www.tumblr.com/share/video?embed=' . urlencode($returnValue['share']['html']) . '&caption=' . urlencode($track->title); + $returnValue['formats'] = $formats; return $returnValue; @@ -191,7 +243,7 @@ } public function comments(){ - return $this->hasMany('Entities\Comment'); + return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc'); } public function favourites() { diff --git a/app/models/Entities/User.php b/app/models/Entities/User.php index 47570850..7cdfcb75 100644 --- a/app/models/Entities/User.php +++ b/app/models/Entities/User.php @@ -6,6 +6,7 @@ use Gravatar; use Illuminate\Auth\UserInterface; use Illuminate\Auth\Reminders\RemindableInterface; + use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\URL; use Illuminate\Support\Str; use Ratchet\Wamp\Exception; @@ -14,18 +15,36 @@ protected $table = 'users'; protected $hidden = ['password_hash', 'password_salt', 'bio']; + public function scopeUserDetails($query) { + if (Auth::check()) { + $query->with(['users' => function($query) { + $query->whereUserId(Auth::user()->id); + }]); + } + + return !$query; + } + public function avatar() { return $this->belongsTo('Entities\Image'); } - public function comments(){ - return $this->hasMany('Entities\Comment', 'profile_id'); + public function users() { + return $this->hasMany('Entities\ResourceUser', 'artist_id'); + } + + public function comments() { + return $this->hasMany('Entities\Comment', 'profile_id')->orderBy('created_at', 'desc'); } public function getUrlAttribute() { return URL::to('/' . $this->slug); } + public function getMessageUrlAttribute() { + return 'http://mlpforums.com/index.php?app=members&module=messaging§ion=send&do=form&fromMemberID='.$this->id; + } + public function getAuthIdentifier() { return $this->getKey(); } diff --git a/app/routes.php b/app/routes.php index 4de756e1..cca99e9f 100644 --- a/app/routes.php +++ b/app/routes.php @@ -52,7 +52,6 @@ Route::get('/playlists/show/{id}', 'Api\Web\PlaylistsController@getShow'); - Route::get('/tracks/recent', 'Api\Web\TracksController@getRecent'); Route::get('/tracks', 'Api\Web\TracksController@getIndex'); Route::get('/tracks/{id}', 'Api\Web\TracksController@getShow')->where('id', '\d+'); @@ -90,6 +89,8 @@ Route::post('/account/settings/save', 'Api\Web\AccountController@postSave'); Route::post('/favourites/toggle', 'Api\Web\FavouritesController@postToggle'); + + Route::post('/follow/toggle', 'Api\Web\FollowController@postToggle'); }); Route::group(['before' => 'auth'], function() { diff --git a/app/views/shared/_app_layout.blade.php b/app/views/shared/_app_layout.blade.php index 2cebb864..87879362 100644 --- a/app/views/shared/_app_layout.blade.php +++ b/app/views/shared/_app_layout.blade.php @@ -1,6 +1,28 @@ @extends('shared._layout') @section('content') + +
+ + +
Pony.fm
@@ -51,7 +73,7 @@
- + @endsection @@ -76,4 +98,7 @@ {{ Assets::scriptIncludes() }} + + + @endsection \ No newline at end of file diff --git a/public/.htaccess b/public/.htaccess index aaada2f0..3cd76108 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -10,4 +10,4 @@ XSendFile On - + \ No newline at end of file diff --git a/public/scripts/app/controllers/album.coffee b/public/scripts/app/controllers/album.coffee index ab4dbe1d..032cffcd 100644 --- a/public/scripts/app/controllers/album.coffee +++ b/public/scripts/app/controllers/album.coffee @@ -5,13 +5,22 @@ window.pfm.preloaders['album'] = [ ] angular.module('ponyfm').controller "album", [ - '$scope', 'albums', '$state', 'playlists', 'auth' - ($scope, albums, $state, playlists, auth) -> + '$scope', 'albums', '$state', 'playlists', 'auth', '$dialog' + ($scope, albums, $state, playlists, auth, $dialog) -> + album = null + albums.fetch($state.params.id).done (albumResponse) -> $scope.album = albumResponse.album + album = albumResponse.album $scope.playlists = [] + $scope.share = () -> + dialog = $dialog.dialog + templateUrl: '/templates/partials/album-share-dialog.html', + controller: ['$scope', ($scope) -> $scope.album = album; $scope.close = () -> dialog.close()] + dialog.open() + if auth.data.isLogged playlists.refreshOwned().done (lists) -> $scope.playlists.push list for list in lists diff --git a/public/scripts/app/controllers/albums.coffee b/public/scripts/app/controllers/albums.coffee index 34ff0546..9c4c5507 100644 --- a/public/scripts/app/controllers/albums.coffee +++ b/public/scripts/app/controllers/albums.coffee @@ -17,5 +17,6 @@ angular.module('ponyfm').controller "albums", [ $scope.$on 'albums-feteched', (e, list) -> refreshPages(list) $scope.gotoPage = (page) -> + return if !page $state.transitionTo 'content.albums.list', {page: page} ] \ No newline at end of file diff --git a/public/scripts/app/controllers/artist-favourites.coffee b/public/scripts/app/controllers/artist-favourites.coffee index 9e86b72b..c8a28768 100644 --- a/public/scripts/app/controllers/artist-favourites.coffee +++ b/public/scripts/app/controllers/artist-favourites.coffee @@ -9,5 +9,4 @@ angular.module('ponyfm').controller "artist-favourites", [ ($scope, artists, $state) -> artists.fetchFavourites($state.params.slug).done (artistResponse) -> $scope.favourites = artistResponse - console.log artistResponse ] \ No newline at end of file diff --git a/public/scripts/app/controllers/artist.coffee b/public/scripts/app/controllers/artist.coffee index 08f84b4f..c69f644c 100644 --- a/public/scripts/app/controllers/artist.coffee +++ b/public/scripts/app/controllers/artist.coffee @@ -5,8 +5,12 @@ window.pfm.preloaders['artist'] = [ ] angular.module('ponyfm').controller "artist", [ - '$scope', 'artists', '$state' - ($scope, artists, $state) -> + '$scope', 'artists', '$state', 'follow' + ($scope, artists, $state, follow) -> artists.fetch($state.params.slug).done (artistResponse) -> $scope.artist = artistResponse.artist + + $scope.toggleFollow = () -> + follow.toggle('artist', $scope.artist.id).then (res) -> + $scope.artist.user_data.is_following = res.is_followed ] \ No newline at end of file diff --git a/public/scripts/app/controllers/artists.coffee b/public/scripts/app/controllers/artists.coffee index 46536363..18f0e7e3 100644 --- a/public/scripts/app/controllers/artists.coffee +++ b/public/scripts/app/controllers/artists.coffee @@ -17,5 +17,6 @@ angular.module('ponyfm').controller "artists", [ $scope.$on 'artists-feteched', (e, list) -> refreshPages(list) $scope.gotoPage = (page) -> + return if !page $state.transitionTo 'content.artists.list', {page: page} ] \ No newline at end of file diff --git a/public/scripts/app/controllers/playlist.coffee b/public/scripts/app/controllers/playlist.coffee index f13a7bff..425ff2f0 100644 --- a/public/scripts/app/controllers/playlist.coffee +++ b/public/scripts/app/controllers/playlist.coffee @@ -5,8 +5,17 @@ window.pfm.preloaders['playlist'] = [ ] angular.module('ponyfm').controller 'playlist', [ - '$scope', '$state', 'playlists' - ($scope, $state, playlists) -> - playlists.fetch($state.params.id).done (playlist) -> - $scope.playlist = playlist + '$scope', '$state', 'playlists', '$dialog' + ($scope, $state, playlists, $dialog) -> + playlist = null + + playlists.fetch($state.params.id).done (playlistResponse) -> + $scope.playlist = playlistResponse + playlist = playlistResponse + + $scope.share = () -> + dialog = $dialog.dialog + templateUrl: '/templates/partials/playlist-share-dialog.html', + controller: ['$scope', ($scope) -> $scope.playlist = playlist; $scope.close = () -> dialog.close()] + dialog.open() ] \ No newline at end of file diff --git a/public/scripts/app/controllers/playlists.coffee b/public/scripts/app/controllers/playlists.coffee index 58983d83..622c3748 100644 --- a/public/scripts/app/controllers/playlists.coffee +++ b/public/scripts/app/controllers/playlists.coffee @@ -17,5 +17,6 @@ angular.module('ponyfm').controller "playlists", [ $scope.$on 'playlists-feteched', (e, list) -> refreshPages(list) $scope.gotoPage = (page) -> + return if !page $state.transitionTo 'content.playlists.list', {page: page} ] \ No newline at end of file diff --git a/public/scripts/app/controllers/track.coffee b/public/scripts/app/controllers/track.coffee index 09410d9e..339e41db 100644 --- a/public/scripts/app/controllers/track.coffee +++ b/public/scripts/app/controllers/track.coffee @@ -7,8 +7,11 @@ window.pfm.preloaders['track'] = [ angular.module('ponyfm').controller "track", [ '$scope', 'tracks', '$state', 'playlists', 'auth', 'favourites', '$dialog' ($scope, tracks, $state, playlists, auth, favourites, $dialog) -> + track = null + tracks.fetch($state.params.id).done (trackResponse) -> $scope.track = trackResponse.track + track = trackResponse.track $scope.playlists = [] @@ -24,6 +27,12 @@ angular.module('ponyfm').controller "track", [ track.is_favourited = res.is_favourited $scope.favouriteWorking = false + $scope.share = () -> + dialog = $dialog.dialog + templateUrl: '/templates/partials/track-share-dialog.html', + controller: ['$scope', ($scope) -> $scope.track = track; $scope.close = () -> dialog.close()] + dialog.open() + $scope.addToNewPlaylist = () -> dialog = $dialog.dialog templateUrl: '/templates/partials/playlist-dialog.html' diff --git a/public/scripts/app/directives/share-buttons.coffee b/public/scripts/app/directives/share-buttons.coffee new file mode 100644 index 00000000..43958f07 --- /dev/null +++ b/public/scripts/app/directives/share-buttons.coffee @@ -0,0 +1,6 @@ +angular.module('ponyfm').directive 'pfmShareButtons', () -> + (scope, element) -> + window.setTimeout((-> + Tumblr.activate_share_on_tumblr_buttons() + FB.XFBML.parse() + ), 0) \ No newline at end of file diff --git a/public/scripts/app/directives/tracks-list.coffee b/public/scripts/app/directives/tracks-list.coffee index cc1f2a65..b30fc7c6 100644 --- a/public/scripts/app/directives/tracks-list.coffee +++ b/public/scripts/app/directives/tracks-list.coffee @@ -1,6 +1,7 @@ angular.module('ponyfm').directive 'pfmTracksList', () -> restrict: 'E' templateUrl: '/templates/directives/tracks-list.html' + replace: true scope: tracks: '=tracks', class: '@class' diff --git a/public/scripts/app/filters/pfm-date.js b/public/scripts/app/filters/pfm-date.js index cbb640a2..f0f4f637 100644 --- a/public/scripts/app/filters/pfm-date.js +++ b/public/scripts/app/filters/pfm-date.js @@ -14,7 +14,7 @@ angular.module('ponyfm').filter('pfmdate', [ if (!value) return false; - return value.toString() == '[object Date]'; + return Object.prototype.toString.apply(value) == '[object Date]'; } function padNumber(num, digits, trim) { @@ -81,6 +81,8 @@ angular.module('ponyfm').filter('pfmdate', [ return obj; } + var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;}; + var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/, NUMBER_STRING = /^\d+$/; @@ -190,8 +192,9 @@ angular.module('ponyfm').filter('pfmdate', [ date = new Date(date); } - if (typeof(date) == 'object' && date.date) + if (typeof(date) == 'object' && date.date) { date = new Date(date.date); + } if (!isDate(date)) { return date; diff --git a/public/scripts/app/services/follow.coffee b/public/scripts/app/services/follow.coffee new file mode 100644 index 00000000..f91b16eb --- /dev/null +++ b/public/scripts/app/services/follow.coffee @@ -0,0 +1,13 @@ +angular.module('ponyfm').factory('follow', [ + '$rootScope', '$http' + ($rootScope, $http) -> + self = + toggle: (type, id) -> + def = new $.Deferred() + $http.post('/api/web/follow/toggle', {type: type, id: id, _token: pfm.token}).success (res) -> + def.resolve res + + def.promise() + + self +]) \ No newline at end of file diff --git a/public/styles/app.less b/public/styles/app.less index 8e0a1040..0ac317bf 100644 --- a/public/styles/app.less +++ b/public/styles/app.less @@ -11,4 +11,5 @@ @import 'animations'; @import 'body'; @import 'player'; -@import 'content'; \ No newline at end of file +@import 'content'; +@import 'dashboard'; \ No newline at end of file diff --git a/public/styles/body.less b/public/styles/body.less index 0c8ae791..266a64ab 100644 --- a/public/styles/body.less +++ b/public/styles/body.less @@ -1,6 +1,14 @@ @import-once 'variables'; @import-once 'base/bootstrap/bootstrap'; +a { + color: #C2889C; + + &:hover { + text-decoration: none; + } +} + .site-content{ .box-sizing(border-box); padding: 10px; diff --git a/public/styles/components.less b/public/styles/components.less index a7422fb1..f7a263b1 100644 --- a/public/styles/components.less +++ b/public/styles/components.less @@ -327,6 +327,17 @@ html { .border-radius(0px); border: 2px solid @pfm-purple; + + h2 { + font-size: 12pt; + color: #C2889C; + line-height: normal; + margin-bottom: 5px; + + small { + font-size: 10pt; + } + } } .breadcrumb { diff --git a/public/styles/content.less b/public/styles/content.less index bae1c800..a80e73be 100644 --- a/public/styles/content.less +++ b/public/styles/content.less @@ -6,23 +6,41 @@ margin: 0px; padding: 0px; list-style: none; + overflow: hidden; + + &.two-columns { + li { + width: 50%; + } + } li { .box-sizing(border-box); float: left; - width: 16.6666%; + width: 25%; padding: 5px; line-height: normal; a { - background: #ddd; + background: #eee; display: block; + overflow: hidden; + position: relative; img { display: block; + float: left; + width: 67px; + height: 67px; + background: #ddd; } - .title, .published { + .info { + margin-left: 72px; + display: block; + } + + .title, .published, .stats { display: block; color: #444; padding: 5px; @@ -32,17 +50,35 @@ .ellipsis(); font-weight: bold; - font-size: 12pt; + font-size: 11pt; + padding-left: 3px; padding-bottom: 0px; } .published { - color: #777; + font-size: 8pt; + color: #555; + } + + .published, .stats { + padding-top: 0px; + } + + .stats { font-size: 10pt; + color: #777; + position: absolute; + bottom: 3px; + right: 3px; + + strong { + font-weight: normal; + } } &:hover { text-decoration: none; + background: #ddd; } } } @@ -57,6 +93,34 @@ } } + &.artist-details { + > header { + .tabs { + clear: left; + margin: 0px; + margin-top: 5px; + border: none; + font-size: 9pt; + + li.active { + a { + border: none; + background: #C1889E; + color: #fff; + } + } + } + } + } + + .share-buttons { + margin-top: 5px; + + .facebook, .twitter { + margin-top: 3px; + } + } + > header { padding: 5px; background: #eee; @@ -174,15 +238,8 @@ html .single-player .play-button { } } -.tracks-listing { - margin: 0px; - padding: 0px; - list-style: none; - +html { li { - .box-sizing(border-box); - overflow: hidden; - &.empty { .border-radius(0px); background: lighten(@pfm-purple, 30%); @@ -199,6 +256,18 @@ html .single-player .play-button { background-color: lighten(@pfm-purple, 30%); } } + } +} + +.tracks-listing { + margin: 0px; + padding: 0px; + list-style: none; + overflow: hidden; + + li { + .box-sizing(border-box); + overflow: hidden; line-height: normal; padding: 0px; diff --git a/public/styles/dashboard.less b/public/styles/dashboard.less new file mode 100644 index 00000000..6d47c386 --- /dev/null +++ b/public/styles/dashboard.less @@ -0,0 +1,23 @@ +@import-once "base/bootstrap/bootstrap"; + +.recent-tracks { + h1 { + a { + display: block; + float: right; + font-size: 10pt; + + margin-top: 8px; + } + } +} + +.dashboard { + section { + .box-sizing(border-box); + + float: left; + width: 50%; + padding: 5px; + } +} \ No newline at end of file diff --git a/public/templates/albums/show.html b/public/templates/albums/show.html index e82656a3..22a0800c 100644 --- a/public/templates/albums/show.html +++ b/public/templates/albums/show.html @@ -8,7 +8,7 @@
  • -
  • Share or Embed
  • +
  • Share or Embed
  • @@ -23,8 +23,14 @@
    + +
    diff --git a/public/templates/artists/content.html b/public/templates/artists/content.html index de0ce23a..5813bb2c 100644 --- a/public/templates/artists/content.html +++ b/public/templates/artists/content.html @@ -1,14 +1,14 @@

    Albums

    - +

    Singles

    - +

    Part of an Album

    - +
    \ No newline at end of file diff --git a/public/templates/artists/favourites.html b/public/templates/artists/favourites.html index 5ee54177..79a4da17 100644 --- a/public/templates/artists/favourites.html +++ b/public/templates/artists/favourites.html @@ -5,6 +5,6 @@

    Albums

    - +
    \ No newline at end of file diff --git a/public/templates/artists/list.html b/public/templates/artists/list.html index 43c54465..586bb5f5 100644 --- a/public/templates/artists/list.html +++ b/public/templates/artists/list.html @@ -1,10 +1,12 @@