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 @@
-
\ 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 @@
-