mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2024-11-25 22:47:59 +01:00
Merge pull request #60 from Poniverse/feature/refactor-track-editor
Refactored the track editor for #2
This commit is contained in:
commit
4a18e4f132
7 changed files with 300 additions and 277 deletions
|
@ -1,120 +1 @@
|
||||||
<form novalidate ng-submit="updateTrack(edit)">
|
<pfm-track-editor track-id="trackId"></pfm-track-editor>
|
||||||
<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 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.album_id != null}">
|
|
||||||
<a pfm-popup="album-selector" pfm-popup-close-on-click 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" pfm-popup-close-on-click 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" ng-class="{'has-error': errors.released_at != null}">
|
|
||||||
<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="span4 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="span4 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 class="span4 form-row">
|
|
||||||
<label for="is_listed"><input ng-disabled="isSaving" ng-change="touchModel()" id="is_listed" type="checkbox" ng-model="edit.is_listed" /> Is Listed</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>
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="two-pane-view" ng-class="{open: data.selectedTrack != null, closed: data.selectedTrack == null}">
|
<div class="two-pane-view" ng-class="{open: data.selectedTrack != null, closed: data.selectedTrack == null}">
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<ul class="account-tracks-listing stretch-to-bottom">
|
<ul class="account-tracks-listing stretch-to-bottom">
|
||||||
<li ng-repeat="track in tracks" ng-class="{selected: track.id == data.selectedTrack.id, 'is-not-published': !track.is_published}">
|
<li ng-repeat="track in tracks track by track.id" 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)">
|
<a href="/account/tracks/edit/{{track.id}}" ng-click="selectTrack(track)">
|
||||||
<img class="image" ng-src="{{track.cover_url}}" />
|
<img class="image" ng-src="{{track.cover_url}}" />
|
||||||
<span class="title">{{track.title}}</span>
|
<span class="title">{{track.title}}</span>
|
||||||
|
|
120
public/templates/directives/track-editor.html
Normal file
120
public/templates/directives/track-editor.html
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
<form novalidate ng-submit="updateTrack(track)">
|
||||||
|
<ul class="toolbar">
|
||||||
|
<li>
|
||||||
|
<button type="submit" class="btn" ng-class="{disabled: (track.is_published && !isDirty) || isSaving, 'btn-primary': !track.is_published || isDirty}">
|
||||||
|
<span ng-show="track.is_published">
|
||||||
|
Save Changes
|
||||||
|
</span>
|
||||||
|
<span ng-hide="track.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()" 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="track.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="track.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="track.is_vocal" /> Is Vocal</label>
|
||||||
|
<textarea ng-disabled="isSaving" ng-change="touchModel()" ng-show="track.is_vocal" ng-animate="'fade'" placeholder="Lyrics (required)" id="lyrics" ng-model="track.lyrics"></textarea>
|
||||||
|
<div class="error">{{errors.lyrics}}</div>
|
||||||
|
<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="track.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="track.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.album_id != null}">
|
||||||
|
<a pfm-popup="album-selector" pfm-popup-close-on-click 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="track.track_type_id == 2" ng-class="{'has-error': errors.show_song_ids != null}">
|
||||||
|
<a pfm-popup="song-selector" pfm-popup-close-on-click 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="track.cover" />
|
||||||
|
</div>
|
||||||
|
<div class="form-row span6" ng-class="{'has-error': errors.released_at != null}">
|
||||||
|
<label for="released_at" class="strong">Release Date:</label>
|
||||||
|
<input ng-disabled="isSaving" type="text" id="released_at" ui-date ng-model="track.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="span4 form-row">
|
||||||
|
<label for="is_explicit"><input ng-disabled="isSaving" ng-change="touchModel()" id="is_explicit" type="checkbox" ng-model="track.is_explicit" /> Contains Explicit Content</label>
|
||||||
|
</div>
|
||||||
|
<div class="span4 form-row">
|
||||||
|
<label for="is_downloadable"><input ng-disabled="isSaving" ng-change="touchModel()" id="is_downloadable" type="checkbox" ng-model="track.is_downloadable" /> Is Downloadable</label>
|
||||||
|
</div>
|
||||||
|
<div class="span4 form-row">
|
||||||
|
<label for="is_listed"><input ng-disabled="isSaving" ng-change="touchModel()" id="is_listed" type="checkbox" ng-model="track.is_listed" /> Is Listed</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: track.license_id == license.id}">
|
||||||
|
<div ng-click="track.license_id = license.id; touchModel()">
|
||||||
|
<strong>{{license.title}}</strong>
|
||||||
|
<p>{{license.description}}</p>
|
||||||
|
<a href="#" pfm-eat-click class="btn" ng-class="{'btn-primary': track.license_id == license.id, 'disabled': isSaving}">
|
||||||
|
<span ng-hide="track.license_id == license.id">Select</span>
|
||||||
|
<span ng-show="track.license_id == license.id">Selected</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -14,149 +14,9 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
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-track", [
|
angular.module('ponyfm').controller "account-track", [
|
||||||
'$scope', '$state', 'taxonomies', '$dialog', 'account-albums', 'account-tracks', 'images'
|
'$scope', '$state'
|
||||||
($scope, $state, taxonomies, $dialog, albums, tracks, images) ->
|
($scope, $state) ->
|
||||||
$scope.isDirty = false
|
# All the fun stuff happens in the pfmTrackEditor directive.
|
||||||
$scope.isSaving = false
|
$scope.trackId = $state.params.track_id
|
||||||
$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 = {}
|
|
||||||
images.refresh true
|
|
||||||
|
|
||||||
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 if value != null
|
|
||||||
formData.append name, value
|
|
||||||
|
|
||||||
if parseInt($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-XSRF-TOKEN', $.cookie('XSRF-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
|
|
||||||
is_listed: track.is_listed
|
|
||||||
|
|
||||||
$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 + '"?', [
|
|
||||||
{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)
|
|
||||||
.then -> $scope.$apply ->
|
|
||||||
$scope.$emit 'track-deleted'
|
|
||||||
$state.transitionTo 'account.tracks'
|
|
||||||
|
|
||||||
$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?')
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -54,7 +54,12 @@ angular.module('ponyfm').controller "account-tracks", [
|
||||||
else
|
else
|
||||||
$scope.selectTrack null
|
$scope.selectTrack null
|
||||||
|
|
||||||
|
$scope.$on 'track-updated', (track) ->
|
||||||
|
tracks.clearCache()
|
||||||
|
$scope.refreshList()
|
||||||
|
|
||||||
$scope.$on 'track-deleted', () ->
|
$scope.$on 'track-deleted', () ->
|
||||||
|
$state.transitionTo 'account.tracks'
|
||||||
tracks.clearCache()
|
tracks.clearCache()
|
||||||
$scope.refreshList()
|
$scope.refreshList()
|
||||||
]
|
]
|
||||||
|
|
|
@ -14,18 +14,8 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
window.pfm.preloaders['track-edit'] = [
|
|
||||||
'tracks', '$state', 'playlists'
|
|
||||||
(tracks, $state, playlists) ->
|
|
||||||
$.when.all [tracks.fetch $state.params.id, playlists.refreshOwned(true)]
|
|
||||||
]
|
|
||||||
|
|
||||||
angular.module('ponyfm').controller "track-edit", [
|
angular.module('ponyfm').controller "track-edit", [
|
||||||
'$scope', 'tracks', '$state', 'playlists', 'auth', 'favourites', '$dialog'
|
'$scope', '$state'
|
||||||
($scope, tracks, $state, playlists, auth, favourites, $dialog) ->
|
($scope, $state) ->
|
||||||
track = null
|
|
||||||
|
|
||||||
tracks.fetch($state.params.id).done (trackResponse) ->
|
|
||||||
$scope.track = trackResponse.track
|
|
||||||
track = trackResponse.track
|
|
||||||
]
|
]
|
||||||
|
|
167
resources/assets/scripts/app/directives/track-editor.coffee
Normal file
167
resources/assets/scripts/app/directives/track-editor.coffee
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
# Pony.fm - A community for pony fan music.
|
||||||
|
# Copyright (C) 2016 Peter Deltchev
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
angular.module('ponyfm').directive 'pfmTrackEditor', () ->
|
||||||
|
restrict: 'E'
|
||||||
|
templateUrl: '/templates/directives/track-editor.html'
|
||||||
|
scope:
|
||||||
|
trackId: '=trackId'
|
||||||
|
|
||||||
|
controller: [
|
||||||
|
'$scope', '$dialog', 'auth', 'account-tracks', 'account-albums', 'taxonomies', 'images'
|
||||||
|
($scope, $dialog, auth, tracks, albums, taxonomies, images) ->
|
||||||
|
$scope.isDirty = false
|
||||||
|
$scope.isSaving = false
|
||||||
|
$scope.taxonomies = taxonomies
|
||||||
|
$scope.selectedSongsTitle = 'None'
|
||||||
|
$scope.selectedSongs = {}
|
||||||
|
$scope.albums = []
|
||||||
|
$scope.selectedAlbum = null
|
||||||
|
albumsDb = {}
|
||||||
|
|
||||||
|
$scope.selectAlbum = (album) ->
|
||||||
|
$scope.selectedAlbum = album
|
||||||
|
$scope.track.album_id = if album then album.id else null
|
||||||
|
$scope.isDirty = true
|
||||||
|
|
||||||
|
$scope.setCover = (image, type) ->
|
||||||
|
delete $scope.track.cover_id
|
||||||
|
delete $scope.track.cover
|
||||||
|
|
||||||
|
if image == null
|
||||||
|
$scope.track.remove_cover = true
|
||||||
|
else if type == 'file'
|
||||||
|
$scope.track.cover = image
|
||||||
|
else if type == 'gallery'
|
||||||
|
$scope.track.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.track.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)
|
||||||
|
$scope.$emit('track-updated', track)
|
||||||
|
|
||||||
|
$scope.track.is_published = true
|
||||||
|
$scope.isDirty = false
|
||||||
|
$scope.errors = {}
|
||||||
|
images.refresh true
|
||||||
|
|
||||||
|
formData = new FormData();
|
||||||
|
_.each $scope.track, (value, name) ->
|
||||||
|
if name == 'cover'
|
||||||
|
return if value == null
|
||||||
|
if typeof(value) == 'object'
|
||||||
|
formData.append name, value, value.name
|
||||||
|
else if value != null
|
||||||
|
formData.append name, value
|
||||||
|
|
||||||
|
if parseInt($scope.track.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.track.id, true
|
||||||
|
xhr.setRequestHeader 'X-XSRF-TOKEN', $.cookie('XSRF-TOKEN')
|
||||||
|
$scope.isSaving = true
|
||||||
|
xhr.send formData
|
||||||
|
|
||||||
|
$scope.deleteTrack = () ->
|
||||||
|
$dialog.messageBox('Delete ' + $scope.track.title, 'Are you sure you want to delete "' + $scope.track.title + '"?', [
|
||||||
|
{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/' + $scope.track.id)
|
||||||
|
.then -> $scope.$apply ->
|
||||||
|
$scope.$emit 'track-deleted'
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# The part where everything gets loaded!
|
||||||
|
# ========================================
|
||||||
|
$.when(
|
||||||
|
albums.refresh(),
|
||||||
|
taxonomies.refresh(),
|
||||||
|
tracks.getEdit($scope.trackId)
|
||||||
|
).done (albums, taxonomies, track)->
|
||||||
|
# Update album data
|
||||||
|
$scope.albums.length = 0
|
||||||
|
albumsDb = {}
|
||||||
|
for album in albums
|
||||||
|
albumsDb[album.id] = album
|
||||||
|
$scope.albums.push album
|
||||||
|
|
||||||
|
# Update track data
|
||||||
|
$scope.track =
|
||||||
|
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
|
||||||
|
is_listed: track.is_listed
|
||||||
|
|
||||||
|
$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.$on '$locationChangeStart', (e) ->
|
||||||
|
return if !$scope.isDirty
|
||||||
|
e.preventDefault() if !confirm('Are you sure you want to leave this page without saving your changes?')
|
||||||
|
]
|
Loading…
Reference in a new issue