diff --git a/app/models/Commands/EditAlbumCommand.php b/app/models/Commands/EditAlbumCommand.php
index 63ecf79f..40d30170 100644
--- a/app/models/Commands/EditAlbumCommand.php
+++ b/app/models/Commands/EditAlbumCommand.php
@@ -61,6 +61,6 @@
$this->_album->syncTrackIds($trackIds);
$this->_album->save();
- return CommandResponse::succeed();
+ return CommandResponse::succeed(['real_cover_url' => $this->_album->getCoverUrl(Image::NORMAL)]);
}
}
\ No newline at end of file
diff --git a/app/models/Commands/EditTrackCommand.php b/app/models/Commands/EditTrackCommand.php
index b73edf9b..3e9700d8 100644
--- a/app/models/Commands/EditTrackCommand.php
+++ b/app/models/Commands/EditTrackCommand.php
@@ -107,7 +107,7 @@
$track->updateTags();
$track->save();
- return CommandResponse::succeed();
+ return CommandResponse::succeed(['real_cover_url' => $track->getCoverUrl(Image::NORMAL)]);
}
private function removeTrackFromAlbum($track) {
diff --git a/app/views/shared/_app_layout.blade.php b/app/views/shared/_app_layout.blade.php
index ae3f76bc..045f2594 100644
--- a/app/views/shared/_app_layout.blade.php
+++ b/app/views/shared/_app_layout.blade.php
@@ -88,9 +88,9 @@
-
+
@yield('app_content')
-
+
diff --git a/public/scripts/app/app.coffee b/public/scripts/app/app.coffee
index 444dff6d..138c9e8f 100644
--- a/public/scripts/app/app.coffee
+++ b/public/scripts/app/app.coffee
@@ -1,6 +1,10 @@
+window.pfm.preloaders = {}
+
angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable'], [
- '$routeProvider', '$locationProvider', '$stateProvider', '$dialogProvider'
- (route, location, state, $dialogProvider) ->
+ '$routeProvider', '$locationProvider', '$stateProvider', '$dialogProvider', '$injector'
+ (route, location, state, $dialogProvider, $injector) ->
+
+ service = (name) -> angular.element(document.body).injector().get name
# Account
@@ -8,88 +12,58 @@ angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable'],
url: '/account'
templateUrl: '/templates/account/settings.html'
controller: 'account-settings'
- navigation:
- index: 9
state.state 'account-content',
url: '/account'
abstract: true
templateUrl: '/templates/account/content/_layout.html'
- navigation:
- index: 8
state.state 'account-content.tracks',
url: '/tracks'
templateUrl: '/templates/account/content/tracks.html'
controller: 'account-tracks'
- navigation:
- index: 8
- subIndex: 1
state.state 'account-content.tracks.edit',
url: '/edit/:track_id'
- navigation:
- index: 8
- subIndex: 1
+ templateUrl: '/templates/account/content/track.html'
+ controller: 'account-tracks-edit'
state.state 'account-content.albums',
url: '/albums'
templateUrl: '/templates/account/content/albums.html'
controller: 'account-albums'
- navigation:
- index: 8
- subIndex: 2
state.state 'account-content.albums.create',
url: '/create'
templateUrl: '/templates/account/content/album.html'
controller: 'account-albums-edit'
- navigation:
- index: 8
- subIndex: 2
state.state 'account-content.albums.edit',
url: '/edit/:album_id'
templateUrl: '/templates/account/content/album.html'
controller: 'account-albums-edit'
- navigation:
- index: 8
- subIndex: 2
state.state 'account-content-playlists',
url: '/account/playlists'
templateUrl: '/templates/account/content/playlists.html'
controller: 'account-playlists'
- navigation:
- index: 6
state.state 'account-favourites',
url: '/account/favourites'
abstract: true
templateUrl: '/templates/account/favourites/_layout.html'
- navigation:
- index: 7
state.state 'account-favourites.tracks',
url: ''
templateUrl: '/templates/account/favourites/tracks.html'
- navigation:
- index: 7
- subIndex: 1
state.state 'account-favourites.playlists',
url: '/playlists'
templateUrl: '/templates/account/favourites/playlists.html'
- navigation:
- index: 7
- subIndex: 3
state.state 'account-favourites.albums',
url: '/albums'
templateUrl: '/templates/account/favourites/albums.html'
- navigation:
- index: 7
- subIndex: 2
# Tracks
@@ -97,53 +71,39 @@ angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable'],
url: '/tracks'
templateUrl: '/templates/tracks/index.html'
controller: 'tracks'
- navigation:
- index: 2
# Albums
state.state 'albums',
url: '/albums'
templateUrl: '/templates/albums/index.html'
- navigation:
- index: 3
# Playlists
state.state 'playlists',
url: '/playlists'
templateUrl: '/templates/playlists/index.html'
- navigation:
- index: 4
state.state 'playlist',
url: '/playlist/:id/:slug'
templateUrl: '/templates/playlists/show.html'
controller: 'playlist'
- navigation:
- index: 4
# Artists
state.state 'artists',
url: '/artists'
templateUrl: '/templates/artists/index.html'
- navigation:
- index: 5
# Pages
state.state 'faq',
url: '/faq'
templateUrl: '/templates/pages/faq.html'
- navigation:
- index: 11
state.state 'about',
url: '/about'
templateUrl: '/templates/pages/about.html'
- navigation:
- index: 10
# Auth
@@ -151,14 +111,10 @@ angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable'],
url: '/login'
templateUrl: '/templates/auth/login.html'
controller: 'login'
- navigation:
- index: 12
state.state 'register',
url: '/register'
templateUrl: '/templates/auth/register.html'
- navigation:
- index: 13
# Hompage
@@ -167,14 +123,10 @@ angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable'],
url: '/'
templateUrl: '/templates/dashboard.html'
controller: 'dashboard'
- navigation:
- index: 0
else
state.state 'home',
url: '/'
templateUrl: '/templates/home/index.html'
- navigation:
- index: 0
route.otherwise '/'
diff --git a/public/scripts/app/controllers/account-albums-edit.coffee b/public/scripts/app/controllers/account-albums-edit.coffee
index 506b1e86..3b671fd4 100644
--- a/public/scripts/app/controllers/account-albums-edit.coffee
+++ b/public/scripts/app/controllers/account-albums-edit.coffee
@@ -1,6 +1,16 @@
+window.pfm.preloaders['account-albums-edit'] = [
+ 'account-tracks', 'account-albums', '$state'
+ (tracks, albums, $state) ->
+ defs = [tracks.refresh()]
+ if $state.params.album_id
+ defs.push albums.getEdit($state.params.album_id, true)
+
+ $.when.all defs
+]
+
angular.module('ponyfm').controller "account-albums-edit", [
- '$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
- ($scope, $state, taxonomies, $dialog, lightbox) ->
+ '$scope', '$state', '$dialog', 'account-albums'
+ ($scope, $state, $dialog, albums) ->
$scope.isNew = $state.params.album_id == undefined
$scope.data.isEditorOpen = true
$scope.errors = {}
@@ -38,33 +48,6 @@ angular.module('ponyfm').controller "account-albums-edit", [
$scope.isDirty = true
- $scope.refresh = () ->
- return if $scope.isNew
- $.getJSON('/api/web/albums/edit/' + $state.params.album_id)
- .done (album) -> $scope.$apply ->
- $scope.isDirty = false
- $scope.errors = {}
- $scope.album =
- id: album.id
- title: album.title
- description: album.description
- remove_cover: false
- cover: album.cover_url
-
- $scope.tracks = []
- $scope.tracks.push track for track in album.tracks
- $scope.trackIds[track.id] = track for track in album.tracks
- $scope.data.selectedAlbum.title = album.title
- $scope.data.selectedAlbum.description = album.description
- $scope.data.selectedAlbum.covers.normal = album.real_cover_url
-
- if $scope.isNew
- $scope.album =
- title: ''
- description: ''
- else
- $scope.refresh();
-
$scope.$on '$destroy', -> $scope.data.isEditorOpen = false
$scope.saveAlbum = ->
@@ -92,7 +75,9 @@ angular.module('ponyfm').controller "account-albums-edit", [
$scope.$emit 'album-created'
$state.transitionTo 'account-content.albums.edit', {album_id: response.id}
else
- $scope.refresh()
+ $scope.isDirty = false
+ $scope.data.selectedAlbum.title = $scope.album.title
+ $scope.data.selectedAlbum.covers.normal = response.real_cover_url
formData = new FormData()
@@ -134,7 +119,29 @@ angular.module('ponyfm').controller "account-albums-edit", [
$scope.isDirty = true
- $scope.$on '$stateChangeStart', (e) ->
- return if $scope.selectedTrack == null || !$scope.isDirty
+ if !$scope.isNew
+ albums.getEdit($state.params.album_id).done (album) ->
+ $scope.album =
+ id: album.id
+ title: album.title
+ description: album.description
+ remove_cover: false
+ cover: album.cover_url
+
+ $scope.tracks = []
+ $scope.tracks.push track for track in album.tracks
+ $scope.trackIds[track.id] = track for track in album.tracks
+
+ else
+ $scope.album =
+ title: ''
+ description: ''
+
+ window.onbeforeunload = ->
+ return if !$scope.isDirty
+ "Are you sure you want to leave this page without saving your changes?"
+
+ $scope.$on '$locationChangeStart', (e) ->
+ return if !$scope.isDirty
e.preventDefault() if !confirm('Are you sure you want to leave this page without saving your changes?')
]
\ No newline at end of file
diff --git a/public/scripts/app/controllers/account-albums.coffee b/public/scripts/app/controllers/account-albums.coffee
index 7b0ac670..c0af7899 100644
--- a/public/scripts/app/controllers/account-albums.coffee
+++ b/public/scripts/app/controllers/account-albums.coffee
@@ -1,41 +1,36 @@
-angular.module('ponyfm').controller "account-albums", [
- '$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
- ($scope, $state, taxonomies, $dialog, lightbox) ->
- albumsDb = {}
- lastIndex = null
+window.pfm.preloaders['account-albums'] = [
+ 'account-tracks', 'account-albums'
+ (tracks, albums) ->
+ $.when.all [tracks.refresh('published=true&in_album=false', true), albums.refresh(true)]
+]
+angular.module('ponyfm').controller "account-albums", [
+ '$scope', '$state', 'account-albums', 'account-tracks'
+ ($scope, $state, albums, tracks) ->
$scope.albums = []
$scope.data =
isEditorOpen: false
selectedAlbum: null
- tracksDb: {}
+ tracksDb: []
- refreshTrackDatabase = () ->
- $.getJSON('/api/web/tracks/owned?published=true&in_album=false')
- .done (tracks) -> $scope.$apply ->
- $scope.data.tracksDb[track.id] = track for track in tracks
+ updateTracks = (tracks) ->
+ $scope.data.tracksDb.push track for track in tracks
- refreshList = () ->
- $.getJSON('/api/web/albums/owned')
- .done (albums) -> $scope.$apply ->
- index = 0
- album.index = index++ for album in albums
- albumsDb[album.id] = album for album in albums
- $scope.albums = albums
+ tracks.refresh('published=true&in_album=false').done updateTracks
- if $state.params.album_id != undefined
- selectAlbum albumsDb[$state.params.album_id]
- else if lastIndex != null
- if $scope.albums.length
- album = null
- if $scope.albums.length > lastIndex + 1
- album = $scope.albums[lastIndex]
- else if lastIndex > 0
- album = $scope.albums[lastIndex - 1]
- else
- album = $scope.albums[0]
+ albumsDb = {}
- $state.transitionTo 'account-content.albums.edit', {album_id: album.id}
+ updateAlbums = (albums) ->
+ $scope.albums.length = 0
+
+ for album in albums
+ $scope.albums.push album
+ albumsDb[album.id] = album
+
+ if $state.params.album_id
+ selectAlbum albumsDb[$state.params.album_id]
+
+ albums.refresh().done updateAlbums
selectAlbum = (album) -> $scope.data.selectedAlbum = album
@@ -45,15 +40,7 @@ angular.module('ponyfm').controller "account-albums", [
else
selectAlbum null
- $scope.$on 'album-created', () -> refreshList()
-
- $scope.$on 'album-deleted', () ->
- lastIndex = $scope.data.selectedAlbum.index
- refreshList()
-
- $scope.$on 'album-updated', () ->
- refreshTrackDatabase()
-
- refreshList()
- refreshTrackDatabase()
+ $scope.$on 'album-created', () -> albums.refresh(true).done(updateAlbums)
+ $scope.$on 'album-deleted', () -> albums.refresh(true).done(updateAlbums)
+ $scope.$on 'album-updated', () -> tracks.refresh('published=true&in_album=false', true).done updateTracks
]
\ No newline at end of file
diff --git a/public/scripts/app/controllers/account-playlists.coffee b/public/scripts/app/controllers/account-playlists.coffee
index a8d1c2c2..ae7865d7 100644
--- a/public/scripts/app/controllers/account-playlists.coffee
+++ b/public/scripts/app/controllers/account-playlists.coffee
@@ -1,12 +1,17 @@
+window.pfm.preloaders['account-playlists'] = [
+ 'playlists'
+ (playlists) -> playlists.refreshOwned true
+]
+
angular.module('ponyfm').controller "account-playlists", [
'$scope', 'auth', '$dialog', 'playlists'
($scope, auth, $dialog, playlists) ->
$scope.playlists = []
- $scope.refresh = ->
- $.get('/api/web/playlists/owned')
- .done (playlists) -> $scope.$apply ->
- $scope.playlists.push playlist for playlist in playlists
+ loadPlaylists = (playlists) ->
+ $scope.playlists.push playlist for playlist in playlists
+
+ playlists.refreshOwned().done loadPlaylists
$scope.editPlaylist = (playlist) ->
dialog = $dialog.dialog
@@ -36,6 +41,4 @@ angular.module('ponyfm').controller "account-playlists", [
content = $scope.playlists[index]
_.each playlist, (value, name) -> content[name] = value
$scope.playlists.sort (left, right) -> left.title.localeCompare right.title
-
- $scope.refresh();
]
\ No newline at end of file
diff --git a/public/scripts/app/controllers/account-tracks-edit.coffee b/public/scripts/app/controllers/account-tracks-edit.coffee
new file mode 100644
index 00000000..ba6a5a44
--- /dev/null
+++ b/public/scripts/app/controllers/account-tracks-edit.coffee
@@ -0,0 +1,148 @@
+window.pfm.preloaders['account-tracks-edit'] = [
+ '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) ->
+ $scope.isDirty = false
+ $scope.isSaving = false
+ $scope.taxonomies = taxonomies
+ $scope.selectedSongsTitle = 'None'
+ $scope.selectedSongs = {}
+ $scope.albums = []
+ $scope.selectedAlbum = null
+
+ albumsDb = {}
+ albums.refresh().done (albums) ->
+ $scope.albums.legnth = 0
+ albumsDb = {}
+ for album in albums
+ albumsDb[album.id] = album
+ $scope.albums.push album
+
+ $scope.selectAlbum = (album) ->
+ $scope.selectedAlbum = album
+ $scope.edit.album_id = if album then album.id else null
+ $scope.isDirty = true
+
+ $scope.setCover = (image, type) ->
+ delete $scope.edit.cover_id
+ delete $scope.edit.cover
+
+ if image == null
+ $scope.edit.remove_cover = true
+ else if type == 'file'
+ $scope.edit.cover = image
+ else if type == 'gallery'
+ $scope.edit.cover_id = image.id
+
+ $scope.isDirty = true
+
+ updateSongDisplay = () ->
+ if _.size $scope.selectedSongs
+ $scope.selectedSongsTitle = (_.map _.values($scope.selectedSongs), (s) -> s.title).join(', ')
+ else
+ $scope.selectedSongsTitle = 'None'
+
+ $scope.toggleSong = (song) ->
+ $scope.isDirty = true
+ if $scope.selectedSongs[song.id]
+ delete $scope.selectedSongs[song.id]
+ else
+ $scope.selectedSongs[song.id] = song
+
+ updateSongDisplay()
+
+ $scope.updateIsVocal = () ->
+ delete $scope.errors.lyrics if !$scope.edit.is_vocal
+
+ $scope.updateTrack = () ->
+ xhr = new XMLHttpRequest()
+ xhr.onload = -> $scope.$apply ->
+ $scope.isSaving = false
+ if xhr.status != 200
+ errors =
+ if xhr.getResponseHeader('content-type') == 'application/json'
+ $.parseJSON(xhr.responseText).errors
+ else
+ ['There was an unknown error!']
+
+ $scope.errors = {}
+ _.each errors, (value, key) -> $scope.errors[key] = value.join ', '
+ return
+
+ track = $.parseJSON(xhr.responseText)
+
+ trackDbItem = $scope.data.selectedTrack
+ trackDbItem.title = $scope.edit.title
+ trackDbItem.is_explicit = $scope.edit.is_explicit
+ trackDbItem.is_vocal = $scope.edit.is_vocal
+ trackDbItem.genre_id = $scope.edit.genre_id
+ trackDbItem.is_published = true
+ trackDbItem.cover_url = track.real_cover_url
+ $scope.isDirty = false
+ $scope.errors = {}
+
+ formData = new FormData();
+ _.each $scope.edit, (value, name) ->
+ if name == 'cover'
+ return if value == null
+ if typeof(value) == 'object'
+ formData.append name, value, value.name
+ else
+ formData.append name, value
+
+ if $scope.edit.track_type_id == 2
+ formData.append 'show_song_ids', _.map(_.values($scope.selectedSongs), (s) -> s.id).join()
+
+ xhr.open 'POST', '/api/web/tracks/edit/' + $scope.edit.id, true
+ xhr.setRequestHeader 'X-Token', pfm.token
+ $scope.isSaving = true
+ xhr.send formData
+
+ tracks.getEdit($state.params.track_id).done (track) ->
+ $scope.edit =
+ id: track.id
+ title: track.title
+ description: track.description
+ lyrics: track.lyrics
+ is_explicit: track.is_explicit
+ is_downloadable: track.is_downloadable
+ is_vocal: track.is_vocal
+ license_id: track.license_id
+ genre_id: track.genre_id
+ track_type_id: track.track_type_id
+ released_at: if track.released_at then track.released_at.date else ''
+ remove_cover: false
+ cover: track.cover_url
+ album_id: track.album_id
+ is_published: track.is_published
+
+ $scope.selectedAlbum = if track.album_id then albumsDb[track.album_id] else null
+ $scope.selectedSongs = {}
+ $scope.selectedSongs[song.id] = song for song in track.show_songs
+ updateSongDisplay()
+
+ $scope.touchModel = -> $scope.isDirty = true
+
+ $scope.deleteTrack = (track) ->
+ $dialog.messageBox('Delete ' + track.title, 'Are you sure you want to delete "' + track.title + '"? This cannot be undone.', [
+ {result: 'ok', label: 'Yes', cssClass: 'btn-danger'}, {result: 'cancel', label: 'No', cssClass: 'btn-primary'}
+ ]).open().then (res) ->
+ return if res == 'cancel'
+ $.post('/api/web/tracks/delete/' + track.id, {_token: window.pfm.token})
+ .then -> $scope.$apply ->
+ $scope.$emit 'track-deleted'
+ $state.transitionTo 'account-content.tracks'
+
+ window.onbeforeunload = ->
+ return if !$scope.isDirty
+ "Are you sure you want to leave this page without saving your changes?"
+
+ $scope.$on '$locationChangeStart', (e) ->
+ return if !$scope.isDirty
+ e.preventDefault() if !confirm('Are you sure you want to leave this page without saving your changes?')
+]
\ No newline at end of file
diff --git a/public/scripts/app/controllers/account-tracks.coffee b/public/scripts/app/controllers/account-tracks.coffee
index da9c43d7..369b00cd 100644
--- a/public/scripts/app/controllers/account-tracks.coffee
+++ b/public/scripts/app/controllers/account-tracks.coffee
@@ -1,95 +1,30 @@
+window.pfm.preloaders['account-tracks'] = [
+ 'account-tracks', 'account-albums', 'taxonomies'
+ (tracks, albums, taxonomies) ->
+ $.when.all [tracks.refresh(null, true), albums.refresh(true), taxonomies.refresh()]
+]
+
angular.module('ponyfm').controller "account-tracks", [
- '$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
- ($scope, $state, taxonomies, $dialog, lightbox) ->
- $scope.selectedTrack = null
- $scope.isDirty = false
- $scope.isSaving = false
- $scope.taxonomies = taxonomies
- $scope.selectedSongsTitle = 'None'
- $scope.selectedSongs = {}
- $scope.albums = []
- $scope.selectedAlbum = null
+ '$scope', '$state', 'taxonomies', '$dialog', 'lightbox', 'account-albums', 'account-tracks'
+ ($scope, $state, taxonomies, $dialog, lightbox, albums, tracks) ->
+ $scope.data =
+ selectedTrack: null
+
+ $scope.tracks = []
tracksDb = {}
- albumsDb = {}
- $scope.selectAlbum = (album) ->
- $scope.selectedAlbum = album
- $scope.edit.album_id = if album then album.id else null
- $scope.isDirty = true
+ setTracks = (tracks) ->
+ $scope.tracks.length = 0
+ tracksDb = {}
+ for track in tracks
+ tracksDb[track.id] = track
+ $scope.tracks.push track
- $scope.setCover = (image, type) ->
- delete $scope.edit.cover_id
- delete $scope.edit.cover
+ if $state.params.track_id
+ $scope.data.selectedTrack = tracksDb[$state.params.track_id]
- if image == null
- $scope.edit.remove_cover = true
- else if type == 'file'
- $scope.edit.cover = image
- else if type == 'gallery'
- $scope.edit.cover_id = image.id
-
- $scope.isDirty = true
-
- refreshAlbums = () ->
- $.getJSON('/api/web/albums/owned')
- .done (albums) -> $scope.$apply ->
- albumsDb[album.id] = album for album in albums
- $scope.albums = albums
- $scope.selectedAlbum = if $scope.edit && $scope.edit.album_id then albumsDb[$scope.edit.album_id] else null
-
- updateSongDisplay = () ->
- if _.size $scope.selectedSongs
- $scope.selectedSongsTitle = (_.map _.values($scope.selectedSongs), (s) -> s.title).join(', ')
- else
- $scope.selectedSongsTitle = 'None'
-
- $scope.toggleSong = (song) ->
- $scope.isDirty = true
- if $scope.selectedSongs[song.id]
- delete $scope.selectedSongs[song.id]
- else
- $scope.selectedSongs[song.id] = song
-
- updateSongDisplay()
-
- $scope.updateIsVocal = () ->
- delete $scope.errors.lyrics if !$scope.edit.is_vocal
-
- $scope.updateTrack = (track) ->
- xhr = new XMLHttpRequest()
- xhr.onload = -> $scope.$apply ->
- $scope.isSaving = false
- if xhr.status != 200
- errors =
- if xhr.getResponseHeader('content-type') == 'application/json'
- $.parseJSON(xhr.responseText).errors
- else
- ['There was an unknown error!']
-
- $scope.errors = {}
- _.each errors, (value, key) -> $scope.errors[key] = value.join ', '
- return
-
- $scope.selectedTrack.is_published = true
- selectTrack $scope.selectedTrack
-
- formData = new FormData();
- _.each $scope.edit, (value, name) ->
- if name == 'cover'
- return if value == null
- if typeof(value) == 'object'
- formData.append name, value, value.name
- else
- formData.append name, value
-
- if $scope.edit.track_type_id == 2
- formData.append 'show_song_ids', _.map(_.values($scope.selectedSongs), (s) -> s.id).join()
-
- xhr.open 'POST', '/api/web/tracks/edit/' + $scope.edit.id, true
- xhr.setRequestHeader 'X-Token', pfm.token
- $scope.isSaving = true
- xhr.send formData
+ tracks.refresh().done setTracks
$scope.filters =
published: [
@@ -114,17 +49,17 @@ angular.module('ponyfm').controller "account-tracks", [
genres: 'All'
trackTypes: 'All'
- taxonomies.refresh().done () ->
- 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
+ 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
@@ -151,76 +86,18 @@ angular.module('ponyfm').controller "account-tracks", [
_.each $scope.filter.genres, (g) -> parts.push g.query
_.each $scope.filter.trackTypes, (g) -> parts.push g.query
query = parts.join '&'
- $.getJSON('/api/web/tracks/owned?' + query).done (tracks) -> $scope.$apply -> showTracks tracks
+ tracks.refresh(query).done setTracks
- showTracks = (tracks) ->
- tracksDb = {}
- $scope.tracks = tracks
- tracksDb[track.id] = track for track in tracks
-
- selectTrack = (t) ->
- $scope.selectedTrack = t
- return if !t
- $.getJSON('/api/web/tracks/edit/' + t.id)
- .done (track) -> $scope.$apply ->
- $scope.isDirty = false
- $scope.errors = {}
- $scope.edit =
- id: track.id
- title: track.title
- description: track.description
- lyrics: track.lyrics
- is_explicit: track.is_explicit
- is_downloadable: track.is_downloadable
- is_vocal: track.is_vocal
- license_id: track.license_id
- genre_id: track.genre_id
- track_type_id: track.track_type_id
- released_at: if track.released_at then track.released_at.date else ''
- remove_cover: false
- cover: track.cover_url
- album_id: track.album_id
-
- trackDbItem = tracksDb[t.id]
- trackDbItem.title = track.title
- trackDbItem.is_explicit = track.is_explicit
- trackDbItem.is_vocal = track.is_vocal
- trackDbItem.genre_id = track.genre_id
- trackDbItem.is_published = track.is_published
- trackDbItem.cover_url = track.real_cover_url
-
- $scope.selectedAlbum = if track.album_id then albumsDb[track.album_id] else null
- $scope.selectedSongs = {}
- $scope.selectedSongs[song.id] = song for song in track.show_songs
- updateSongDisplay()
-
- $scope.touchModel = -> $scope.isDirty = true
-
- $.getJSON('/api/web/tracks/owned?order=created_at,desc').done (tracks) -> $scope.$apply ->
- showTracks tracks
- if $state.params.track_id
- selectTrack tracksDb[$state.params.track_id]
-
- $scope.selectTrack = (track) -> $scope.selectedTrack = track
- $scope.deleteTrack = (track) ->
- $dialog.messageBox('Delete ' + track.title, 'Are you sure you want to delete "' + track.title + '"? This cannot be undone.', [
- {result: 'ok', label: 'Yes', cssClass: 'btn-danger'}, {result: 'cancel', label: 'No', cssClass: 'btn-primary'}
- ]).open().then (res) ->
- return if res == 'cancel'
- selectTrack null if track == $scope.selectedTrack
- $.post('/api/web/tracks/delete/' + track.id, {_token: window.pfm.token})
- .then ->
- $scope.refreshList()
+ $scope.selectTrack = (track) ->
+ $scope.data.selectedTrack = track
$scope.$on '$stateChangeSuccess', () ->
if $state.params.track_id
- selectTrack tracksDb[$state.params.track_id]
+ $scope.selectTrack tracksDb[$state.params.track_id]
else
- selectTrack null
+ $scope.selectTrack null
- $scope.$on '$stateChangeStart', (e) ->
- return if $scope.selectedTrack == null || !$scope.isDirty
- e.preventDefault() if !confirm('Are you sure you want to leave this page without saving your changes?')
-
- refreshAlbums()
+ $scope.$on 'track-deleted', () ->
+ tracks.clearCache()
+ $scope.refreshList()
]
\ No newline at end of file
diff --git a/public/scripts/app/controllers/application.coffee b/public/scripts/app/controllers/application.coffee
index 4d01a80d..e3f5a43f 100644
--- a/public/scripts/app/controllers/application.coffee
+++ b/public/scripts/app/controllers/application.coffee
@@ -1,52 +1,51 @@
angular.module('ponyfm').controller "application", [
- '$scope', 'auth', '$location', 'upload', '$state', '$stateParams', 'taxonomies'
- ($scope, auth, $location, upload, $state, $stateParams, taxonomies) ->
+ '$scope', 'auth', '$location', 'upload', '$state', '$stateParams', '$injector'
+ ($scope, auth, $location, upload, $state, $stateParams, $injector) ->
$scope.auth = auth.data
$scope.$state = $state
$scope.$stateParams = $stateParams
+ $loadingElement = null
$scope.logout = () ->
auth.logout().done -> location.reload()
$scope.isActive = (loc) -> $location.path() == loc
$scope.$on '$viewContentLoaded', () ->
- window.setTimeout window.handleResize, 500
+ window.handleResize()
- # Show loading screen here?
- taxonomies.refresh()
-
- $scope.mainViewAnimation = 'slide-down';
+ if $loadingElement
+ $loadingElement.removeClass 'loading'
+ $loadingElement = null
+ statesPreloaded = {}
$scope.$on '$stateChangeStart', (e, newState, newParams, oldState) ->
- oldIndex =
- if (oldState && oldState.navigation && oldState.navigation.index)
- oldState.navigation.index
- else
- 0
+ return if !oldState || !newState.controller
- newIndex =
- if (newState && newState.navigation && newState.navigation.index)
- newState.navigation.index
- else
- 0
+ preloader = window.pfm.preloaders[newState.controller]
+ return if !preloader
- oldSubIndex =
- if (oldState && oldState.navigation && oldState.navigation.subIndex)
- oldState.navigation.subIndex
- else
- 0
+ if statesPreloaded[newState]
+ delete statesPreloaded[newState]
+ return
- newSubIndex =
- if (newState && newState.navigation && newState.navigation.subIndex)
- newState.navigation.subIndex
- else
- 0
+ e.preventDefault()
- $scope.mainViewAnimation = 'slide-down' if oldIndex > newIndex
- $scope.mainViewAnimation = 'slide-up' if oldIndex < newIndex
- $scope.mainViewAnimation = 'slide-right' if oldIndex == newIndex
+ selector = ''
+ newParts = newState.name.split '.'
+ oldParts = oldState.name.split '.'
+ zipped = _.zip(newParts, oldParts)
+ for i in [0..zipped.length]
+ break if !zipped[i] || zipped[i][0] != zipped[i][1]
+ selector += ' ui-view '
- $scope.subViewAnimation = 'slide-right' if oldSubIndex > newSubIndex
- $scope.subViewAnimation = 'slide-left' if oldSubIndex < newSubIndex
- $scope.subViewAnimation = 'slide-up' if oldSubIndex == newSubIndex
+ selector += ' ui-view ' if newState.name != oldState.name
+
+ $loadingElement = $ selector
+ $loadingElement.addClass 'loading'
+
+ stateToInject = angular.copy newState
+ stateToInject.params = newParams
+ $injector.invoke(preloader, null, {$state: stateToInject}).then ->
+ statesPreloaded[newState] = true
+ $state.transitionTo newState, newParams
]
\ No newline at end of file
diff --git a/public/scripts/app/directives/popup.coffee b/public/scripts/app/directives/popup.coffee
index f8ba3251..3a59cb6c 100644
--- a/public/scripts/app/directives/popup.coffee
+++ b/public/scripts/app/directives/popup.coffee
@@ -12,9 +12,6 @@ angular.module('ponyfm').directive 'pfmPopup', () ->
$positionParent = null
open = false
- $popup.parents().each () ->
- $this = $ this
- $positionParent = $this if $positionParent == null && ($this.css('position') == 'relative' || $this.is 'body')
documentClickHandler = () ->
return if !open
@@ -22,6 +19,10 @@ angular.module('ponyfm').directive 'pfmPopup', () ->
open = false
calculatePosition = ->
+ $popup.parents().each () ->
+ $this = $ this
+ $positionParent = $this if $positionParent == null && ($this.css('position') == 'relative' || $this.is 'body')
+
position = $element.offset()
parentPosition = $positionParent.offset()
@@ -42,7 +43,7 @@ angular.module('ponyfm').directive 'pfmPopup', () ->
height = windowHeight - top;
return {
- left: left - parentPosition.left - 2
+ left: left - parentPosition.left - 5
top: top - parentPosition.top,
height: height - 15}
@@ -70,13 +71,15 @@ angular.module('ponyfm').directive 'pfmPopup', () ->
$popup.addClass 'open'
$popup.css 'height', 'auto'
- position = calculatePosition()
- $popup.css
- left: position.left
- top: position.top
- height: position.height
+ window.setTimeout (->
+ position = calculatePosition()
+ $popup.css
+ left: position.left
+ top: position.top
+ height: position.height
- open = true
+ open = true
+ ), 0
scope.$on '$destroy', () ->
$(document.body).unbind 'click', documentClickHandler
diff --git a/public/scripts/app/services/account-albums.coffee b/public/scripts/app/services/account-albums.coffee
new file mode 100644
index 00000000..6a381458
--- /dev/null
+++ b/public/scripts/app/services/account-albums.coffee
@@ -0,0 +1,27 @@
+angular.module('ponyfm').factory('account-albums', [
+ '$rootScope', '$http'
+ ($rootScope, $http) ->
+ def = null
+ albums = []
+
+ self =
+ getEdit: (id, force) ->
+ url = '/api/web/albums/edit/' + id
+ force = force || false
+ return albums[id] if !force && albums[id]
+
+ editDef = new $.Deferred()
+ albums[id] = editDef
+ $http.get(url).success (album) -> editDef.resolve album
+ editDef.promise()
+
+ refresh: (force) ->
+ force = force || false
+ return def if !force && def
+ def = new $.Deferred()
+ $http.get('/api/web/albums/owned').success (ownedAlbums) ->
+ def.resolve(ownedAlbums)
+ def.promise()
+
+ self
+])
\ No newline at end of file
diff --git a/public/scripts/app/services/account-tracks.coffee b/public/scripts/app/services/account-tracks.coffee
new file mode 100644
index 00000000..7f4dc51f
--- /dev/null
+++ b/public/scripts/app/services/account-tracks.coffee
@@ -0,0 +1,31 @@
+angular.module('ponyfm').factory('account-tracks', [
+ '$rootScope', '$http'
+ ($rootScope, $http) ->
+ cache = {}
+
+ self =
+ clearCache: () -> cache = {}
+
+ getEdit: (id, force) ->
+ url = '/api/web/tracks/edit/' + id
+ force = force || false
+ return cache[url] if !force && cache[url]
+
+ def = new $.Deferred()
+ cache[url] = def
+ $http.get(url).success (track) -> def.resolve track
+ def.promise()
+
+ refresh: (query, force) ->
+ query = query || 'created_at,desc'
+ url = '/api/web/tracks/owned?' + query
+ force = force || false
+ return cache[url] if !force && cache[url]
+
+ def = new $.Deferred()
+ cache[url] = def
+ $http.get(url).success (tracks) -> def.resolve tracks
+ def.promise()
+
+ self
+])
\ No newline at end of file
diff --git a/public/scripts/app/services/playlists.coffee b/public/scripts/app/services/playlists.coffee
index 13ed0dc2..bf1b1529 100644
--- a/public/scripts/app/services/playlists.coffee
+++ b/public/scripts/app/services/playlists.coffee
@@ -1,8 +1,20 @@
angular.module('ponyfm').factory('playlists', [
- '$rootScope', '$state'
- ($rootScope, $state) ->
+ '$rootScope', '$state', '$http'
+ ($rootScope, $state, $http) ->
+ playlistDef = null
+
self =
pinnedPlaylists: []
+ refreshOwned: (force) ->
+ force = force || false
+ return playlistDef if !force && playlistDef
+
+ playlistDef = new $.Deferred()
+ $http.get('/api/web/playlists/owned').success (playlists) ->
+ playlistDef.resolve playlists
+
+ playlistDef
+
refresh: () ->
$.getJSON('/api/web/playlists/pinned')
.done (playlists) -> $rootScope.$apply ->
diff --git a/public/scripts/app/services/taxonomies.coffee b/public/scripts/app/services/taxonomies.coffee
index a1b152b2..d7b0f861 100644
--- a/public/scripts/app/services/taxonomies.coffee
+++ b/public/scripts/app/services/taxonomies.coffee
@@ -1,6 +1,6 @@
angular.module('ponyfm').factory('taxonomies', [
- '$rootScope'
- ($rootScope) ->
+ '$rootScope', '$http'
+ ($rootScope, $http) ->
def = null
self =
@@ -9,17 +9,18 @@ angular.module('ponyfm').factory('taxonomies', [
genres: []
showSongs: []
refresh: () ->
- return def if def != null
+ return def.promise() if def != null
def = new $.Deferred()
- $.getJSON('/api/web/taxonomies/all')
- .done (taxonomies) -> $rootScope.$apply ->
+ $http.get('/api/web/taxonomies/all')
+ .success (taxonomies) ->
self.trackTypes.push t for t in taxonomies.track_types
self.licenses.push t for t in taxonomies.licenses
self.genres.push t for t in taxonomies.genres
self.showSongs.push t for t in taxonomies.show_songs
def.resolve self
- def
+
+ def.promise()
self
])
\ No newline at end of file
diff --git a/public/scripts/shared/jquery-extensions.js b/public/scripts/shared/jquery-extensions.js
new file mode 100644
index 00000000..2c9d91b3
--- /dev/null
+++ b/public/scripts/shared/jquery-extensions.js
@@ -0,0 +1,14 @@
+if (jQuery.when.all===undefined) {
+ jQuery.when.all = function(deferreds) {
+ var deferred = new jQuery.Deferred();
+ $.when.apply(jQuery, deferreds).then(
+ function() {
+ deferred.resolve(Array.prototype.slice.call(arguments));
+ },
+ function() {
+ deferred.fail(Array.prototype.slice.call(arguments));
+ });
+
+ return deferred;
+ }
+}
\ No newline at end of file
diff --git a/public/scripts/shared/layout.coffee b/public/scripts/shared/layout.coffee
index 9a3893c0..9f58acc4 100644
--- a/public/scripts/shared/layout.coffee
+++ b/public/scripts/shared/layout.coffee
@@ -2,18 +2,13 @@ window.handleResize = () ->
windowHeight = $(window).height()
$siteBody = $ '.site-body'
$siteBody.height windowHeight - $('header').height() - 1
- redo = false
$('.stretch-to-bottom').each () ->
$this = $ this
newHeight = windowHeight - $this.offset().top + 1
- if newHeight <= 0
- redo = true
- else
+ if newHeight > 0
$this.height newHeight
- window.setTimeout(window.handleResize, 0) if redo
-
window.alignVertically = (element) ->
$element = $(element)
$parent = $element.parent()
diff --git a/public/styles/layout.less b/public/styles/layout.less
index e70592fd..84455451 100644
--- a/public/styles/layout.less
+++ b/public/styles/layout.less
@@ -21,6 +21,36 @@ html body {
z-index: -5;
}
+ui-view {
+ display: block;
+
+ &:before {
+ .transition(opacity 250ms);
+
+ opacity: 0;
+ background: #fff;
+ content: ' ';
+ top: 0px;
+ left: 0px;
+ z-index: 1000;
+ width: 0px;
+ height: 0px;
+ position: absolute;
+ display: block;
+ overflow: hidden;
+ }
+
+ &.loading {
+ position: relative;
+
+ &:before {
+ opacity: .8;
+ width: 100%;
+ height: 100%;
+ }
+ }
+}
+
header {
.clearfix();
background: #222;
diff --git a/public/templates/account/content/_layout.html b/public/templates/account/content/_layout.html
index a17c8514..e8ee9ddc 100644
--- a/public/templates/account/content/_layout.html
+++ b/public/templates/account/content/_layout.html
@@ -4,5 +4,5 @@
Albums
-
+
\ No newline at end of file
diff --git a/public/templates/account/content/albums.html b/public/templates/account/content/albums.html
index d6e3480a..67f36c21 100644
--- a/public/templates/account/content/albums.html
+++ b/public/templates/account/content/albums.html
@@ -23,7 +23,6 @@
-
-
+
\ No newline at end of file
diff --git a/public/templates/account/content/track.html b/public/templates/account/content/track.html
new file mode 100644
index 00000000..0ecdde92
--- /dev/null
+++ b/public/templates/account/content/track.html
@@ -0,0 +1,116 @@
+
\ No newline at end of file
diff --git a/public/templates/account/content/tracks.html b/public/templates/account/content/tracks.html
index 708e1fe5..73f11e1b 100644
--- a/public/templates/account/content/tracks.html
+++ b/public/templates/account/content/tracks.html
@@ -25,7 +25,7 @@
Type: {{titles.trackTypes}}
@@ -35,18 +35,18 @@
Genera: {{titles.genres}}
-
\ No newline at end of file