diff --git a/app/controllers/Api/Web/FavouritesController.php b/app/controllers/Api/Web/FavouritesController.php index de728c73..fa435cf8 100644 --- a/app/controllers/Api/Web/FavouritesController.php +++ b/app/controllers/Api/Web/FavouritesController.php @@ -3,10 +3,96 @@ namespace Api\Web; use Commands\ToggleFavouriteCommand; + use Entities\Album; + use Entities\Favourite; + use Entities\Playlist; + use Entities\Track; + use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Input; + use Illuminate\Support\Facades\Response; class FavouritesController extends \ApiControllerBase { public function postToggle() { return $this->execute(new ToggleFavouriteCommand(Input::get('type'), Input::get('id'))); } + + public function getTracks() { + $query = Favourite + ::whereUserId(Auth::user()->id) + ->whereNotNull('track_id') + ->with([ + 'track' => function($query) { + $query + ->userDetails() + ->published(); + }, + 'track.user', + 'track.genre', + 'track.cover', + 'track.album', + 'track.album.user' + ]); + + $tracks = []; + + foreach ($query->get() as $fav) { + if ($fav->track == null) // deleted track + continue; + + $tracks[] = Track::mapPublicTrackSummary($fav->track); + } + + return Response::json(["tracks" => $tracks], 200); + } + + public function getAlbums() { + $query = Favourite + ::whereUserId(Auth::user()->id) + ->whereNotNull('album_id') + ->with([ + 'album' => function($query) { + $query->userDetails(); + }, + 'album.user', + 'album.user.avatar', + 'album.cover' + ]); + + $albums = []; + + foreach ($query->get() as $fav) { + if ($fav->album == null) // deleted album + continue; + + $albums[] = Album::mapPublicAlbumSummary($fav->album); + } + + return Response::json(["albums" => $albums], 200); + } + + public function getPlaylists() { + $query = Favourite + ::whereUserId(Auth::user()->id) + ->whereNotNull('playlist_id') + ->with([ + 'playlist' => function($query) { + $query->userDetails(); + }, + 'playlist.user', + 'playlist.user.avatar', + 'playlist.tracks', + 'playlist.tracks.cover' + ]); + + $playlists = []; + + foreach ($query->get() as $fav) { + if ($fav->playlist == null) // deleted playlist + continue; + + $playlists[] = Playlist::mapPublicPlaylistSummary($fav->playlist); + } + + return Response::json(["playlists" => $playlists], 200); + } } \ No newline at end of file diff --git a/app/controllers/UploaderController.php b/app/controllers/UploaderController.php new file mode 100644 index 00000000..c748fb3a --- /dev/null +++ b/app/controllers/UploaderController.php @@ -0,0 +1,7 @@ +_input['is_vocal']) && $this->_input['is_vocal'] == 'true' ? true : false; + $isVocal = (isset($this->_input['is_vocal']) && $this->_input['is_vocal'] == 'true') ? true : false; $rules = [ 'title' => 'required|min:3|max:80', 'released_at' => 'before:today' . ($this->_input['released_at'] != "" ? '|date' : ''), - 'lyrics' => $isVocal ? 'required' : '', 'license_id' => 'required|exists:licenses,id', 'genre_id' => 'required|exists:genres,id', 'cover' => 'image|mimes:png|min_width:350|min_height:350', @@ -50,6 +49,9 @@ 'album_id' => 'exists:albums,id' ]; + if ($isVocal) + $rules['lyrics'] = 'required'; + if ($this->_input['track_type_id'] == 2) $rules['show_song_ids'] = 'required|exists:show_songs,id'; @@ -80,7 +82,7 @@ $track->album_id = $this->_input['album_id']; Album::whereId($album->id)->update([ - 'track_count' => DB::raw('SELECT COUNT(id) FROM tracks WHERE album_id = ' . $album->id) + 'track_count' => DB::raw('(SELECT COUNT(id) FROM tracks WHERE album_id = ' . $album->id . ')') ]); } } else { diff --git a/app/models/Entities/Album.php b/app/models/Entities/Album.php index 0bc03100..c9fdc09c 100644 --- a/app/models/Entities/Album.php +++ b/app/models/Entities/Album.php @@ -132,7 +132,11 @@ 'name' => $album->user->display_name, 'url' => $album->user->url, ], - 'user_data' => $userData + 'user_data' => $userData, + 'permissions' => [ + 'delete' => Auth::check() && Auth::user()->id == $album->user_id, + 'edit' => Auth::check() && Auth::user()->id == $album->user_id + ] ]; } diff --git a/app/models/Entities/Playlist.php b/app/models/Entities/Playlist.php index c9fb9a0f..46be51b2 100644 --- a/app/models/Entities/Playlist.php +++ b/app/models/Entities/Playlist.php @@ -105,7 +105,11 @@ 'name' => $playlist->user->display_name, 'url' => $playlist->user->url, ], - 'user_data' => $userData + 'user_data' => $userData, + 'permissions' => [ + 'delete' => Auth::check() && Auth::user()->id == $playlist->user_id, + 'edit' => Auth::check() && Auth::user()->id == $playlist->user_id + ] ]; } diff --git a/app/models/Entities/Track.php b/app/models/Entities/Track.php index ebb1d8e7..aa4f2612 100644 --- a/app/models/Entities/Track.php +++ b/app/models/Entities/Track.php @@ -38,8 +38,6 @@ $query->whereUserId(Auth::user()->id); }]); } - - return !$query; } public function scopePublished($query) { @@ -194,7 +192,11 @@ 'streams' => [ 'mp3' => $track->getStreamUrl('MP3') ], - 'user_data' => $userData + 'user_data' => $userData, + 'permissions' => [ + 'delete' => Auth::check() && Auth::user()->id == $track->user_id, + 'edit' => Auth::check() && Auth::user()->id == $track->user_id + ] ]; } diff --git a/app/routes.php b/app/routes.php index cca99e9f..2e28f1ea 100644 --- a/app/routes.php +++ b/app/routes.php @@ -106,6 +106,10 @@ Route::get('/playlists/owned', 'Api\Web\PlaylistsController@getOwned'); Route::get('/playlists/pinned', 'Api\Web\PlaylistsController@getPinned'); + + Route::get('/favourites/tracks', 'Api\Web\FavouritesController@getTracks'); + Route::get('/favourites/albums', 'Api\Web\FavouritesController@getAlbums'); + Route::get('/favourites/playlists', 'Api\Web\FavouritesController@getPlaylists'); }); Route::group(['before' => 'csrf'], function(){ @@ -127,6 +131,8 @@ Route::get('/albums/create', 'ContentController@getAlbums'); Route::get('/playlists', 'ContentController@getPlaylists'); + Route::get('/uploader', 'UploaderController@getIndex'); + Route::get('/', 'AccountController@getIndex'); }); }); diff --git a/app/views/shared/_app_layout.blade.php b/app/views/shared/_app_layout.blade.php index 87879362..a41c7b3c 100644 --- a/app/views/shared/_app_layout.blade.php +++ b/app/views/shared/_app_layout.blade.php @@ -26,6 +26,18 @@
Pony.fm
+ @if (Auth::check()) + + @endif
@@ -42,29 +54,25 @@ @if (Auth::check()) -
  • Account
  • +
  • Account
  • +
  • Favourites
  • @endif -
  • Meta
  • +
  • About
  • @if (Auth::check()) +
  • + Upload Music +
  • - Playlists

  • no pinned playlists
  • @endif @@ -73,8 +81,6 @@ - - @endsection @section('styles') diff --git a/app/views/shared/_layout.blade.php b/app/views/shared/_layout.blade.php index 3d3c33e0..d56ce336 100644 --- a/app/views/shared/_layout.blade.php +++ b/app/views/shared/_layout.blade.php @@ -10,7 +10,7 @@ @yield('styles') - + @yield('content') @yield('scripts') diff --git a/public/scripts/app/app.coffee b/public/scripts/app/app.coffee index 3b0ced1a..c28f1e22 100644 --- a/public/scripts/app/app.coffee +++ b/public/scripts/app/app.coffee @@ -6,64 +6,74 @@ module.config [ '$locationProvider', '$stateProvider', '$dialogProvider' (location, state, $dialogProvider) -> + # Upload + + state.state 'uploader', + url: '/account/uploader' + templateUrl: '/templates/uploader/index.html' + controller: 'uploader' + # Account state.state 'account', url: '/account' + abstract: true + templateUrl: '/templates/account/_layout.html' + + state.state 'account.settings', + url: '' templateUrl: '/templates/account/settings.html' controller: 'account-settings' - state.state 'account-content', - url: '/account' - abstract: true - templateUrl: '/templates/account/content/_layout.html' - - state.state 'account-content.tracks', + state.state 'account.tracks', url: '/tracks' - templateUrl: '/templates/account/content/tracks.html' + templateUrl: '/templates/account/tracks.html' controller: 'account-tracks' - state.state 'account-content.tracks.edit', + state.state 'account.tracks.edit', url: '/edit/:track_id' - templateUrl: '/templates/account/content/track.html' - controller: 'account-tracks-edit' + templateUrl: '/templates/account/track.html' + controller: 'account-track' - state.state 'account-content.albums', + state.state 'account.albums', url: '/albums' - templateUrl: '/templates/account/content/albums.html' + templateUrl: '/templates/account/albums.html' controller: 'account-albums' - state.state 'account-content.albums.create', + state.state 'account.albums.create', url: '/create' - templateUrl: '/templates/account/content/album.html' + templateUrl: '/templates/account/album.html' controller: 'account-albums-edit' - state.state 'account-content.albums.edit', + state.state 'account.albums.edit', url: '/edit/:album_id' - templateUrl: '/templates/account/content/album.html' + templateUrl: '/templates/account/album.html' controller: 'account-albums-edit' - state.state 'account-content-playlists', - url: '/account/playlists' - templateUrl: '/templates/account/content/playlists.html' + state.state 'account.playlists', + url: '/playlists' + templateUrl: '/templates/account/playlists.html' controller: 'account-playlists' - state.state 'account-favourites', + state.state 'favourites', url: '/account/favourites' abstract: true - templateUrl: '/templates/account/favourites/_layout.html' + templateUrl: '/templates/favourites/_layout.html' - state.state 'account-favourites.tracks', - url: '' - templateUrl: '/templates/account/favourites/tracks.html' + state.state 'favourites.tracks', + url: '/tracks' + templateUrl: '/templates/favourites/tracks.html' + controller: 'favourites-tracks' - state.state 'account-favourites.playlists', + state.state 'favourites.playlists', url: '/playlists' - templateUrl: '/templates/account/favourites/playlists.html' + templateUrl: '/templates/favourites/playlists.html' + controller: 'favourites-playlists' - state.state 'account-favourites.albums', + state.state 'favourites.albums', url: '/albums' - templateUrl: '/templates/account/favourites/albums.html' + templateUrl: '/templates/favourites/albums.html' + controller: 'favourites-albums' # Tracks @@ -72,14 +82,14 @@ module.config [ templateUrl: '/templates/content/_layout.html' state.state 'content.tracks', - templateUrl: '/templates/tracks/search.html' + templateUrl: '/templates/tracks/index.html' controller: 'tracks' url: '/tracks' abstract: true state.state 'content.tracks.list', url: '^/tracks?filter&page' - templateUrl: '/templates/tracks/search-list.html' + templateUrl: '/templates/tracks/list.html' controller: 'tracks-list' state.state 'content.track', diff --git a/public/scripts/app/controllers/account-albums-edit.coffee b/public/scripts/app/controllers/account-albums-edit.coffee index 89145e08..d7238650 100644 --- a/public/scripts/app/controllers/account-albums-edit.coffee +++ b/public/scripts/app/controllers/account-albums-edit.coffee @@ -73,7 +73,7 @@ angular.module('ponyfm').controller "account-albums-edit", [ if $scope.isNew $scope.isDirty = false $scope.$emit 'album-created' - $state.transitionTo 'account-content.albums.edit', {album_id: response.id} + $state.transitionTo 'account.albums.edit', {album_id: response.id} else $scope.isDirty = false $scope.data.selectedAlbum.title = $scope.album.title @@ -104,7 +104,7 @@ angular.module('ponyfm').controller "account-albums-edit", [ $.post('/api/web/albums/delete/' + $scope.album.id, {_token: window.pfm.token}) .then -> $scope.$apply -> $scope.$emit 'album-deleted' - $state.transitionTo 'account-content.albums' + $state.transitionTo 'account.albums' $scope.setCover = (image, type) -> delete $scope.album.cover_id diff --git a/public/scripts/app/controllers/account-albums.coffee b/public/scripts/app/controllers/account-albums.coffee index c0af7899..78451c8e 100644 --- a/public/scripts/app/controllers/account-albums.coffee +++ b/public/scripts/app/controllers/account-albums.coffee @@ -13,6 +13,8 @@ angular.module('ponyfm').controller "account-albums", [ selectedAlbum: null tracksDb: [] + selectAlbum = (album) -> $scope.data.selectedAlbum = album + updateTracks = (tracks) -> $scope.data.tracksDb.push track for track in tracks @@ -32,8 +34,6 @@ angular.module('ponyfm').controller "account-albums", [ albums.refresh().done updateAlbums - selectAlbum = (album) -> $scope.data.selectedAlbum = album - $scope.$on '$stateChangeSuccess', () -> if $state.params.album_id selectAlbum albumsDb[$state.params.album_id] diff --git a/public/scripts/app/controllers/account-tracks-edit.coffee b/public/scripts/app/controllers/account-track.coffee similarity index 94% rename from public/scripts/app/controllers/account-tracks-edit.coffee rename to public/scripts/app/controllers/account-track.coffee index 31f17ae5..f9ae1b10 100644 --- a/public/scripts/app/controllers/account-tracks-edit.coffee +++ b/public/scripts/app/controllers/account-track.coffee @@ -1,12 +1,12 @@ -window.pfm.preloaders['account-tracks-edit'] = [ +window.pfm.preloaders['account-track'] = [ 'account-tracks', 'account-albums', 'taxonomies', '$state' (tracks, albums, taxonomies, state) -> $.when.all [albums.refresh(), taxonomies.refresh(), tracks.getEdit(state.params.track_id, true)] ] -angular.module('ponyfm').controller "account-tracks-edit", [ - '$scope', '$state', 'taxonomies', '$dialog', 'account-albums', 'account-tracks' - ($scope, $state, taxonomies, $dialog, albums, tracks) -> +angular.module('ponyfm').controller "account-track", [ + '$scope', '$state', 'taxonomies', '$dialog', 'account-albums', 'account-tracks', 'images' + ($scope, $state, taxonomies, $dialog, albums, tracks, images) -> $scope.isDirty = false $scope.isSaving = false $scope.taxonomies = taxonomies @@ -85,6 +85,7 @@ angular.module('ponyfm').controller "account-tracks-edit", [ trackDbItem.cover_url = track.real_cover_url $scope.isDirty = false $scope.errors = {} + images.refresh true formData = new FormData(); _.each $scope.edit, (value, name) -> @@ -136,7 +137,7 @@ angular.module('ponyfm').controller "account-tracks-edit", [ $.post('/api/web/tracks/delete/' + track.id, {_token: window.pfm.token}) .then -> $scope.$apply -> $scope.$emit 'track-deleted' - $state.transitionTo 'account-content.tracks' + $state.transitionTo 'account.tracks' $scope.$on '$locationChangeStart', (e) -> return if !$scope.isDirty diff --git a/public/scripts/app/controllers/account-tracks.coffee b/public/scripts/app/controllers/account-tracks.coffee index 369b00cd..6c1db3c0 100644 --- a/public/scripts/app/controllers/account-tracks.coffee +++ b/public/scripts/app/controllers/account-tracks.coffee @@ -26,67 +26,8 @@ angular.module('ponyfm').controller "account-tracks", [ tracks.refresh().done setTracks - $scope.filters = - published: [ - {title: 'Either', query: ''}, - {title: 'Yes', query: 'published=1'}, - {title: 'No', query: 'published=0'}] - - sort: [ - {title: 'Newest to Oldest', query: 'order=created_at,desc'}, - {title: 'Oldest to Newest', query: 'order=created_at,asc'}] - - genres: {} - trackTypes: {} - - $scope.filter = - published: $scope.filters.published[0] - sort: $scope.filters.sort[0] - genres: {} - trackTypes: {} - - $scope.titles = - genres: 'All' - trackTypes: 'All' - - for genre in taxonomies.genres - $scope.filters.genres[genre.id] = - id: genre.id - title: genre.name - query: 'genres[]=' + genre.id - - for type in taxonomies.trackTypes - $scope.filters.trackTypes[type.id] = - id: type.id - title: type.title - query: 'types[]=' + type.id - - $scope.updateFilter = (type, filter) -> - $scope.filter[type] = filter - $scope.refreshList() - - $scope.toggleFilter = (type, id) -> - if !$scope.filter[type][id] - $scope.filter[type][id] = $scope.filters[type][id] - else - delete $scope.filter[type][id] - - length = _.keys($scope.filter[type]).length - if length == 1 - $scope.titles[type] = _.map($scope.filter[type], (f) -> f.title).join ', ' - else if length > 1 - $scope.titles[type] = length + ' selected' - else - $scope.titles[type] = 'All' - - $scope.refreshList() - $scope.refreshList = () -> - parts = [$scope.filter.sort.query, $scope.filter.published.query] - _.each $scope.filter.genres, (g) -> parts.push g.query - _.each $scope.filter.trackTypes, (g) -> parts.push g.query - query = parts.join '&' - tracks.refresh(query).done setTracks + tracks.refresh().done setTracks $scope.selectTrack = (track) -> $scope.data.selectedTrack = track diff --git a/public/scripts/app/controllers/favourites-albums.coffee b/public/scripts/app/controllers/favourites-albums.coffee new file mode 100644 index 00000000..c1c8cbf9 --- /dev/null +++ b/public/scripts/app/controllers/favourites-albums.coffee @@ -0,0 +1,12 @@ +window.pfm.preloaders['favourites-albums'] = [ + 'favourites' + (favourites) -> + favourites.fetchAlbums(true) +] + +angular.module('ponyfm').controller "favourites-albums", [ + '$scope', 'favourites' + ($scope, favourites) -> + favourites.fetchAlbums().done (res) -> + $scope.albums = res.albums +] \ No newline at end of file diff --git a/public/scripts/app/controllers/favourites-playlists.coffee b/public/scripts/app/controllers/favourites-playlists.coffee new file mode 100644 index 00000000..0f041875 --- /dev/null +++ b/public/scripts/app/controllers/favourites-playlists.coffee @@ -0,0 +1,12 @@ +window.pfm.preloaders['favourites-playlists'] = [ + 'favourites' + (favourites) -> + favourites.fetchPlaylists(true) +] + +angular.module('ponyfm').controller "favourites-playlists", [ + '$scope', 'favourites' + ($scope, favourites) -> + favourites.fetchPlaylists().done (res) -> + $scope.playlists = res.playlists +] \ No newline at end of file diff --git a/public/scripts/app/controllers/favourites-tracks.coffee b/public/scripts/app/controllers/favourites-tracks.coffee new file mode 100644 index 00000000..8a2ccdd4 --- /dev/null +++ b/public/scripts/app/controllers/favourites-tracks.coffee @@ -0,0 +1,12 @@ +window.pfm.preloaders['favourites-tracks'] = [ + 'favourites' + (favourites) -> + favourites.fetchTracks(true) +] + +angular.module('ponyfm').controller "favourites-tracks", [ + '$scope', 'favourites' + ($scope, favourites) -> + favourites.fetchTracks().done (res) -> + $scope.tracks = res.tracks +] \ No newline at end of file diff --git a/public/scripts/app/controllers/upload.coffee b/public/scripts/app/controllers/upload.coffee deleted file mode 100644 index 43b2d911..00000000 --- a/public/scripts/app/controllers/upload.coffee +++ /dev/null @@ -1,32 +0,0 @@ -angular.module('ponyfm').controller "upload", [ - '$scope', 'auth', 'upload', '$state' - ($scope, auth, upload, $state) -> - $scope.$on 'upload-queue-started', () -> - $scope.state = 'uploading' - $scope.uploadDialogOpen = true - $scope.uploads = {} - $scope.progress = 0 - $scope.uploadedFiles = 0 - $scope.totalFiles = 0 - - $scope.$on 'upload-added', (e, upload) -> - $scope.uploads[upload.index] = upload - $scope.totalFiles++ - - $scope.$on 'upload-queue-ended', () -> - $scope.state = 'finished' - $scope.uploadDialogOpen = false if _.each upload.queue, (u) -> u.error == null - $state.transitionTo 'account-content.tracks' - $scope.uploadDialogOpen = false if !(_.size $scope.uploads) - - $scope.$on 'upload-finished', (e, upload) -> - $scope.uploadedFiles++ - delete $scope.uploads[upload.index] if upload.success - - $scope.$on 'upload-progress', () -> - $scope.progress = upload.totalBytesUploaded / upload.totalBytes * 100 - $scope.state = 'processing' if $scope.progress >= 100 - - $scope.close = () -> - $scope.uploadDialogOpen = false -] \ No newline at end of file diff --git a/public/scripts/app/controllers/uploader.coffee b/public/scripts/app/controllers/uploader.coffee new file mode 100644 index 00000000..121a4afa --- /dev/null +++ b/public/scripts/app/controllers/uploader.coffee @@ -0,0 +1,8 @@ +angular.module('ponyfm').controller "uploader", [ + '$scope', 'auth', 'upload', '$state' + ($scope, auth, upload, $state) -> + + $scope.data = upload + + $scope.$on 'upload-finished', (e, upload) -> +] \ No newline at end of file diff --git a/public/scripts/app/directives/player.coffee b/public/scripts/app/directives/player.coffee index 4cacc9f4..29db05b4 100644 --- a/public/scripts/app/directives/player.coffee +++ b/public/scripts/app/directives/player.coffee @@ -41,7 +41,7 @@ angular.module('ponyfm').directive 'pfmPlayer', () -> moveVolumeSlider = (absoluteY) -> newY = absoluteY - $bar.offset().top; - maxY = $bar.height() - ($knob.height() / 2) + maxY = $bar.height() - ($knob.height() / 2) - 8 newY = 0 if newY < 0 newY = maxY if newY > maxY @@ -54,11 +54,11 @@ angular.module('ponyfm').directive 'pfmPlayer', () -> e.preventDefault() e.stopPropagation() - $slider.click (e) -> $scope.$apply -> moveVolumeSlider(e.pageY) + $slider.click (e) -> $scope.$apply -> moveVolumeSlider(e.pageY - 8) $(document).mousemove (e) -> return if !isSliding - moveVolumeSlider(e.pageY) + moveVolumeSlider(e.pageY - 8) $knob.mousedown (e) -> e.preventDefault() diff --git a/public/scripts/app/directives/popup.coffee b/public/scripts/app/directives/popup.coffee index 3a59cb6c..1541e715 100644 --- a/public/scripts/app/directives/popup.coffee +++ b/public/scripts/app/directives/popup.coffee @@ -43,7 +43,7 @@ angular.module('ponyfm').directive 'pfmPopup', () -> height = windowHeight - top; return { - left: left - parentPosition.left - 5 + left: left - parentPosition.left top: top - parentPosition.top, height: height - 15} diff --git a/public/scripts/app/directives/uploader.coffee b/public/scripts/app/directives/uploader.coffee index 267cf00b..fb817b72 100644 --- a/public/scripts/app/directives/uploader.coffee +++ b/public/scripts/app/directives/uploader.coffee @@ -1,21 +1,19 @@ angular.module('ponyfm').directive 'uploader', [ 'upload' - (upload) -> (scope) -> - $body = $ 'body' - $notice = $("

    Drop the files anywhere to begin your upload!

    ").appendTo($body) - notice = $notice[0] + (upload) -> (scope, element) -> + $dropzone = $(element) - window.addEventListener 'dragover', (e) -> + $dropzone[0].addEventListener 'dragover', (e) -> e.preventDefault() - $body.addClass 'file-over' + $dropzone.addClass 'file-over' - notice.addEventListener 'dragleave', (e) -> + $dropzone[0].addEventListener 'dragleave', (e) -> e.preventDefault() - $body.removeClass 'file-over' + $dropzone.removeClass 'file-over' - notice.addEventListener 'drop', (e) -> + $dropzone[0].addEventListener 'drop', (e) -> e.preventDefault() - $body.removeClass 'file-over' + $dropzone.removeClass 'file-over' files = e.target.files || e.dataTransfer.files scope.$apply -> upload.upload files diff --git a/public/scripts/app/services/favourites.coffee b/public/scripts/app/services/favourites.coffee index 1165bde7..a242c3ef 100644 --- a/public/scripts/app/services/favourites.coffee +++ b/public/scripts/app/services/favourites.coffee @@ -1,6 +1,10 @@ angular.module('ponyfm').factory('favourites', [ '$rootScope', '$http' ($rootScope, $http) -> + tracksDef = null + playlistsDef = null + albumsDef = null + self = toggle: (type, id) -> def = new $.Deferred() @@ -9,5 +13,29 @@ angular.module('ponyfm').factory('favourites', [ def.promise() + fetchTracks: (force) -> + return tracksDef if !force && tracksDef + tracksDef = new $.Deferred() + $http.get('/api/web/favourites/tracks').success (res) -> + tracksDef.resolve res + + tracksDef + + fetchAlbums: (force) -> + return albumsDef if !force && albumsDef + albumsDef = new $.Deferred() + $http.get('/api/web/favourites/albums').success (res) -> + albumsDef.resolve res + + albumsDef + + fetchPlaylists: (force) -> + return playlistsDef if !force && playlistsDef + playlistsDef = new $.Deferred() + $http.get('/api/web/favourites/playlists').success (res) -> + playlistsDef.resolve res + + playlistsDef + self ]) \ No newline at end of file diff --git a/public/scripts/app/services/images.coffee b/public/scripts/app/services/images.coffee index d961bd3b..33b74522 100644 --- a/public/scripts/app/services/images.coffee +++ b/public/scripts/app/services/images.coffee @@ -5,8 +5,8 @@ angular.module('ponyfm').factory('images', [ self = images: [] isLoading: true - refresh: () -> - return def if def + refresh: (force) -> + return def if !force && def def = new $.Deferred() self.images = [] diff --git a/public/scripts/app/services/upload.coffee b/public/scripts/app/services/upload.coffee index 3eac12e1..00c2a959 100644 --- a/public/scripts/app/services/upload.coffee +++ b/public/scripts/app/services/upload.coffee @@ -3,12 +3,8 @@ angular.module('ponyfm').factory('upload', [ ($rootScope) -> self = queue: [] - totalBytes: 0 - totalBytesUploaded: 0 upload: (files) -> - $rootScope.$broadcast 'upload-queue-started' if self.queue.length == 0 - _.each files, (file) -> upload = name: file.name @@ -21,7 +17,6 @@ angular.module('ponyfm').factory('upload', [ error: null self.queue.push upload - self.totalBytes += file.size $rootScope.$broadcast 'upload-added', upload xhr = new XMLHttpRequest() @@ -29,7 +24,6 @@ angular.module('ponyfm').factory('upload', [ $rootScope.$apply -> upload.uploadedSize = e.loaded upload.progress = e.loaded / upload.size * 100 - self.totalBytesUploaded = _.reduce self.queue, ((i, u) -> i + u.uploadedSize), 0 $rootScope.$broadcast 'upload-progress', upload xhr.onload = -> $rootScope.$apply -> @@ -45,15 +39,9 @@ angular.module('ponyfm').factory('upload', [ $rootScope.$broadcast 'upload-error', [upload, error] else upload.success = true + upload.trackId = $.parseJSON(xhr.responseText).id $rootScope.$broadcast 'upload-finished', upload - - if (_.every self.queue, (u) -> !u.isUploading) - self.queue = [] - self.totalBytes = 0 - self.totalBytesUploaded = 0 - $rootScope.$broadcast 'upload-queue-ended' - formData = new FormData(); formData.append('track', file); diff --git a/public/styles/account-content.less b/public/styles/account-content.less index 8f643102..1ae43147 100644 --- a/public/styles/account-content.less +++ b/public/styles/account-content.less @@ -1,2 +1,418 @@ @import-once 'base/bootstrap/bootstrap'; @import-once 'mixins'; + +ul.playlists { + overflow-y: auto; + margin: 0px; + padding: 0px; + list-style: none; + margin: 0px 5px; + margin-top: 10px; + + li { + overflow: hidden; + margin: 0px; + padding: 0px; + height: 40px; + border-bottom: 1px solid #ddd; + + img { + border-right: 1px solid #ddd; + padding: 0px; + display: block; + height: 40px; + width: 40px; + float: left; + } + + .btn-group { + float: right; + display: block; + margin-top: 7px; + margin-right: 7px; + + .btn { + .border-radius(0px); + } + } + + a.main { + display: block; + text-decoration: none; + color: #444; + + .is-public { + display: block; + float: right; + font-weight: bold; + margin-top: 10px; + margin-right: 10px; + font-size: 8pt; + } + + .title { + .ellipsis(); + margin-left: 50px; + line-height: 40px; + height: 40px; + display: block; + } + + &:hover { + background: #eee; + } + } + } +} + +.image-selector { + width: 500px; + max-height: 300px; + overflow-y: auto; + + ul { + list-style: none; + padding: 0px; + margin: 0px; + + li { + margin: 0px; + float: left; + width: 20%; + cursor: pointer; + + img { + .transition(all 400ms); + display: block; + width: 100px; + height: 100px; + } + + &:hover { + img { + opacity: .8; + } + } + } + } +} + +html { + .two-pane-view.closed { + .account-albums-listing { + li { + .box-sizing(border-box); + width: 20%; + + a { + padding: 15px; + + .image { + .img-polaroid(); + position: relative; + left: -5px; + width: 100%; + height: auto; + float: none; + } + + .title { + margin: 0px; + font-size: 12pt; + padding: 0px; + margin-top: 5px; + } + + .published { + margin: 0px; + padding: 0px; + } + } + } + } + } +} + +.account-tracks-listing, .account-albums-listing { + overflow-y: auto; + margin: 0px; + padding: 0px; + list-style: none; + + li { + .box-sizing(border-box); + + padding: 0px; + margin: 0px; + line-height: normal; + + &.empty { + .alert(); + float: none !important; + width: auto !important; + display: block; + padding: 5px; + font-size: 9pt; + } + + &.is-not-published a { + background: fadeout(@yellow, 90%); + } + + &.selected, &.selected:hover { + a { + background: @pfm-purple; + cursor: default; + color: #fff; + + .published { + color: #eee; + } + } + } + + a { + .transition(350px ease-out all); + + display: block; + margin: 0px; + padding: 5px; + font-size: 9pt; + font-weight: normal; + overflow: hidden; + + .image { + width: 32px; + height: 32px; + float: left; + display: block; + } + + .title { + .ellipsis(); + display: block; + margin-left: 37px; + } + + .published { + display: block; + color: #777; + margin-left: 37px; + font-size: 8pt; + } + + &:hover { + background: #ddd; + text-decoration: none; + } + } + } +} + +.two-pane-view { + .list { + .dropdowns { + margin-top: 0px; + } + } + + .editor { + display: none; + + .album-track-listing { + padding: 0px; + clear: both; + margin: 0px; + margin-top: 10px; + list-style: none; + + li { + overflow: hidden; + line-height: normal; + padding: 0px; + margin: 0px; + font-size: 8pt; + border-bottom: 1px dashed #ddd; + + div { + padding: 2px; + } + + span { + display: block; + float: left; + margin-left: 5px; + margin-top: 2px; + } + + .btn { + line-height: normal; + padding: 2px 5px; + margin: 0px; + } + + &.ui-sortable-helper { + #gradient>.vertical(@dropdownLinkBackgroundHover, darken(@dropdownLinkBackgroundHover, 5%)); + border: none; + color: #fff; + } + + &.ui-sortable-placeholder { + background: @yellow; + } + } + } + + .show-songs, .album { + .btn { + display: block; + float: none; + } + } + + .show-songs, .album, .track-selector { + .btn { + .border-radius(0px); + padding: 3px 10px; + font-size: 8pt; + text-align: left; + } + + .error { + margin-top: 10px; + } + + .pfm-popup { + width: 300px; + + ul { + margin: 0px; + padding: 0px; + list-style: none; + + li { + margin: 0px; + padding: 0px; + + a { + .ellipsis(); + display: block; + padding: 3px 10px; + font-size: 8pt; + color: #333333; + + &:hover { + #gradient>.vertical(@dropdownLinkBackgroundHover, darken(@dropdownLinkBackgroundHover, 5%)); + text-decoration: none; + color: @dropdownLinkColorHover; + } + } + + &.selected { + a { + #gradient>.vertical(@green, darken(@green, 5%)); + color: #fff; + font-weight: bold; + + &:hover { + #gradient>.vertical(fadeout(@green, 20%), fadeout(darken(@green, 5%), 20%)); + } + } + } + } + } + } + } + } + + &.closed { + .account-tracks-listing, .account-albums-listing { + .clearfix(); + + li { + float: left; + width: 25%; + + &.empty { + } + } + } + } + + &.open { + .list { + border-right: 2px solid #ddd; + + width: 250px; + float: left; + } + + .editor { + margin-left: 260px; + margin-right: 10px; + display: block; + + .stretch-to-bottom { + padding-right: 10px; + } + } + } +} + +.license-grid { + margin: 0px; + padding: 0px; + overflow: hidden; + list-style: none; + + li { + float: left; + width: 25%; + + > div { + margin: 0px 5px; + border: 1px solid #ddd; + padding: 10px; + cursor: pointer; + + strong { + font-size: 9pt; + display: block; + margin: 0px; + margin-bottom: 5px; + padding: 0px; + line-height: normal; + } + } + + p { + min-height: 120px; + font-size: 9pt; + } + + a { + .border-radius(0px); + display: block; + width: auto; + } + + &.selected { + > div { + cursor: default; + border-color: @blue; + } + } + + &:hover > div { + border: 1px solid #3366CC; + } + + &:first-child > div { + margin-left: 0px; + } + + &:last-child > div { + margin-right: 0px; + } + } +} \ No newline at end of file diff --git a/public/styles/app.less b/public/styles/app.less index 0ac317bf..babef2c2 100644 --- a/public/styles/app.less +++ b/public/styles/app.less @@ -12,4 +12,5 @@ @import 'body'; @import 'player'; @import 'content'; -@import 'dashboard'; \ No newline at end of file +@import 'dashboard'; +@import 'uploader'; \ No newline at end of file diff --git a/public/styles/layout.less b/public/styles/layout.less index 8dd542f5..3823a28f 100644 --- a/public/styles/layout.less +++ b/public/styles/layout.less @@ -33,6 +33,50 @@ header { text-decoration: none; } } + + .user-details { + float: right; + margin-right: 10px; + margin-top: 9px; + + .avatar { + .img-polaroid(); + + display: block; + float: right; + padding: 2px; + cursor: pointer; + + &:hover { + background: #ddd; + } + + span { + font-weight: bold; + display: inline-block; + padding: 0px 3px; + } + } + + .dropdown-menu { + left: auto; + right: 0px; + } + + .name { + float: left; + height: 44px; + line-height: 44px; + padding-right: 10px; + font-weight: bold; + font-size: 12pt; + } + + img { + height: 40px; + width: 40px; + } + } } .now-playing { @@ -52,6 +96,7 @@ header { padding: 0px; margin: 0px; font-size: 10pt; + position: relative; li { margin: 0px; @@ -128,6 +173,11 @@ header { } } } + + li.uploader { + a { + } + } } .site-content { diff --git a/public/styles/player.less b/public/styles/player.less index b7b726f0..9302a342 100644 --- a/public/styles/player.less +++ b/public/styles/player.less @@ -2,7 +2,7 @@ @import-once 'mixins'; .track-player { - overflow: hidden; + margin-right: 75px; padding: 10px; .image { @@ -106,6 +106,47 @@ color: #000; } } + + &.volume { + position: relative; + + .volume-slider { + display: none; + z-index: 1000; + position: absolute; + left: 0px; + top: 33px; + width: 100%; + height: 150px; + background: #ddd; + + .bar { + background: @pfm-purple; + width: 10px; + margin: auto; + height: 100%; + position: relative; + } + + .knob { + position: absolute; + top: 0px; + left: -3px; + + background: darken(@pfm-purple, 20%); + width: 16px; + height: 16px; + } + } + + &:hover, &.keep-open { + .volume-slider { + display: block; + } + + background: #ddd; + } + } } } } \ No newline at end of file diff --git a/public/styles/profiler.less b/public/styles/profiler.less index 9de8ba48..ad4c15e0 100644 --- a/public/styles/profiler.less +++ b/public/styles/profiler.less @@ -11,6 +11,7 @@ html { border-left: 3px solid #111; .buttons { + padding: 5px; background: #222; .clear-button { @@ -18,6 +19,10 @@ html { } .open-button { + font-size: inherit; + padding: 2px 10px; + text-indent: 0px; + i:before { content: "\f077"; } @@ -42,7 +47,6 @@ html { color: #fff; .buttons { - padding: 5px; overflow: hidden; > a { @@ -60,6 +64,13 @@ html { margin-right: 5px; display: none; } + + .open-button { + font-size: 1pt; + padding: 2px; + text-indent: -1000px; + overflow: hidden; + } } ul { diff --git a/public/styles/uploader.less b/public/styles/uploader.less new file mode 100644 index 00000000..48e54b60 --- /dev/null +++ b/public/styles/uploader.less @@ -0,0 +1,82 @@ +@import-once 'variables'; + +.uploader { + h1 { + margin: 10px 0px; + } + + .dropzone { + border: 2px dotted @pfm-purple; + background: lighten(@pfm-purple, 25%); + padding: 10px; + color: darken(@pfm-purple, 25%); + margin-bottom: 10px; + + p { + padding: 0px; + margin: 0px; + } + + &.file-over { + background: lighten(@pfm-purple, 5%); + } + } + + .close-button { + .border-radius(0px); + width: auto; + margin-bottom: 10px; + float: none; + display: block; + } + + .uploads { + margin: 0px; + padding: 0px; + list-style: none; + + li { + margin-bottom: 5px; + background: #eee; + font-size: 9pt; + position: relative; + z-index: 1; + color: #444; + border: 2px solid #aaa; + + p { + margin: 5px; + padding: 0px; + height: 26px; + line-height: 26px; + + a { + } + } + + .bar { + position: absolute; + top: 0px; + left: 0px; + height: 100%; + z-index: -1; + } + + &.has-error { + border-color: @red; + + .bar { + display: none; + } + } + + &.is-processing { + border-color: @blue; + + .bar { + display: none; + } + } + } + } +} \ No newline at end of file diff --git a/public/templates/account/_layout.html b/public/templates/account/_layout.html new file mode 100644 index 00000000..4ff51c58 --- /dev/null +++ b/public/templates/account/_layout.html @@ -0,0 +1,8 @@ + + + diff --git a/public/templates/account/content/album.html b/public/templates/account/album.html similarity index 100% rename from public/templates/account/content/album.html rename to public/templates/account/album.html diff --git a/public/templates/account/content/albums.html b/public/templates/account/albums.html similarity index 100% rename from public/templates/account/content/albums.html rename to public/templates/account/albums.html diff --git a/public/templates/account/content/_layout.html b/public/templates/account/content/_layout.html deleted file mode 100644 index 98762ac2..00000000 --- a/public/templates/account/content/_layout.html +++ /dev/null @@ -1,8 +0,0 @@ -
    - - - -
    \ No newline at end of file diff --git a/public/templates/account/content/playlists.html b/public/templates/account/content/playlists.html deleted file mode 100644 index 12689a12..00000000 --- a/public/templates/account/content/playlists.html +++ /dev/null @@ -1,25 +0,0 @@ -
    -

    Your Playlists

    - -
    \ No newline at end of file diff --git a/public/templates/account/content/tracks.html b/public/templates/account/content/tracks.html deleted file mode 100644 index 73f11e1b..00000000 --- a/public/templates/account/content/tracks.html +++ /dev/null @@ -1,60 +0,0 @@ -
    - - -
    - - - -
    -
    \ No newline at end of file diff --git a/public/templates/account/favourites/_layout.html b/public/templates/account/favourites/_layout.html deleted file mode 100644 index f3f83ba6..00000000 --- a/public/templates/account/favourites/_layout.html +++ /dev/null @@ -1,14 +0,0 @@ -
    - - - - -
    -		$state = {{$state.current.name}}
    -		$stateParams = {{$stateParams}}
    -	
    -
    \ No newline at end of file diff --git a/public/templates/account/favourites/albums.html b/public/templates/account/favourites/albums.html deleted file mode 100644 index fdb5a3d6..00000000 --- a/public/templates/account/favourites/albums.html +++ /dev/null @@ -1 +0,0 @@ -

    Favourite Albums

    \ No newline at end of file diff --git a/public/templates/account/favourites/playlists.html b/public/templates/account/favourites/playlists.html deleted file mode 100644 index f6915843..00000000 --- a/public/templates/account/favourites/playlists.html +++ /dev/null @@ -1 +0,0 @@ -

    Favourite Playlists

    \ No newline at end of file diff --git a/public/templates/account/favourites/tracks.html b/public/templates/account/favourites/tracks.html deleted file mode 100644 index bdf47f27..00000000 --- a/public/templates/account/favourites/tracks.html +++ /dev/null @@ -1 +0,0 @@ -

    Favourite tracks

    \ No newline at end of file diff --git a/public/templates/account/playlists.html b/public/templates/account/playlists.html new file mode 100644 index 00000000..86bec588 --- /dev/null +++ b/public/templates/account/playlists.html @@ -0,0 +1,22 @@ + diff --git a/public/templates/account/settings.html b/public/templates/account/settings.html index d0906c05..b88f1283 100644 --- a/public/templates/account/settings.html +++ b/public/templates/account/settings.html @@ -1,44 +1,36 @@ -
    -

    Account Settings

    -
    - -
    -
    -
    - - -
    Your current MLP Forums display name is {{settings.mlpforums_name}}
    -
    {{errors.display_name}}
    -
    -
    - -
    -
    -
    -
    - - -
    {{errors.description}}
    -
    -
    - -
    - -
    - -
    {{errors.avatar}}
    -
    {{errors.gravatar}}
    -
    -
    + +
      +
    • + +
    • +
    +
    +
    + + +
    Your current MLP Forums display name is {{settings.mlpforums_name}}
    +
    {{errors.display_name}}
    - -
    \ No newline at end of file +
    + +
    +
    + + +
    {{errors.description}}
    +
    +
    + +
    + +
    + +
    {{errors.avatar}}
    +
    {{errors.gravatar}}
    +
    + diff --git a/public/templates/account/content/track.html b/public/templates/account/track.html similarity index 100% rename from public/templates/account/content/track.html rename to public/templates/account/track.html diff --git a/public/templates/account/tracks.html b/public/templates/account/tracks.html new file mode 100644 index 00000000..4077a95a --- /dev/null +++ b/public/templates/account/tracks.html @@ -0,0 +1,15 @@ + diff --git a/public/templates/albums/list.html b/public/templates/albums/list.html index 76f13c39..ac1fb334 100644 --- a/public/templates/albums/list.html +++ b/public/templates/albums/list.html @@ -1,3 +1,3 @@
    - +
    \ No newline at end of file diff --git a/public/templates/albums/show.html b/public/templates/albums/show.html index 22a0800c..d4fa2789 100644 --- a/public/templates/albums/show.html +++ b/public/templates/albums/show.html @@ -10,6 +10,7 @@
  • Share or Embed
  • +
  • Edit
  • diff --git a/public/templates/directives/player.html b/public/templates/directives/player.html index 1bb075ad..ce36ef82 100644 --- a/public/templates/directives/player.html +++ b/public/templates/directives/player.html @@ -12,7 +12,7 @@
  • -
  • +
  • diff --git a/public/templates/favourites/_layout.html b/public/templates/favourites/_layout.html new file mode 100644 index 00000000..5f6096d3 --- /dev/null +++ b/public/templates/favourites/_layout.html @@ -0,0 +1,14 @@ +
    + + + + +
    +		$state = {{$state.current.name}}
    +		$stateParams = {{$stateParams}}
    +	
    +
    \ No newline at end of file diff --git a/public/templates/favourites/albums.html b/public/templates/favourites/albums.html new file mode 100644 index 00000000..76f13c39 --- /dev/null +++ b/public/templates/favourites/albums.html @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/public/templates/favourites/playlists.html b/public/templates/favourites/playlists.html new file mode 100644 index 00000000..19b6d3f9 --- /dev/null +++ b/public/templates/favourites/playlists.html @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/public/templates/tracks/search-list.html b/public/templates/favourites/tracks.html similarity index 100% rename from public/templates/tracks/search-list.html rename to public/templates/favourites/tracks.html diff --git a/public/templates/partials/upload-dialog.html b/public/templates/partials/upload-dialog.html deleted file mode 100644 index e34d2cf8..00000000 --- a/public/templates/partials/upload-dialog.html +++ /dev/null @@ -1,19 +0,0 @@ -
    -
    -

    - {{uploadedFiles}} of {{totalFiles}} - Uploading Tracks... -

    -

    Processing...

    - - Close - -
      -
    • -

      {{upload.name}}

      -

      {{upload.error}}

      -
      -
    • -
    -
    -
    \ No newline at end of file diff --git a/public/templates/playlists/list.html b/public/templates/playlists/list.html index 0e07df5b..19b6d3f9 100644 --- a/public/templates/playlists/list.html +++ b/public/templates/playlists/list.html @@ -1,3 +1,3 @@
    - +
    \ No newline at end of file diff --git a/public/templates/tracks/search.html b/public/templates/tracks/index.html similarity index 100% rename from public/templates/tracks/search.html rename to public/templates/tracks/index.html diff --git a/public/templates/tracks/list.html b/public/templates/tracks/list.html new file mode 100644 index 00000000..45e52838 --- /dev/null +++ b/public/templates/tracks/list.html @@ -0,0 +1,3 @@ +
    + +
    \ No newline at end of file diff --git a/public/templates/tracks/show.html b/public/templates/tracks/show.html index ef62b001..5a1a8f32 100644 --- a/public/templates/tracks/show.html +++ b/public/templates/tracks/show.html @@ -24,6 +24,7 @@
  • Share
  • +
  • Edit
  • diff --git a/public/templates/uploader/index.html b/public/templates/uploader/index.html new file mode 100644 index 00000000..b234fd9c --- /dev/null +++ b/public/templates/uploader/index.html @@ -0,0 +1,25 @@ +
    +
    +

    Drop files here to begin your upload!

    +
    + +
      +
    • +

      + + Processing + Uploading + {{upload.name}} + + + + Publish + + {{upload.name}} + +

      +

      {{upload.error}}

      +
      +
    • +
    +
    \ No newline at end of file