Design work

This commit is contained in:
nelsonlaquet 2013-08-27 01:53:37 -05:00
parent 4c025dd1e9
commit 04787e9f07
25 changed files with 292 additions and 97 deletions

View file

@ -54,7 +54,7 @@
->where('track_count', '>', 0); ->where('track_count', '>', 0);
$count = $query->count(); $count = $query->count();
$perPage = 15; $perPage = 18;
$query->skip(($page - 1) * $perPage)->take($perPage); $query->skip(($page - 1) * $perPage)->take($perPage);
$albums = []; $albums = [];

View file

@ -128,7 +128,7 @@
->where('track_count', '>', 0); ->where('track_count', '>', 0);
$count = $query->count(); $count = $query->count();
$perPage = 15; $perPage = 18;
$query->skip(($page - 1) * $perPage)->take($perPage); $query->skip(($page - 1) * $perPage)->take($perPage);
$users = []; $users = [];

View file

@ -33,6 +33,31 @@
return $this->execute(new AddTrackToPlaylistCommand($id, Input::get('track_id'))); return $this->execute(new AddTrackToPlaylistCommand($id, Input::get('track_id')));
} }
public function getIndex() {
$page = 1;
if (Input::has('page'))
$page = Input::get('page');
$query = Playlist::summary()
->with('user', 'user.avatar', 'tracks', 'tracks.cover')
->details()
->orderBy('created_at', 'desc')
->where('track_count', '>', 0)
->whereIsPublic(true);
$count = $query->count();
$perPage = 18;
$query->skip(($page - 1) * $perPage)->take($perPage);
$playlists = [];
foreach ($query->get() as $playlist) {
$playlists[] = Playlist::mapPublicPlaylistSummary($playlist);
}
return Response::json(["playlists" => $playlists, "current_page" => $page, "total_pages" => ceil($count / $perPage)], 200);
}
public function getShow($id) { 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->details(); }, 'comments', 'comments.user'])->details()->find($id);
if (!$playlist || !$playlist->canView(Auth::user())) if (!$playlist || !$playlist->canView(Auth::user()))

View file

@ -78,8 +78,9 @@
$data = self::mapPublicAlbumSummary($album); $data = self::mapPublicAlbumSummary($album);
$data['tracks'] = $tracks; $data['tracks'] = $tracks;
$data['comments'] = ['count' => count($comments), 'list' => $comments]; $data['comments'] = $comments;
$data['formats'] = $formats; $data['formats'] = $formats;
$data['description'] = $album->description;
return $data; return $data;
} }

View file

@ -59,6 +59,7 @@
Route::get('/albums', 'Api\Web\AlbumsController@getIndex'); Route::get('/albums', 'Api\Web\AlbumsController@getIndex');
Route::get('/albums/{id}', 'Api\Web\AlbumsController@getShow')->where('id', '\d+'); Route::get('/albums/{id}', 'Api\Web\AlbumsController@getShow')->where('id', '\d+');
Route::get('/playlists', 'Api\Web\PlaylistsController@getIndex');
Route::get('/playlists/{id}', 'Api\Web\PlaylistsController@getShow')->where('id', '\d+'); Route::get('/playlists/{id}', 'Api\Web\PlaylistsController@getShow')->where('id', '\d+');
Route::get('/comments/{type}/{id}', 'Api\Web\CommentsController@getIndex')->where('id', '\d+'); Route::get('/comments/{type}/{id}', 'Api\Web\CommentsController@getIndex')->where('id', '\d+');

View file

@ -110,6 +110,13 @@ module.config [
state.state 'content.playlists', state.state 'content.playlists',
url: '/playlists' url: '/playlists'
templateUrl: '/templates/playlists/index.html' templateUrl: '/templates/playlists/index.html'
controller: 'playlists'
abstract: true
state.state 'content.playlists.list',
url: '?page'
controller: 'playlists-list'
templateUrl: '/templates/playlists/list.html'
state.state 'content.playlist', state.state 'content.playlist',
url: '/playlist/{id:[^\-]+}-{slug}' url: '/playlist/{id:[^\-]+}-{slug}'

View file

@ -0,0 +1,12 @@
window.pfm.preloaders['playlists-list'] = [
'playlists', '$state'
(playlists, $state) ->
playlists.fetchList($state.params.page, true)
]
angular.module('ponyfm').controller "playlists-list", [
'$scope', 'playlists', '$state',
($scope, playlists, $state) ->
playlists.fetchList($state.params.page).done (searchResults) ->
$scope.playlists = searchResults.playlists
]

View file

@ -0,0 +1,21 @@
angular.module('ponyfm').controller "playlists", [
'$scope', 'playlists', '$state'
($scope, playlists, $state) ->
refreshPages = (list) ->
$scope.playlists = list.playlists
$scope.currentPage = parseInt(list.current_page)
$scope.totalPages = parseInt(list.total_pages)
delete $scope.nextPage
delete $scope.prevPage
$scope.nextPage = $scope.currentPage + 1 if $scope.currentPage < $scope.totalPages
$scope.prevPage = $scope.currentPage - 1 if $scope.currentPage > 1
$scope.pages = [1..$scope.totalPages]
playlists.fetchList($state.params.page).done refreshPages
$scope.$on 'playlists-feteched', (e, list) -> refreshPages(list)
$scope.gotoPage = (page) ->
$state.transitionTo 'content.playlists.list', {page: page}
]

View file

@ -1,5 +1,6 @@
angular.module('ponyfm').directive 'pfmAlbumsList', () -> angular.module('ponyfm').directive 'pfmAlbumsList', () ->
restrict: 'E' restrict: 'E'
replace: true
templateUrl: '/templates/directives/albums-list.html' templateUrl: '/templates/directives/albums-list.html'
scope: scope:
albums: '=albums', albums: '=albums',

View file

@ -0,0 +1,13 @@
angular.module('ponyfm').directive 'pfmPlaylistsList', () ->
restrict: 'E'
replace: true
templateUrl: '/templates/directives/playlists-list.html'
scope:
playlists: '=playlists',
class: '@class'
controller: [
'$scope', 'auth'
($scope, auth) ->
$scope.auth = auth.data
]

View file

@ -11,7 +11,10 @@ angular.module('ponyfm').filter('pfmdate', [
function isNumber(value){return typeof value == 'number';} function isNumber(value){return typeof value == 'number';}
function isDate(value){ function isDate(value){
return toString.apply(value) == '[object Date]'; if (!value)
return false;
return value.toString() == '[object Date]';
} }
function padNumber(num, digits, trim) { function padNumber(num, digits, trim) {

View file

@ -0,0 +1,20 @@
angular.module('ponyfm').filter 'secondsDisplay', () ->
(input) ->
sec_num = parseInt(input, 10)
return '00:00' if !sec_num
hours = Math.floor(sec_num / 3600)
minutes = Math.floor((sec_num - (hours * 3600)) / 60)
seconds = sec_num - (hours * 3600) - (minutes * 60)
if (hours < 10)
hours = "0" + hours
if (minutes < 10)
minutes = "0" + minutes
if (seconds < 10)
seconds = "0" + seconds
time = ''
time += hours + ':' if hours != "00"
time += minutes + ':' + seconds;
return time;

View file

@ -14,6 +14,7 @@ angular.module('ponyfm').factory('player', [
track.loadingProgress = (self.currentSound.bytesLoaded / self.currentSound.bytesTotal) * 100 track.loadingProgress = (self.currentSound.bytesLoaded / self.currentSound.bytesTotal) * 100
whileplaying: () -> $rootScope.safeApply -> whileplaying: () -> $rootScope.safeApply ->
track.progressSeconds = self.currentSound.position / 1000
track.progress = (self.currentSound.position / (track.duration * 1000)) * 100 track.progress = (self.currentSound.position / (track.duration * 1000)) * 100
onfinish: () -> $rootScope.safeApply -> onfinish: () -> $rootScope.safeApply ->

View file

@ -3,10 +3,22 @@ angular.module('ponyfm').factory('playlists', [
($rootScope, $state, $http) -> ($rootScope, $state, $http) ->
playlistDef = null playlistDef = null
playlists = {} playlists = {}
playlistPages = []
self = self =
pinnedPlaylists: [] pinnedPlaylists: []
fetchList: (page, force) ->
force = force || false
page = 1 if !page
return playlistPages[page] if !force && playlistPages[page]
playlistDef = new $.Deferred()
$http.get('/api/web/playlists?page=' + page).success (playlists) ->
playlistDef.resolve playlists
$rootScope.$broadcast 'playlists-feteched', playlists
playlistPages[page] = playlistDef.promise()
fetch: (id, force) -> fetch: (id, force) ->
force = force || false force = force || false
return playlists[id] if !force && playlists[id] return playlists[id] if !force && playlists[id]

View file

@ -11,4 +11,4 @@
@import 'animations'; @import 'animations';
@import 'body'; @import 'body';
@import 'player'; @import 'player';
@import 'tracks'; @import 'content';

View file

@ -2,7 +2,61 @@
@import-once 'mixins'; @import-once 'mixins';
@import-once 'variables'; @import-once 'variables';
.track-details { .albums-listing, .playlists-listing, .artist-listing {
margin: 0px;
padding: 0px;
list-style: none;
li {
.box-sizing(border-box);
float: left;
width: 16.6666%;
padding: 5px;
line-height: normal;
a {
background: #ddd;
display: block;
img {
display: block;
}
.title, .published {
display: block;
color: #444;
padding: 5px;
}
.title {
.ellipsis();
font-weight: bold;
font-size: 12pt;
padding-bottom: 0px;
}
.published {
color: #777;
font-size: 10pt;
}
&:hover {
text-decoration: none;
}
}
}
}
.resource-details {
&.track-details {
> header {
h2, h1 {
margin-left: 47px;
}
}
}
> header { > header {
padding: 5px; padding: 5px;
background: #eee; background: #eee;
@ -11,12 +65,10 @@
h1 { h1 {
margin: 0px; margin: 0px;
margin-left: 47px;
} }
h2 { h2 {
margin: 0px; margin: 0px;
margin-left: 47px;
padding: 0px; padding: 0px;
font-weight: normal; font-weight: normal;
clear: none; clear: none;
@ -103,7 +155,7 @@ html .single-player .play-button {
left: 0px; left: 0px;
width: 100%; width: 100%;
height: 100%; height: 100%;
line-height: 38px; line-height: 45px;
text-align: center; text-align: center;
font-size: 12pt; font-size: 12pt;
color: #fff; color: #fff;
@ -128,8 +180,8 @@ html .single-player .play-button {
list-style: none; list-style: none;
li { li {
.clearfix();
.box-sizing(border-box); .box-sizing(border-box);
overflow: hidden;
&.empty { &.empty {
.border-radius(0px); .border-radius(0px);

View file

@ -76,6 +76,16 @@
padding: 0px; padding: 0px;
float: right; float: right;
li.status {
font-size: 10pt;
margin-top: 12px;
margin-right: 5px;
strong {
font-weight: normal;
}
}
li { li {
line-height: normal; line-height: normal;
float: left; float: left;

View file

@ -1,57 +1,46 @@
<div class="album-details"> <div class="resource-details album-details" bindonce="album">
<ul class="breadcrumb"> <ul class="dropdowns">
<li><a href="/albums">Albums</a> <span class="divider">/</span></li> <li class="dropdown">
<li class="active">{{album.title}}</li>
</ul>
<div class="track-toolbar btn-group pull-right">
<pfm-favourite-button resource="album" type="album"></pfm-favourite-button>
<div class="dropdown">
<a href="#" class="btn btn-small btn-info dropdown-toggle"> <a href="#" class="btn btn-small btn-info dropdown-toggle">
Downloads <i class="caret"></i> Downloads
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li ng-repeat="format in album.formats"><a target="_blank" href="{{format.url}}">{{format.name}} <small>({{format.size}})</small></a></li> <li bindonce ng-repeat="format in album.formats"><a target="_blank" bo-href="format.url"><span bo-text="format.name"></span> <small bo-text="'(' + format.size + ')'"></small></a></li>
</ul>
</li>
<li><a href="#" class="btn">Share or Embed</a></li>
<li><pfm-favourite-button resource="album" type="album"></pfm-favourite-button></li>
</ul>
<header>
<h1 bo-text="album.title"></h1>
<h2>
by: <a bo-href="album.user.url" bo-text="album.user.name"></a>
</h2>
</header>
<div class="stretch-to-bottom details-columns">
<div class="right">
<img class="cover" bo-src="album.covers.normal" />
<ul class="stats">
<li>Published: <strong bo-text="album.published_at | pfmdate:'short'"></strong></li>
<li>Views: <strong bo-text="album.stats.views"></strong></li>
<li>Downloads: <strong bo-text="album.stats.downloads"></strong></li>
<li>Favourites: <strong bo-text="album.stats.favourites"></strong></li>
</ul> </ul>
</div> </div>
</div>
<h1> <div class="left">
{{album.title}} <div class="description" bo-show="album.description.length">
<span class="subtitle"> <h2>Description</h2>
by: <a href="{{album.user.url}}">{{album.user.name}}</a> <p bo-html="album.description | noHTML | newlines"></p>
</span>
</h1>
<div class="stretch-to-bottom">
<div class="row-fluid">
<div class="span8">
<div class="description">
<p ng-bind-html-unsafe="album.description | noHTML | newlines"></p>
</div>
<h2>Tracks</h2>
<pfm-tracks-list tracks="album.tracks" class="condensed no-artist"></pfm-tracks-list>
<h2>Comments</h2>
<pfm-comments type="album" resource="album"></pfm-comments>
</div> </div>
<div class="span4 cover-image">
<img ng-src="{{album.covers.normal}}" />
<div class="fb-like" data-href="{{album.url}}" data-send="false" data-layout="button_count" data-width="20" data-show-faces="false"></div> <h2>Tracks</h2>
<a href="https://twitter.com/share" class="twitter-share-button" data-url="{{album.url}}" data-text="{{album.title + ' by ' + album.user.name + ' on Pony.fm'}}" data-via="ponyfm">Tweet</a> <pfm-tracks-list tracks="album.tracks" class="condensed no-artist"></pfm-tracks-list>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
<a href="#" class="btn btn-info">Share or Embed</a> <pfm-comments type="album" resource="album"></pfm-comments>
<h2>Stats</h2>
<ul class="stats">
<li>Views: <strong>{{album.stats.views}}</strong></li>
<li>Downloads: <strong>{{album.stats.downloads}}</strong></li>
<li>Favourites: <strong>{{album.stats.favourites}}</strong></li>
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -4,7 +4,7 @@
<img class="image" ng-src="{{artist.avatars.normal}}" /> <img class="image" ng-src="{{artist.avatars.normal}}" />
<span class="title">{{artist.name}}</span> <span class="title">{{artist.name}}</span>
<span class="published"> <span class="published">
joined {{artist.created_at | momentFromNow}} joined {{artist.created_at.date | momentFromNow}}
</span> </span>
</a> </a>
</li> </li>

View file

@ -1,5 +1,9 @@
<div class="track-player" ng-show="player.isPlaying"> <div class="track-player" ng-show="player.isPlaying">
<ul class="buttons"> <ul class="buttons">
<li class="status">
<strong>{{player.currentTrack.progressSeconds | secondsDisplay}}</strong> /
<strong>{{player.currentTrack.duration | secondsDisplay}}</strong>
</li>
<li><a pfm-eat-click ng-click="playPrev()" class="previous" href="#"><i class="icon-fast-backward"></i></a></li> <li><a pfm-eat-click ng-click="playPrev()" class="previous" href="#"><i class="icon-fast-backward"></i></a></li>
<li> <li>
<a pfm-eat-click ng-click="playPause()" class="play" href="#"> <a pfm-eat-click ng-click="playPause()" class="play" href="#">

View file

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

View file

@ -0,0 +1,11 @@
<div class="pagination" ng-show="totalPages > 1">
<ul>
<li ng-class="{disabled: !prevPage}"><a href="#" ng-click="gotoPage(prevPage);" pfm-eat-click>Prev</a></li>
<li ng-repeat="page in pages" ng-class="{active: page == currentPage}">
<a href="#" ng-click="gotoPage(page);" pfm-eat-click>{{page}}</a>
</li>
<li ng-class="{disabled: !nextPage}"><a href="#" ng-click="gotoPage(nextPage);" pfm-eat-click>Next</a></li>
</ul>
</div>
<ui-view></ui-view>

View file

@ -0,0 +1,3 @@
<div class="stretch-to-bottom">
<pfm-playlists-list playlists="playlists" />
</div>

View file

@ -1,52 +1,47 @@
<div class="playlist-details"> <div class="resource-details playlist-details" bindonce="playlist">
<ul class="breadcrumb"> <ul class="dropdowns">
<li><a href="/account/playlists">Your Playlists</a> <span class="divider">/</span></li> <li class="dropdown">
<li class="active">{{playlist.title}}</li>
</ul>
<div class="track-toolbar btn-group pull-right">
<pfm-favourite-button resource="playlist" type="playlist"></pfm-favourite-button>
<div class="dropdown">
<a href="#" class="btn btn-small btn-info dropdown-toggle"> <a href="#" class="btn btn-small btn-info dropdown-toggle">
Downloads <i class="caret"></i> Downloads
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li ng-repeat="format in playlist.formats"><a target="_blank" href="{{format.url}}">{{format.name}} <small>({{format.size}})</small></a></li> <li bindonce ng-repeat="format in playlist.formats"><a target="_blank" bo-href="format.url"><span bo-text="format.name"></span> <small bo-text="'(' + format.size + ')'"></small></a></li>
</ul>
</li>
<li><a href="#" class="btn">Share or Embed</a></li>
<li><pfm-favourite-button resource="playlist" type="playlist"></pfm-favourite-button></li>
</ul>
<header>
<h1 bo-text="playlist.title"></h1>
<h2>
created by: <a bo-href="playlist.user.url" bo-text="playlist.user.name"></a>
</h2>
</header>
<div class="stretch-to-bottom details-columns">
<div class="right">
<img class="cover" bo-src="playlist.covers.normal" />
<ul class="stats">
<li>Created: <strong bo-text="playlist.created_at.date | pfmdate:'short'"></strong></li>
<li>Views: <strong bo-text="playlist.stats.views"></strong></li>
<li>Downloads: <strong bo-text="playlist.stats.downloads"></strong></li>
<li>Favourites: <strong bo-text="playlist.stats.favourites"></strong></li>
</ul> </ul>
</div> </div>
</div>
<h1> <div class="left">
{{playlist.title}} <div class="description" bo-show="playlist.description.length">
</h1> <h2>Description</h2>
<p bo-html="playlist.description | noHTML | newlines"></p>
<div class="stretch-to-bottom">
<div class="row-fluid">
<div class="span9">
<div class="description">
<p ng-bind-html-unsafe="playlist.description | noHTML | newlines"></p>
</div>
<h2>Tracks</h2>
<pfm-tracks-list tracks="playlist.tracks"></pfm-tracks-list>
<h2>Comments</h2>
<pfm-comments type="playlist" resource="playlist"></pfm-comments>
</div> </div>
<div class="span3 cover-image">
<div class="fb-like" data-href="{{playlist.url}}" data-send="false" data-layout="button_count" data-width="20" data-show-faces="false"></div>
<a href="https://twitter.com/share" class="twitter-share-button" data-url="{{playlist.url}}" data-text="{{playlist.title + ' by ' + playlist.user.name + ' on Pony.fm'}}" data-via="ponyfm">Tweet</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
<a href="#" class="btn btn-info">Share or Embed</a> <h2>Tracks</h2>
<pfm-tracks-list tracks="playlist.tracks"></pfm-tracks-list>
<h2>Stats</h2> <pfm-comments type="playlist" resource="playlist"></pfm-comments>
<ul class="stats">
<li>Views: <strong>{{playlist.stats.views}}</strong></li>
<li>Downloads: <strong>{{playlist.stats.downloads}}</strong></li>
<li>Favourites: <strong>{{playlist.stats.favourites}}</strong></li>
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,4 +1,4 @@
<div class="track-details" bindonce="track"> <div class="resource-details track-details" bindonce="track">
<ul class="dropdowns"> <ul class="dropdowns">
<li class="dropdown"> <li class="dropdown">
<a href="#" class="btn btn-small btn-info dropdown-toggle"> <a href="#" class="btn btn-small btn-info dropdown-toggle">