Finished show songs

This commit is contained in:
nelsonlaquet 2013-07-28 01:07:25 -05:00
parent c3744e2931
commit f2b1bc82cf
10 changed files with 186 additions and 41 deletions

View file

@ -20,6 +20,7 @@
$images[] = [ $images[] = [
'id' => $image->id, 'id' => $image->id,
'url' => $image->getUrl(Image::SMALL), 'url' => $image->getUrl(Image::SMALL),
'url_normal' => $image->getUrl(Image::NORMAL),
'filename' => $image->filename 'filename' => $image->filename
]; ];
} }

View file

@ -67,13 +67,18 @@
} }
public function getEdit($id) { public function getEdit($id) {
$track = Track::find($id); $track = Track::with('showSongs')->find($id);
if (!$track) if (!$track)
return $this->notFound('Track ' . $id . ' not found!'); return $this->notFound('Track ' . $id . ' not found!');
if ($track->user_id != Auth::user()->id) if ($track->user_id != Auth::user()->id)
return $this->notAuthorized(); return $this->notAuthorized();
$showSongs = [];
foreach ($track->showSongs as $showSong) {
$showSongs[] = ['id' => $showSong->id, 'title' => $showSong->title];
}
return Response::json([ return Response::json([
'id' => $track->id, 'id' => $track->id,
'title' => $track->title, 'title' => $track->title,
@ -93,7 +98,8 @@
'lyrics' => $track->lyrics, 'lyrics' => $track->lyrics,
'released_at' => $track->released_at, 'released_at' => $track->released_at,
'cover_url' => $track->hasCover() ? $track->getCoverUrl(Image::NORMAL) : null, 'cover_url' => $track->hasCover() ? $track->getCoverUrl(Image::NORMAL) : null,
'real_cover_url' => $track->getCoverUrl(Image::NORMAL) 'real_cover_url' => $track->getCoverUrl(Image::NORMAL),
'show_songs' => $showSongs
], 200); ], 200);
} }

View file

@ -11,7 +11,7 @@ class CreateSongsTable extends Migration {
$table->string('slug', 200)->indexed(); $table->string('slug', 200)->indexed();
}); });
Schema::create('track_show_songs', function($table) { Schema::create('show_song_track', function($table) {
$table->increments('id'); $table->increments('id');
$table->integer('track_id')->unsigned(); $table->integer('track_id')->unsigned();
$table->integer('show_song_id')->unsigned(); $table->integer('show_song_id')->unsigned();
@ -2039,12 +2039,12 @@ Twilight Sparkle: Yes! Everything’s going to be just fine!",
} }
public function down() { public function down() {
Schema::table('track_show_songs', function($table){ Schema::table('show_song_track', function($table){
$table->drop_foreign('track_show_songs_track_id_foreign'); $table->drop_foreign('show_song_track_track_id_foreign');
$table->drop_foreign('track_show_songs_show_song_id_foreign'); $table->drop_foreign('show_song_track_show_song_id_foreign');
}); });
Schema::drop('track_show_songs'); Schema::drop('show_song_track');
Schema::drop('show_songs'); Schema::drop('show_songs');
} }
} }

View file

@ -34,17 +34,22 @@
public function execute() { public function execute() {
$isVocal = isset($this->_input['is_vocal']) && $this->_input['is_vocal'] == 'true' ? true : false; $isVocal = isset($this->_input['is_vocal']) && $this->_input['is_vocal'] == 'true' ? true : false;
$validator = \Validator::make($this->_input, [ $rules = [
'title' => 'required|min:3|max:80', 'title' => 'required|min:3|max:80',
'released_at' => 'before:today' . ($this->_input['released_at'] != "" ? '|date' : ''), 'released_at' => 'before:today' . ($this->_input['released_at'] != "" ? '|date' : ''),
'lyrics' => $isVocal ? 'required' : '', 'lyrics' => $isVocal ? 'required' : '',
'license_id' => 'required|exists:licenses,id', 'license_id' => 'required|exists:licenses,id',
'genre_id' => 'required|exists:genres,id', 'genre_id' => 'required|exists:genres,id',
'cover' => 'image|mimes:png|min_width:350|min_height:350', 'cover' => 'image|mimes:png|min_width:350|min_height:350',
'track_type_id' => 'required|exists:track_types,id', 'track_type_id' => 'required|exists:track_types,id',
'songs' => 'required_when:track_type,2|exists:songs,id', 'songs' => 'required_when:track_type,2|exists:songs,id',
'cover_id' => 'exists:images,id' 'cover_id' => 'exists:images,id',
]); ];
if ($this->_input['track_type_id'] == 2)
$rules['show_song_ids'] = 'required|exists:show_songs,id';
$validator = \Validator::make($this->_input, $rules);
if ($validator->fails()) if ($validator->fails())
return CommandResponse::fail($validator); return CommandResponse::fail($validator);
@ -61,6 +66,11 @@
$track->is_downloadable = $this->_input['is_downloadable'] == 'true'; $track->is_downloadable = $this->_input['is_downloadable'] == 'true';
$track->is_vocal = $isVocal; $track->is_vocal = $isVocal;
if ($track->track_type_id == 2) {
$track->showSongs()->sync(explode(',', $this->_input['show_song_ids']));
} else
$track->showSongs()->sync([]);
if ($track->published_at == null) { if ($track->published_at == null) {
$track->published_at = new \DateTime(); $track->published_at = new \DateTime();
} }

View file

@ -37,6 +37,10 @@
return $this->belongsTo('Entities\Image'); return $this->belongsTo('Entities\Image');
} }
public function showSongs() {
return $this->belongsToMany('Entities\ShowSong');
}
public function isPublished() { public function isPublished() {
return $this->published_at != null && $this->deleted_at == null; return $this->published_at != null && $this->deleted_at == null;
} }

View file

@ -9,24 +9,43 @@ angular.module('ponyfm').controller "account-content-tracks", [
$scope.selectedTrack = null $scope.selectedTrack = null
$scope.isDirty = false $scope.isDirty = false
$scope.isSaving = false $scope.isSaving = false
$scope.taxonomies = $scope.taxonomies = taxonomies
trackTypes: taxonomies.trackTypes $scope.selectedSongsTitle = 'None'
licenses: taxonomies.licenses $scope.selectedSongs = {}
genres: taxonomies.genres
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 = () -> $scope.updateIsVocal = () ->
delete $scope.errors.lyrics if !$scope.edit.is_vocal delete $scope.errors.lyrics if !$scope.edit.is_vocal
$scope.previewCover = () -> $scope.previewCover = () ->
return if !$scope.edit.cover return if !$scope.edit.cover && !$scope.edit.cover_id
if typeof($scope.edit.cover) == 'object'
lightbox.openDataUrl $('#coverPreview').attr 'src' if $scope.edit.cover_id
lightbox.openImageUrl $scope.cover_url
else else
lightbox.openImageUrl $scope.edit.cover if typeof($scope.edit.cover) == 'object'
lightbox.openDataUrl $('#coverPreview').attr 'src'
else
lightbox.openImageUrl $scope.edit.cover
$scope.selectGalleryImage = (image) -> $scope.selectGalleryImage = (image) ->
$('#coverPreview').attr 'src', image.url $('#coverPreview').attr 'src', image.url
$scope.edit.cover_id = image.id $scope.edit.cover_id = image.id
$scope.cover_url = image.url_normal
$scope.edit.remove_cover = false $scope.edit.remove_cover = false
$scope.edit.cover = null $scope.edit.cover = null
$scope.isDirty = true $scope.isDirty = true
@ -58,6 +77,9 @@ angular.module('ponyfm').controller "account-content-tracks", [
else else
formData.append name, value 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.open 'POST', '/api/web/tracks/edit/' + $scope.edit.id, true
xhr.setRequestHeader 'X-Token', pfm.token xhr.setRequestHeader 'X-Token', pfm.token
$scope.isSaving = true $scope.isSaving = true
@ -196,6 +218,10 @@ angular.module('ponyfm').controller "account-content-tracks", [
$('#coverPreview').attr 'src', track.cover_url $('#coverPreview').attr 'src', track.cover_url
$scope.isCoverLoaded = true $scope.isCoverLoaded = true
$scope.selectedSongs = {}
$scope.selectedSongs[song.id] = song for song in track.show_songs
updateSongDisplay()
$scope.touchModel = -> $scope.isDirty = true $scope.touchModel = -> $scope.isDirty = true
$.getJSON('/api/web/tracks/owned?order=created_at,desc').done (tracks) -> $scope.$apply -> $.getJSON('/api/web/tracks/owned?order=created_at,desc').done (tracks) -> $scope.$apply ->

View file

@ -2,17 +2,51 @@ angular.module('ponyfm').directive 'pfmPopup', () ->
(scope, element, attrs) -> (scope, element, attrs) ->
$popup = $ '#' + attrs.pfmPopup $popup = $ '#' + attrs.pfmPopup
$element = $ element $element = $ element
$popup.remove() $positionParent = null
open = false open = false
$popup.parents().each () ->
$this = $ this
$positionParent = $this if $positionParent == null && ($this.css('position') == 'relative' || $this.is 'body')
documentClickHandler = () -> documentClickHandler = () ->
return if !open return if !open
$popup.removeClass 'open' $popup.removeClass 'open'
open = false open = false
$(document.body).bind 'click', documentClickHandler calculatePosition = ->
position = $element.offset()
parentPosition = $positionParent.offset()
$(document.body).append $popup left = position.left
right = left + $popup.width()
windowWidth = $(window).width() - 15
if right > windowWidth
left -= right - windowWidth
height = 'auto'
top = position.top + $element.height() + 10
bottom = top + $popup.height()
windowHeight = $(window).height()
if bottom > windowHeight
height = windowHeight - top;
return {
left: left - parentPosition.left - 2
top: top - parentPosition.top,
height: height}
windowResizeHandler = () ->
return if !open
$popup.css 'height', 'auto'
position = calculatePosition()
$popup.css
left: position.left
top: position.top
height: position.height
$(document.body).bind 'click', documentClickHandler
$(window).bind 'resize', windowResizeHandler
$(element).click (e) -> $(element).click (e) ->
e.preventDefault() e.preventDefault()
@ -25,19 +59,15 @@ angular.module('ponyfm').directive 'pfmPopup', () ->
$popup.addClass 'open' $popup.addClass 'open'
position = $element.offset() $popup.css 'height', 'auto'
left = position.left position = calculatePosition()
right = left + $popup.width()
windowWidth = $(window).width() - 15
if right > windowWidth
left -= right - windowWidth
$popup.css $popup.css
top: position.top + $element.height() + 10 left: position.left
left: left top: position.top
height: position.height
open = true open = true
scope.$on '$destroy', () -> scope.$on '$destroy', () ->
$(document.body).unbind 'click', documentClickHandler $(document.body).unbind 'click', documentClickHandler
$popup.remove() $(window).unbind 'click', windowResizeHandler

View file

@ -125,6 +125,62 @@
.editor { .editor {
display: none; display: none;
.show-songs {
.btn {
.border-radius(0px);
display: block;
float: none;
padding: 3px 10px;
font-size: 8pt;
text-align: left;
}
.error {
margin-top: 10px;
}
.pfm-popup {
width: 300px;
ul {
margin: 0px;
padding: 0px;
list-style: none;
li {
margin: 0px;
padding: 0px;
a {
.ellipsis();
display: block;
padding: 3px 10px;
font-size: 8pt;
color: #333333;
&:hover {
#gradient>.vertical(@dropdownLinkBackgroundHover, darken(@dropdownLinkBackgroundHover, 5%));
text-decoration: none;
color: @dropdownLinkColorHover;
}
}
&.selected {
a {
#gradient>.vertical(@green, darken(@green, 5%));
color: #fff;
font-weight: bold;
&:hover {
#gradient>.vertical(fadeout(@green, 20%), fadeout(darken(@green, 5%), 20%));
}
}
}
}
}
}
}
.form-row { .form-row {
margin-bottom: 10px; margin-bottom: 10px;

View file

@ -84,10 +84,12 @@ html body {
.pfm-popup { .pfm-popup {
.box-shadow(0 5px 10px rgba(0, 0, 0, 0.2)); .box-shadow(0 5px 10px rgba(0, 0, 0, 0.2));
z-index: 1000;
position: absolute; position: absolute;
display: none; display: none;
border: 1px solid rgba(0, 0, 0, 0.2); border: 1px solid rgba(0, 0, 0, 0.2);
background: #fff; background: #fff;
overflow-y: auto;
&.open { &.open {
display: block; display: block;

View file

@ -105,8 +105,18 @@
<div class="error">{{errors.genre_id}}</div> <div class="error">{{errors.genre_id}}</div>
</div> </div>
</div> </div>
<div class="form-row" ng-show="edit.track_type_id == 2"> <div class="row-fluid">
<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>
<div class="row-fluid"> <div class="row-fluid">
<div class="form-row span6" ng-class="{'has-error': errors.cover != null}"> <div class="form-row span6" ng-class="{'has-error': errors.cover != null}">