mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2024-11-21 20:48:00 +01:00
Fixed album/track controllers
This commit is contained in:
parent
d9d44f9e6e
commit
d4789ebda3
22 changed files with 569 additions and 486 deletions
|
@ -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)]);
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -88,9 +88,9 @@
|
|||
</ul>
|
||||
</nav>
|
||||
</section>
|
||||
<section ui-view class="site-content">
|
||||
<ui-view class="site-content">
|
||||
@yield('app_content')
|
||||
</section>
|
||||
</ui-view>
|
||||
</div>
|
||||
|
||||
<ng-include src="'templates/partials/upload-dialog.html'" />
|
||||
|
|
|
@ -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 '/'
|
||||
|
||||
|
|
|
@ -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?')
|
||||
]
|
|
@ -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
|
||||
]
|
|
@ -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();
|
||||
]
|
148
public/scripts/app/controllers/account-tracks-edit.coffee
Normal file
148
public/scripts/app/controllers/account-tracks-edit.coffee
Normal file
|
@ -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?')
|
||||
]
|
|
@ -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()
|
||||
]
|
|
@ -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
|
||||
]
|
|
@ -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
|
||||
|
|
27
public/scripts/app/services/account-albums.coffee
Normal file
27
public/scripts/app/services/account-albums.coffee
Normal file
|
@ -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
|
||||
])
|
31
public/scripts/app/services/account-tracks.coffee
Normal file
31
public/scripts/app/services/account-tracks.coffee
Normal file
|
@ -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
|
||||
])
|
|
@ -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 ->
|
||||
|
|
|
@ -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
|
||||
])
|
14
public/scripts/shared/jquery-extensions.js
vendored
Normal file
14
public/scripts/shared/jquery-extensions.js
vendored
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
<li ng-class="{active: $state.includes('account-content.albums')}"><a href="/account/albums">Albums</a></li>
|
||||
</ul>
|
||||
|
||||
<div ui-view class="inner-view"></div>
|
||||
<ui-view></ui-view>
|
||||
</div>
|
|
@ -23,7 +23,6 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="editor" ui-view>
|
||||
</div>
|
||||
<ui-view class="editor"></ui-view>
|
||||
</div>
|
||||
</div>
|
116
public/templates/account/content/track.html
Normal file
116
public/templates/account/content/track.html
Normal file
|
@ -0,0 +1,116 @@
|
|||
<form novalidate ng-submit="updateTrack(edit)">
|
||||
<ul class="toolbar">
|
||||
<li>
|
||||
<button type="submit" class="btn" ng-class="{disabled: (data.selectedTrack.is_published && !isDirty) || isSaving, 'btn-primary': !data.selectedTrack.is_published || isDirty}">
|
||||
<span ng-show="edit.is_published">
|
||||
Save Changes
|
||||
</span>
|
||||
<span ng-hide="edit.is_published">
|
||||
Publish Track
|
||||
</span>
|
||||
<i ng-show="isSaving" class="icon-cog icon-spin icon-large"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li class="delete"><a ng-class="{disabled: isSaving}" class="btn btn-danger" href="#" ng-click="deleteTrack(data.selectedTrack)" pfm-eat-click>Delete Track</a></li>
|
||||
</ul>
|
||||
<div class="stretch-to-bottom">
|
||||
<div class="form-row" ng-class="{'has-error': errors.title != null}">
|
||||
<label for="title" class="strong">Title:</label>
|
||||
<input ng-disabled="isSaving" ng-change="touchModel()" placeholder="Track Title" type="text" id="title" ng-model="edit.title" />
|
||||
<div class="error">{{errors.title}}</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span6 form-row" ng-class="{'has-error': errors.description != null}">
|
||||
<label for="description" class="strong">Description:</label>
|
||||
<textarea ng-disabled="isSaving" ng-change="touchModel()" placeholder="Description (optional)" id="description" ng-model="edit.description"></textarea>
|
||||
<div class="error">{{errors.description}}</div>
|
||||
</div>
|
||||
<div class="span6 form-row" ng-class="{'has-error': errors.lyrics != null}">
|
||||
<label for="is_vocal" class="strong"><input ng-disabled="isSaving" ng-change="touchModel(); updateIsVocal()" id="is_vocal" type="checkbox" ng-model="edit.is_vocal" /> Is Vocal</label>
|
||||
<textarea ng-disabled="isSaving" ng-change="touchModel()" ng-show="edit.is_vocal" ng-animate="'fade'" placeholder="Lyrics (required)" id="lyrics" ng-model="edit.lyrics"></textarea>
|
||||
<div class="error">{{errors.lyrics}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="form-row span6" ng-class="{'has-error': errors.genre_id != null}">
|
||||
<label for="genre" class="strong">Genre:</label>
|
||||
<select ng-disabled="isSaving" id="genre" ng-change="touchModel()" ng-model="edit.genre_id" ng-options="genre.id as genre.name for genre in taxonomies.genres">
|
||||
<option value="">Please select a genre...</option>
|
||||
</select>
|
||||
<div class="error">{{errors.genre_id}}</div>
|
||||
</div>
|
||||
<div class="form-row span6" ng-class="{'has-error': errors.track_type_id != null}">
|
||||
<label for="track_type" class="strong">This track is...</label>
|
||||
<select ng-disabled="isSaving" id="track_type" ng-change="touchModel()" ng-model="edit.track_type_id" ng-options="type.id as type.editor_title for type in taxonomies.trackTypes">
|
||||
<option value="">Please select a type...</option>
|
||||
</select>
|
||||
<div class="error">{{errors.track_type_id}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="form-row album span6" ng-class="{'has-error': errors.show_song_ids != null}">
|
||||
<a pfm-popup="album-selector" href="#" class="btn btn-small">
|
||||
Album:
|
||||
<strong ng-show="selectedAlbum">{{selectedAlbum.title}}</strong>
|
||||
<strong ng-hide="selectedAlbum">None</strong>
|
||||
</a>
|
||||
<div id="album-selector" class="pfm-popup">
|
||||
<ul>
|
||||
<li ng-class="{selected: selectedAlbum == null}">
|
||||
<a pfm-eat-click href="#" ng-click="selectAlbum(null);">None</a>
|
||||
</li>
|
||||
<li ng-repeat="album in albums" ng-class="{selected: selectedAlbum.id == album.id}">
|
||||
<a pfm-eat-click href="#" ng-click="selectAlbum(album);">{{album.title}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="error">{{errors.album_id}}</div>
|
||||
</div>
|
||||
<div class="form-row show-songs span6" ng-show="edit.track_type_id == 2" ng-class="{'has-error': errors.show_song_ids != null}">
|
||||
<a pfm-popup="song-selector" href="#" class="btn btn-small">Show Songs: <strong>{{selectedSongsTitle}}</strong></a>
|
||||
<div id="song-selector" class="pfm-popup">
|
||||
<ul>
|
||||
<li ng-repeat="song in taxonomies.showSongs" ng-class="{selected: selectedSongs[song.id]}">
|
||||
<a pfm-eat-click href="#" ng-click="toggleSong(song); $event.stopPropagation();">{{song.title}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="error">{{errors.show_song_ids}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="form-row span6" ng-class="{'has-error': errors.cover != null}">
|
||||
<label class="strong">Track Cover: </label>
|
||||
<pfm-image-upload set-image="setCover" image="edit.cover" />
|
||||
</div>
|
||||
<div class="form-row span6">
|
||||
<label for="released_at" class="strong">Release Date:</label>
|
||||
<input ng-disabled="isSaving" type="text" id="released_at" ui-date ng-model="edit.released_at" ng-change="touchModel()" ui-date-format="yy-mm-dd" />
|
||||
<div class="error">{{errors.released_at}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span6 form-row">
|
||||
<label for="is_explicit"><input ng-disabled="isSaving" ng-change="touchModel()" id="is_explicit" type="checkbox" ng-model="edit.is_explicit" /> Contains Explicit Content</label>
|
||||
</div>
|
||||
<div class="span6 form-row">
|
||||
<label for="is_downloadable"><input ng-disabled="isSaving" ng-change="touchModel()" id="is_downloadable" type="checkbox" ng-model="edit.is_downloadable" /> Is Downloadable</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label class="strong">Choose a License:</label>
|
||||
<ul class="license-grid">
|
||||
<li ng-repeat="license in taxonomies.licenses" ng-class="{selected: edit.license_id == license.id}">
|
||||
<div ng-click="edit.license_id = license.id; touchModel()">
|
||||
<strong>{{license.title}}</strong>
|
||||
<p>{{license.description}}</p>
|
||||
<a href="#" pfm-eat-click class="btn" ng-class="{'btn-primary': edit.license_id == license.id, 'disabled': isSaving}">
|
||||
<span ng-hide="edit.license_id == license.id">Select</span>
|
||||
<span ng-show="edit.license_id == license.id">Selected</span>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
|
@ -25,7 +25,7 @@
|
|||
Type: <strong>{{titles.trackTypes}}</strong>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-repeat="type in taxonomies.trackTypes" ng-class="{selected: filter.trackTypes[type.id]}">
|
||||
<li ng-repeat="type in filters.trackTypes" ng-class="{selected: filter.trackTypes[type.id]}">
|
||||
<a pfm-eat-click href="#" ng-click="toggleFilter('trackTypes', type.id); $event.stopPropagation();">{{type.title}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -35,18 +35,18 @@
|
|||
Genera: <strong>{{titles.genres}}</strong>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li ng-repeat="genre in taxonomies.genres" ng-class="{selected: filter.genres[genre.id]}">
|
||||
<a pfm-eat-click href="#" ng-click="toggleFilter('genres', genre.id); $event.stopPropagation();">{{genre.name}}</a>
|
||||
<li ng-repeat="genre in filters.genres" ng-class="{selected: filter.genres[genre.id]}">
|
||||
<a pfm-eat-click href="#" ng-click="toggleFilter('genres', genre.id); $event.stopPropagation();">{{genre.title}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="two-pane-view" ng-class="{open: selectedTrack != null, closed: selectedTrack == null}">
|
||||
<div class="two-pane-view" ng-class="{open: data.selectedTrack != null, closed: data.selectedTrack == null}">
|
||||
<div class="list">
|
||||
<ul class="account-tracks-listing stretch-to-bottom">
|
||||
<li ng-repeat="track in tracks" ng-class="{selected: track.id == selectedTrack.id, 'is-not-published': !track.is_published}">
|
||||
<a href="/account/tracks/edit/{{track.id}}">
|
||||
<li ng-repeat="track in tracks" ng-class="{selected: track.id == data.selectedTrack.id, 'is-not-published': !track.is_published}">
|
||||
<a href="/account/tracks/edit/{{track.id}}" ng-click="selectTrack(track)">
|
||||
<img class="image" ng-src="{{track.cover_url}}" />
|
||||
<span class="title">{{track.title}}</span>
|
||||
<span class="published">{{track.created_at | pfmdate:'MM/dd/yyyy'}}</span>
|
||||
|
@ -55,124 +55,6 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="editor">
|
||||
<form novalidate ng-submit="updateTrack(edit)">
|
||||
<ul class="toolbar">
|
||||
<li>
|
||||
<button type="submit" class="btn" ng-class="{disabled: (selectedTrack.is_published && !isDirty) || isSaving, 'btn-primary': !selectedTrack.is_published || isDirty}">
|
||||
<span ng-show="selectedTrack.is_published">
|
||||
Save Changes
|
||||
</span>
|
||||
<span ng-hide="selectedTrack.is_published">
|
||||
Publish Track
|
||||
</span>
|
||||
|
||||
<i ng-show="isSaving" class="icon-cog icon-spin icon-large"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li class="delete"><a ng-class="{disabled: isSaving}" class="btn btn-danger" href="#" ng-click="deleteTrack(selectedTrack)" pfm-eat-click>Delete Track</a></li>
|
||||
</ul>
|
||||
<div class="stretch-to-bottom">
|
||||
<div class="form-row" ng-class="{'has-error': errors.title != null}">
|
||||
<label for="title" class="strong">Title:</label>
|
||||
<input ng-disabled="isSaving" ng-change="touchModel()" placeholder="Track Title" type="text" id="title" ng-model="edit.title" />
|
||||
<div class="error">{{errors.title}}</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span6 form-row" ng-class="{'has-error': errors.description != null}">
|
||||
<label for="description" class="strong">Description:</label>
|
||||
<textarea ng-disabled="isSaving" ng-change="touchModel()" placeholder="Description (optional)" id="description" ng-model="edit.description"></textarea>
|
||||
<div class="error">{{errors.description}}</div>
|
||||
</div>
|
||||
<div class="span6 form-row" ng-class="{'has-error': errors.lyrics != null}">
|
||||
<label for="is_vocal" class="strong"><input ng-disabled="isSaving" ng-change="touchModel(); updateIsVocal()" id="is_vocal" type="checkbox" ng-model="edit.is_vocal" /> Is Vocal</label>
|
||||
<textarea ng-disabled="isSaving" ng-change="touchModel()" ng-show="edit.is_vocal" ng-animate="'fade'" placeholder="Lyrics (required)" id="lyrics" ng-model="edit.lyrics"></textarea>
|
||||
<div class="error">{{errors.lyrics}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="form-row span6" ng-class="{'has-error': errors.genre_id != null}">
|
||||
<label for="genre" class="strong">Genre:</label>
|
||||
<select ng-disabled="isSaving" id="genre" ng-change="touchModel()" ng-model="edit.genre_id" ng-options="genre.id as genre.name for genre in taxonomies.genres">
|
||||
<option value="">Please select a genre...</option>
|
||||
</select>
|
||||
<div class="error">{{errors.genre_id}}</div>
|
||||
</div>
|
||||
<div class="form-row span6" ng-class="{'has-error': errors.track_type_id != null}">
|
||||
<label for="track_type" class="strong">This track is...</label>
|
||||
<select ng-disabled="isSaving" id="track_type" ng-change="touchModel()" ng-model="edit.track_type_id" ng-options="type.id as type.editor_title for type in taxonomies.trackTypes">
|
||||
<option value="">Please select a type...</option>
|
||||
</select>
|
||||
<div class="error">{{errors.track_type_id}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="form-row album span6" ng-class="{'has-error': errors.show_song_ids != null}">
|
||||
<a pfm-popup="album-selector" href="#" class="btn btn-small">
|
||||
Album:
|
||||
<strong ng-show="selectedAlbum">{{selectedAlbum.title}}</strong>
|
||||
<strong ng-hide="selectedAlbum">None</strong>
|
||||
</a>
|
||||
<div id="album-selector" class="pfm-popup">
|
||||
<ul>
|
||||
<li ng-class="{selected: selectedAlbum == null}">
|
||||
<a pfm-eat-click href="#" ng-click="selectAlbum(null);">None</a>
|
||||
</li>
|
||||
<li ng-repeat="album in albums" ng-class="{selected: selectedAlbum.id == album.id}">
|
||||
<a pfm-eat-click href="#" ng-click="selectAlbum(album);">{{album.title}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="error">{{errors.album_id}}</div>
|
||||
</div>
|
||||
<div class="form-row show-songs span6" ng-show="edit.track_type_id == 2" ng-class="{'has-error': errors.show_song_ids != null}">
|
||||
<a pfm-popup="song-selector" href="#" class="btn btn-small">Show Songs: <strong>{{selectedSongsTitle}}</strong></a>
|
||||
<div id="song-selector" class="pfm-popup">
|
||||
<ul>
|
||||
<li ng-repeat="song in taxonomies.showSongs" ng-class="{selected: selectedSongs[song.id]}">
|
||||
<a pfm-eat-click href="#" ng-click="toggleSong(song); $event.stopPropagation();">{{song.title}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="error">{{errors.show_song_ids}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="form-row span6" ng-class="{'has-error': errors.cover != null}">
|
||||
<label class="strong">Track Cover: </label>
|
||||
<pfm-image-upload set-image="setCover" image="edit.cover" />
|
||||
</div>
|
||||
<div class="form-row span6">
|
||||
<label for="released_at" class="strong">Release Date:</label>
|
||||
<input ng-disabled="isSaving" type="text" id="released_at" ui-date ng-model="edit.released_at" ng-change="touchModel()" ui-date-format="yy-mm-dd" />
|
||||
<div class="error">{{errors.released_at}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span6 form-row">
|
||||
<label for="is_explicit"><input ng-disabled="isSaving" ng-change="touchModel()" id="is_explicit" type="checkbox" ng-model="edit.is_explicit" /> Contains Explicit Content</label>
|
||||
</div>
|
||||
<div class="span6 form-row">
|
||||
<label for="is_downloadable"><input ng-disabled="isSaving" ng-change="touchModel()" id="is_downloadable" type="checkbox" ng-model="edit.is_downloadable" /> Is Downloadable</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label class="strong">Choose a License:</label>
|
||||
<ul class="license-grid">
|
||||
<li ng-repeat="license in taxonomies.licenses" ng-class="{selected: edit.license_id == license.id}">
|
||||
<div ng-click="edit.license_id = license.id; touchModel()">
|
||||
<strong>{{license.title}}</strong>
|
||||
<p>{{license.description}}</p>
|
||||
<a href="#" pfm-eat-click class="btn" ng-class="{'btn-primary': edit.license_id == license.id, 'disabled': isSaving}">
|
||||
<span ng-hide="edit.license_id == license.id">Select</span>
|
||||
<span ng-show="edit.license_id == license.id">Selected</span>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<ui-view class="editor"></ui-view>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in a new issue