mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2024-11-22 04:58:01 +01:00
Commit for things
This commit is contained in:
parent
f093d7a570
commit
e2bb57922a
16 changed files with 390 additions and 206 deletions
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
namespace Api\Web;
|
namespace Api\Web;
|
||||||
|
|
||||||
|
use Commands\CreateAlbumCommand;
|
||||||
use Commands\DeleteTrackCommand;
|
use Commands\DeleteTrackCommand;
|
||||||
use Commands\EditTrackCommand;
|
use Commands\EditTrackCommand;
|
||||||
use Commands\UploadTrackCommand;
|
|
||||||
use Cover;
|
use Cover;
|
||||||
use Entities\Album;
|
use Entities\Album;
|
||||||
use Entities\Image;
|
use Entities\Image;
|
||||||
|
@ -15,44 +15,42 @@
|
||||||
|
|
||||||
class AlbumsController extends \ApiControllerBase {
|
class AlbumsController extends \ApiControllerBase {
|
||||||
public function getOwned() {
|
public function getOwned() {
|
||||||
$query = Album::summary()->where('user_id', \Auth::user()->id);
|
$query = Album::summary()->where('user_id', \Auth::user()->id)->get();
|
||||||
return Response::json($query->get(), 200);
|
$albums = [];
|
||||||
|
foreach ($query as $album) {
|
||||||
|
$albums[] = [
|
||||||
|
'id' => $album->id,
|
||||||
|
'title' => $album->title,
|
||||||
|
'slug' => $album->slug,
|
||||||
|
'created_at' => $album->created_at,
|
||||||
|
'cover_url' => $album->getCoverUrl(Image::SMALL)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return Response::json($albums, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postCreate() {
|
||||||
|
return $this->execute(new CreateAlbumCommand(Input::all()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEdit($id) {
|
public function getEdit($id) {
|
||||||
$track = Track::with('showSongs')->find($id);
|
$album = Album::find($id);
|
||||||
if (!$track)
|
if (!$album)
|
||||||
return $this->notFound('Track ' . $id . ' not found!');
|
return $this->notFound('Album ' . $id . ' not found!');
|
||||||
|
|
||||||
if ($track->user_id != Auth::user()->id)
|
if ($album->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' => $album->id,
|
||||||
'title' => $track->title,
|
'title' => $album->title,
|
||||||
'user_id' => $track->user_id,
|
'user_id' => $album->user_id,
|
||||||
'slug' => $track->slug,
|
'slug' => $album->slug,
|
||||||
'is_vocal' => (bool)$track->is_vocal,
|
'created_at' => $album->created_at,
|
||||||
'is_explicit' => (bool)$track->is_explicit,
|
'published_at' => $album->published_at,
|
||||||
'is_downloadable' => !$track->isPublished() ? true : (bool)$track->is_downloadable,
|
'description' => $album->description,
|
||||||
'is_published' => $track->published_at != null,
|
'cover_url' => $album->hasCover() ? $album->getCoverUrl(Image::NORMAL) : null,
|
||||||
'created_at' => $track->created_at,
|
'real_cover_url' => $album->getCoverUrl(Image::NORMAL)
|
||||||
'published_at' => $track->published_at,
|
|
||||||
'duration' => $track->duration,
|
|
||||||
'genre_id' => $track->genre_id,
|
|
||||||
'track_type_id' => $track->track_type_id,
|
|
||||||
'license_id' => $track->license_id != null ? $track->license_id : 3,
|
|
||||||
'description' => $track->description,
|
|
||||||
'lyrics' => $track->lyrics,
|
|
||||||
'released_at' => $track->released_at,
|
|
||||||
'cover_url' => $track->hasCover() ? $track->getCoverUrl(Image::NORMAL) : null,
|
|
||||||
'real_cover_url' => $track->getCoverUrl(Image::NORMAL),
|
|
||||||
'show_songs' => $showSongs
|
|
||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,12 @@
|
||||||
foreach ($query->get() as $image) {
|
foreach ($query->get() as $image) {
|
||||||
$images[] = [
|
$images[] = [
|
||||||
'id' => $image->id,
|
'id' => $image->id,
|
||||||
'url' => $image->getUrl(Image::SMALL),
|
'urls' => [
|
||||||
'url_normal' => $image->getUrl(Image::NORMAL),
|
'small' => $image->getUrl(Image::SMALL),
|
||||||
|
'normal' => $image->getUrl(Image::NORMAL),
|
||||||
|
'thumbnail' => $image->getUrl(Image::THUMBNAIL),
|
||||||
|
'original' => $image->getUrl(Image::ORIGINAL)
|
||||||
|
],
|
||||||
'filename' => $image->filename
|
'filename' => $image->filename
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
62
app/models/Commands/CreateAlbumCommand.php
Normal file
62
app/models/Commands/CreateAlbumCommand.php
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Commands;
|
||||||
|
|
||||||
|
use Entities\Album;
|
||||||
|
use Entities\Image;
|
||||||
|
use Entities\Track;
|
||||||
|
use External;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class CreateAlbumCommand extends CommandBase {
|
||||||
|
private $_input;
|
||||||
|
|
||||||
|
function __construct($input) {
|
||||||
|
$this->_input = $input;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize() {
|
||||||
|
$user = \Auth::user();
|
||||||
|
return $user != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
* @return CommandResponse
|
||||||
|
*/
|
||||||
|
public function execute() {
|
||||||
|
$rules = [
|
||||||
|
'title' => 'required|min:3|max:50',
|
||||||
|
'description' => '',
|
||||||
|
'cover' => 'image|mimes:png|min_width:350|min_height:350',
|
||||||
|
'cover_id' => 'exists:images,id',
|
||||||
|
];
|
||||||
|
|
||||||
|
$validator = \Validator::make($this->_input, $rules);
|
||||||
|
|
||||||
|
if ($validator->fails())
|
||||||
|
return CommandResponse::fail($validator);
|
||||||
|
|
||||||
|
$album = new Album();
|
||||||
|
$album->user_id = Auth::user()->id;
|
||||||
|
$album->title = $this->_input['title'];
|
||||||
|
$album->description = $this->_input['description'];
|
||||||
|
|
||||||
|
if (isset($this->_input['cover_id'])) {
|
||||||
|
$album->cover_id = $this->_input['cover_id'];
|
||||||
|
}
|
||||||
|
else if (isset($this->_input['cover'])) {
|
||||||
|
$cover = $this->_input['cover'];
|
||||||
|
$album->cover_id = Image::upload($cover, Auth::user())->id;
|
||||||
|
} else if ($this->_input['remove_cover'] == 'true')
|
||||||
|
$album->cover_id = null;
|
||||||
|
|
||||||
|
$album->save();
|
||||||
|
|
||||||
|
return CommandResponse::succeed(['id' => $album->id]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@
|
||||||
protected $softDelete = true;
|
protected $softDelete = true;
|
||||||
|
|
||||||
public static function summary() {
|
public static function summary() {
|
||||||
return self::select('id', 'title', 'user_id', 'slug', 'created_at');
|
return self::select('id', 'title', 'user_id', 'slug', 'created_at', 'cover_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $table = 'albums';
|
protected $table = 'albums';
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
Route::post('/tracks/upload', 'Api\Web\TracksController@postUpload');
|
Route::post('/tracks/upload', 'Api\Web\TracksController@postUpload');
|
||||||
Route::post('/tracks/delete/{id}', 'Api\Web\TracksController@postDelete');
|
Route::post('/tracks/delete/{id}', 'Api\Web\TracksController@postDelete');
|
||||||
Route::post('/tracks/edit/{id}', 'Api\Web\TracksController@putEdit');
|
Route::post('/tracks/edit/{id}', 'Api\Web\TracksController@putEdit');
|
||||||
|
|
||||||
|
Route::post('/albums/create', 'Api\Web\AlbumsController@postCreate');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group(['before' => 'auth'], function() {
|
Route::group(['before' => 'auth'], function() {
|
||||||
|
|
|
@ -1,17 +1,87 @@
|
||||||
angular.module('ponyfm').controller "account-albums-edit", [
|
angular.module('ponyfm').controller "account-albums-edit", [
|
||||||
'$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
|
'$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
|
||||||
($scope, $state, taxonomies, $dialog, lightbox) ->
|
($scope, $state, taxonomies, $dialog, lightbox) ->
|
||||||
$scope.isNew = $state.params.album_id == null
|
$scope.isNew = $state.params.album_id == undefined
|
||||||
$scope.data.isEditorOpen = true
|
$scope.data.isEditorOpen = true
|
||||||
$scope.errors = {}
|
$scope.errors = {}
|
||||||
$scope.isDirty = false
|
$scope.isDirty = false
|
||||||
|
$scope.album = {}
|
||||||
|
$scope.isSaving = false
|
||||||
|
|
||||||
$scope.touchModel = -> $scope.isDirty = true
|
$scope.touchModel = -> $scope.isDirty = true
|
||||||
|
|
||||||
|
$scope.refresh = () ->
|
||||||
|
return if $scope.isNew
|
||||||
|
$.getJSON('/api/web/albums/edit/' + $scope.data.selectedAlbum.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
|
||||||
|
|
||||||
if $scope.isNew
|
if $scope.isNew
|
||||||
$scope.album =
|
$scope.album =
|
||||||
title: ''
|
title: ''
|
||||||
description: ''
|
description: ''
|
||||||
|
else
|
||||||
|
$scope.refresh();
|
||||||
|
|
||||||
$scope.$on '$destroy', -> $scope.data.isEditorOpen = false
|
$scope.$on '$destroy', -> $scope.data.isEditorOpen = false
|
||||||
|
|
||||||
|
$scope.saveAlbum = ->
|
||||||
|
url =
|
||||||
|
if $scope.isNew
|
||||||
|
'/api/web/albums/create'
|
||||||
|
else
|
||||||
|
'/api/web/albums/edit' + $scope.album.id
|
||||||
|
|
||||||
|
xhr = new XMLHttpRequest()
|
||||||
|
xhr.onload = -> $scope.$apply ->
|
||||||
|
$scope.isSaving = false
|
||||||
|
response = $.parseJSON(xhr.responseText).errors
|
||||||
|
if xhr.status != 200
|
||||||
|
$scope.errors = {}
|
||||||
|
_.each response.errors, (value, key) -> $scope.errors[key] = value.join ', '
|
||||||
|
return
|
||||||
|
|
||||||
|
$scope.$emit 'album-updated'
|
||||||
|
|
||||||
|
if $scope.isNew
|
||||||
|
$state.transitionTo 'account-content.albums.edit', {album_id: response.id}
|
||||||
|
else
|
||||||
|
$scope.refresh()
|
||||||
|
|
||||||
|
formData = new FormData()
|
||||||
|
|
||||||
|
_.each $scope.album, (value, name) ->
|
||||||
|
if name == 'cover'
|
||||||
|
return if value == null
|
||||||
|
if typeof(value) == 'object'
|
||||||
|
formData.append name, value, value.name
|
||||||
|
else
|
||||||
|
formData.append name, value
|
||||||
|
|
||||||
|
xhr.open 'POST', url, true
|
||||||
|
xhr.setRequestHeader 'X-Token', pfm.token
|
||||||
|
$scope.isSaving = true
|
||||||
|
xhr.send formData
|
||||||
|
|
||||||
|
$scope.deleteAlbum = ->
|
||||||
|
|
||||||
|
$scope.setCover = (image, type) ->
|
||||||
|
delete $scope.album.cover_id
|
||||||
|
delete $scope.album.cover
|
||||||
|
|
||||||
|
if image == null
|
||||||
|
$scope.album.remove_cover = true
|
||||||
|
else if type == 'file'
|
||||||
|
$scope.album.cover = image
|
||||||
|
else if type == 'gallery'
|
||||||
|
$scope.album.cover_id = image.id
|
||||||
|
|
||||||
|
$scope.isDirty = true
|
||||||
]
|
]
|
|
@ -1,19 +1,28 @@
|
||||||
angular.module('ponyfm').controller "account-albums", [
|
angular.module('ponyfm').controller "account-albums", [
|
||||||
'$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
|
'$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
|
||||||
($scope, $state, taxonomies, $dialog, lightbox) ->
|
($scope, $state, taxonomies, $dialog, lightbox) ->
|
||||||
refreshList = () ->
|
albumsDb = {}
|
||||||
$.getJSON('/api/web/albums/owned')
|
|
||||||
.done (albums) ->
|
|
||||||
$scope.albums = albums
|
|
||||||
|
|
||||||
refreshList()
|
$scope.albums = []
|
||||||
$scope.data =
|
$scope.data =
|
||||||
isEditorOpen: false
|
isEditorOpen: false
|
||||||
selectedAlbum: null
|
selectedAlbum: null
|
||||||
|
|
||||||
|
refreshList = () ->
|
||||||
|
$.getJSON('/api/web/albums/owned')
|
||||||
|
.done (albums) -> $scope.$apply ->
|
||||||
|
albumsDb[album.id] = album for album in albums
|
||||||
|
$scope.albums = albums
|
||||||
|
|
||||||
|
selectAlbum albumsDb[$state.params.album_id] if $state.params.album_id != undefined
|
||||||
|
|
||||||
|
selectAlbum = (album) -> $scope.data.selectedAlbum = album
|
||||||
|
|
||||||
$scope.$on '$stateChangeSuccess', () ->
|
$scope.$on '$stateChangeSuccess', () ->
|
||||||
if $state.params.album_id
|
if $state.params.album_id
|
||||||
selectAlbum albumsDb[$state.params.album_id]
|
selectAlbum albumsDb[$state.params.album_id]
|
||||||
else
|
else
|
||||||
selectAlbum null
|
selectAlbum null
|
||||||
|
|
||||||
|
refreshList()
|
||||||
]
|
]
|
|
@ -1,11 +1,6 @@
|
||||||
angular.module('ponyfm').controller "account-tracks", [
|
angular.module('ponyfm').controller "account-tracks", [
|
||||||
'$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
|
'$scope', '$state', 'taxonomies', '$dialog', 'lightbox'
|
||||||
($scope, $state, taxonomies, $dialog, lightbox) ->
|
($scope, $state, taxonomies, $dialog, lightbox) ->
|
||||||
$('#coverPreview').load () ->
|
|
||||||
$scope.$apply -> $scope.isCoverLoaded = true
|
|
||||||
window.alignVertically(this)
|
|
||||||
|
|
||||||
$scope.isCoverLoaded = false
|
|
||||||
$scope.selectedTrack = null
|
$scope.selectedTrack = null
|
||||||
$scope.isDirty = false
|
$scope.isDirty = false
|
||||||
$scope.isSaving = false
|
$scope.isSaving = false
|
||||||
|
@ -13,6 +8,19 @@ angular.module('ponyfm').controller "account-tracks", [
|
||||||
$scope.selectedSongsTitle = 'None'
|
$scope.selectedSongsTitle = 'None'
|
||||||
$scope.selectedSongs = {}
|
$scope.selectedSongs = {}
|
||||||
|
|
||||||
|
$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 = () ->
|
updateSongDisplay = () ->
|
||||||
if _.size $scope.selectedSongs
|
if _.size $scope.selectedSongs
|
||||||
$scope.selectedSongsTitle = (_.map _.values($scope.selectedSongs), (s) -> s.title).join(', ')
|
$scope.selectedSongsTitle = (_.map _.values($scope.selectedSongs), (s) -> s.title).join(', ')
|
||||||
|
@ -31,25 +39,6 @@ angular.module('ponyfm').controller "account-tracks", [
|
||||||
$scope.updateIsVocal = () ->
|
$scope.updateIsVocal = () ->
|
||||||
delete $scope.errors.lyrics if !$scope.edit.is_vocal
|
delete $scope.errors.lyrics if !$scope.edit.is_vocal
|
||||||
|
|
||||||
$scope.previewCover = () ->
|
|
||||||
return if !$scope.edit.cover && !$scope.edit.cover_id
|
|
||||||
|
|
||||||
if $scope.edit.cover_id
|
|
||||||
lightbox.openImageUrl $scope.cover_url
|
|
||||||
else
|
|
||||||
if typeof($scope.edit.cover) == 'object'
|
|
||||||
lightbox.openDataUrl $('#coverPreview').attr 'src'
|
|
||||||
else
|
|
||||||
lightbox.openImageUrl $scope.edit.cover
|
|
||||||
|
|
||||||
$scope.selectGalleryImage = (image) ->
|
|
||||||
$('#coverPreview').attr 'src', image.url
|
|
||||||
$scope.edit.cover_id = image.id
|
|
||||||
$scope.cover_url = image.url_normal
|
|
||||||
$scope.edit.remove_cover = false
|
|
||||||
$scope.edit.cover = null
|
|
||||||
$scope.isDirty = true
|
|
||||||
|
|
||||||
$scope.updateTrack = (track) ->
|
$scope.updateTrack = (track) ->
|
||||||
xhr = new XMLHttpRequest()
|
xhr = new XMLHttpRequest()
|
||||||
xhr.onload = -> $scope.$apply ->
|
xhr.onload = -> $scope.$apply ->
|
||||||
|
@ -85,35 +74,6 @@ angular.module('ponyfm').controller "account-tracks", [
|
||||||
$scope.isSaving = true
|
$scope.isSaving = true
|
||||||
xhr.send formData
|
xhr.send formData
|
||||||
|
|
||||||
$scope.uploadTrackCover = () ->
|
|
||||||
$("#coverImage").trigger 'click'
|
|
||||||
|
|
||||||
$scope.setCoverImage = (input) ->
|
|
||||||
$scope.$apply ->
|
|
||||||
delete $scope.edit.cover_id
|
|
||||||
previewElement = $('#coverPreview')[0]
|
|
||||||
file = input.files[0]
|
|
||||||
|
|
||||||
if file.type != 'image/png'
|
|
||||||
$scope.errors.cover = 'Cover image must be a png!'
|
|
||||||
$scope.isCoverLoaded = false
|
|
||||||
$scope.edit.cover = null
|
|
||||||
return
|
|
||||||
|
|
||||||
delete $scope.errors.cover
|
|
||||||
$scope.isDirty = true
|
|
||||||
reader = new FileReader()
|
|
||||||
reader.onload = (e) -> previewElement.src = e.target.result
|
|
||||||
reader.readAsDataURL file
|
|
||||||
$scope.edit.cover = file
|
|
||||||
|
|
||||||
$scope.clearTrackCover = () ->
|
|
||||||
$scope.isCoverLoaded = false
|
|
||||||
$scope.isDirty = true
|
|
||||||
$scope.edit.remove_cover = true
|
|
||||||
delete $scope.edit.cover_id
|
|
||||||
delete $scope.edit.cover
|
|
||||||
|
|
||||||
$scope.filters =
|
$scope.filters =
|
||||||
published: [
|
published: [
|
||||||
{title: 'Either', query: ''},
|
{title: 'Either', query: ''},
|
||||||
|
@ -185,7 +145,6 @@ angular.module('ponyfm').controller "account-tracks", [
|
||||||
|
|
||||||
selectTrack = (t) ->
|
selectTrack = (t) ->
|
||||||
$scope.selectedTrack = t
|
$scope.selectedTrack = t
|
||||||
$scope.isCoverLoaded = false
|
|
||||||
return if !t
|
return if !t
|
||||||
$.getJSON('/api/web/tracks/edit/' + t.id)
|
$.getJSON('/api/web/tracks/edit/' + t.id)
|
||||||
.done (track) -> $scope.$apply ->
|
.done (track) -> $scope.$apply ->
|
||||||
|
@ -214,10 +173,6 @@ angular.module('ponyfm').controller "account-tracks", [
|
||||||
trackDbItem.is_published = track.is_published
|
trackDbItem.is_published = track.is_published
|
||||||
trackDbItem.cover_url = track.real_cover_url
|
trackDbItem.cover_url = track.real_cover_url
|
||||||
|
|
||||||
if track.cover_url
|
|
||||||
$('#coverPreview').attr 'src', track.cover_url
|
|
||||||
$scope.isCoverLoaded = true
|
|
||||||
|
|
||||||
$scope.selectedSongs = {}
|
$scope.selectedSongs = {}
|
||||||
$scope.selectedSongs[song.id] = song for song in track.show_songs
|
$scope.selectedSongs[song.id] = song for song in track.show_songs
|
||||||
updateSongDisplay()
|
updateSongDisplay()
|
||||||
|
|
|
@ -1,9 +1,86 @@
|
||||||
angular.module('ponyfm').directive 'pfmImageUpload',
|
angular.module('ponyfm').directive 'pfmImageUpload', () ->
|
||||||
|
$image = null
|
||||||
|
$uploader = null
|
||||||
|
|
||||||
restrict: 'E'
|
restrict: 'E'
|
||||||
|
templateUrl: '/templates/directives/image-upload.html'
|
||||||
scope:
|
scope:
|
||||||
setUploadedImage: '&'
|
setImage: '=setImage'
|
||||||
setGalleryImage: '&'
|
image: '=image'
|
||||||
|
|
||||||
|
compile: (element) ->
|
||||||
|
$image = element.find 'img'
|
||||||
|
$uploader = element.find 'input'
|
||||||
|
|
||||||
controller: [
|
controller: [
|
||||||
'upload'
|
'images', '$scope', 'lightbox'
|
||||||
(upload) -> (scope) ->
|
(images, $scope, lightbox) ->
|
||||||
|
$scope.imageObject = null
|
||||||
|
$scope.imageFile = null
|
||||||
|
$scope.imageUrl = null
|
||||||
|
$scope.isImageLoaded = false
|
||||||
|
$scope.error = null
|
||||||
|
|
||||||
|
$scope.$watch 'image', (val) ->
|
||||||
|
$scope.imageObject = $scope.imageFile = $scope.imageUrl = null
|
||||||
|
$scope.isImageLoaded = false
|
||||||
|
return if !val
|
||||||
|
|
||||||
|
$scope.imageUrl = val
|
||||||
|
$image.attr 'src', val
|
||||||
|
$scope.isImageLoaded = true
|
||||||
|
|
||||||
|
$image.load () -> $scope.$apply ->
|
||||||
|
$scope.isImageLoaded = true
|
||||||
|
window.setTimeout (() -> window.alignVertically($image)), 0
|
||||||
|
|
||||||
|
images.refresh().done (images) -> $scope.images = images
|
||||||
|
|
||||||
|
$scope.previewImage = () ->
|
||||||
|
return if !$scope.isImageLoaded
|
||||||
|
|
||||||
|
if $scope.imageObject
|
||||||
|
lightbox.openImageUrl $scope.imageObject.urls.normal
|
||||||
|
else if $scope.imageFile
|
||||||
|
lightbox.openDataUrl $image.attr 'src'
|
||||||
|
else if $scope.imageUrl
|
||||||
|
lightbox.openImageUrl $scope.imageUrl
|
||||||
|
|
||||||
|
$scope.uploadImage = () ->
|
||||||
|
$uploader.trigger 'click'
|
||||||
|
|
||||||
|
$scope.clearImage = () ->
|
||||||
|
$scope.imageObject = $scope.imageFile = $scope.imageUrl = null
|
||||||
|
$scope.isImageLoaded = false
|
||||||
|
$scope.setImage null
|
||||||
|
|
||||||
|
$scope.selectGalleryImage = (image) ->
|
||||||
|
$scope.imageObject = image
|
||||||
|
$scope.imageFile = null
|
||||||
|
$scope.imageUrl = image.urls.small
|
||||||
|
$image.attr 'src', image.urls.small
|
||||||
|
$scope.isImageLoaded = true
|
||||||
|
$scope.setImage image, 'gallery'
|
||||||
|
|
||||||
|
$scope.setImageFile = (input) ->
|
||||||
|
$scope.$apply ->
|
||||||
|
file = input.files[0]
|
||||||
|
$scope.imageObject = null
|
||||||
|
$scope.imageFile = file
|
||||||
|
|
||||||
|
if file.type != 'image/png'
|
||||||
|
$scope.error = 'Image must be a png!'
|
||||||
|
$scope.isImageLoaded = false
|
||||||
|
$scope.imageObject = $scope.imageFile = $scope.imageUrl = null
|
||||||
|
return
|
||||||
|
|
||||||
|
$scope.error = null
|
||||||
|
$scope.setImage file, 'file'
|
||||||
|
|
||||||
|
reader = new FileReader()
|
||||||
|
reader.onload = (e) -> $scope.$apply ->
|
||||||
|
$image[0].src = e.target.result
|
||||||
|
$scope.isImageLoaded = true
|
||||||
|
|
||||||
|
reader.readAsDataURL file
|
||||||
]
|
]
|
25
public/scripts/app/services/images.coffee
Normal file
25
public/scripts/app/services/images.coffee
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
angular.module('ponyfm').factory('images', [
|
||||||
|
'$rootScope'
|
||||||
|
($rootScope) ->
|
||||||
|
def = null
|
||||||
|
self =
|
||||||
|
images: []
|
||||||
|
isLoading: true
|
||||||
|
refresh: () ->
|
||||||
|
return def if def
|
||||||
|
def = new $.Deferred()
|
||||||
|
|
||||||
|
self.images = []
|
||||||
|
self.isLoading = true
|
||||||
|
|
||||||
|
$.getJSON('/api/web/images/owned').done (images) -> $rootScope.$apply ->
|
||||||
|
self.images = images
|
||||||
|
self.isLoading = false
|
||||||
|
def.resolve images
|
||||||
|
|
||||||
|
return def
|
||||||
|
|
||||||
|
self.refresh()
|
||||||
|
return self
|
||||||
|
])
|
||||||
|
|
|
@ -201,66 +201,15 @@
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.has-error {
|
|
||||||
label {
|
|
||||||
color: @red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.cover-upload {
|
.has-error {
|
||||||
overflow: hidden;
|
label {
|
||||||
|
color: @red;
|
||||||
|
}
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
clear: left;
|
|
||||||
margin-top: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=file] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
.border-radius(0px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview {
|
|
||||||
.img-polaroid();
|
|
||||||
overflow: hidden;
|
|
||||||
width: 46px;
|
|
||||||
height: 46px;
|
|
||||||
float: left;
|
|
||||||
|
|
||||||
img {
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.canOpen {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: @blue;
|
|
||||||
border-style: solid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p, .btn-group {
|
|
||||||
color: #555;
|
|
||||||
margin-left: 60px;
|
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 9pt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,4 +94,55 @@ html body {
|
||||||
&.open {
|
&.open {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-upload {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.error {
|
||||||
|
clear: left;
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=file] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
.border-radius(0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
.img-polaroid();
|
||||||
|
overflow: hidden;
|
||||||
|
width: 46px;
|
||||||
|
height: 46px;
|
||||||
|
float: left;
|
||||||
|
|
||||||
|
img {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.canOpen {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @blue;
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p, .btn-group {
|
||||||
|
color: #555;
|
||||||
|
margin-left: 60px;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 9pt;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
<form novalidate ng-submit="updateAlbum()">
|
<form novalidate ng-submit="saveAlbum()">
|
||||||
<ul class="toolbar">
|
<ul class="toolbar">
|
||||||
<li>
|
<li>
|
||||||
<button type="submit" class="btn" ng-class="{disabled: !isDirty || isSaving, 'btn-primary': isDirty}">
|
<button type="submit" class="btn" ng-class="{disabled: !isDirty || isSaving, 'btn-primary': isDirty}">
|
||||||
|
@ -6,7 +6,7 @@
|
||||||
<i ng-show="isSaving" class="icon-cog icon-spin icon-large"></i>
|
<i ng-show="isSaving" class="icon-cog icon-spin icon-large"></i>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="delete"><a ng-class="{disabled: isSaving}" class="btn btn-danger" href="#" ng-click="deleteAlbum(selectedAlbum)" pfm-eat-click>Delete Album</a></li>
|
<li class="delete" ng-show="!isNew"><a ng-class="{disabled: isSaving}" class="btn btn-danger" href="#" ng-click="deleteAlbum()" pfm-eat-click>Delete Album</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="strech-to-bottom">
|
<div class="strech-to-bottom">
|
||||||
<div class="form-row" ng-class="{'has-error': errors.title != null}">
|
<div class="form-row" ng-class="{'has-error': errors.title != null}">
|
||||||
|
@ -14,33 +14,14 @@
|
||||||
<input ng-disabled="isSaving" ng-change="touchModel()" placeholder="Album Title" type="text" id="title" ng-model="album.title" />
|
<input ng-disabled="isSaving" ng-change="touchModel()" placeholder="Album Title" type="text" id="title" ng-model="album.title" />
|
||||||
<div class="error">{{errors.title}}</div>
|
<div class="error">{{errors.title}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row" ng-class="{'has-error': errors.description != null}">
|
<div class="form-row">
|
||||||
<label for="description" class="strong">Description:</label>
|
<label for="description" class="strong">Description:</label>
|
||||||
<textarea ng-disabled="isSaving" ng-change="touchModel()" placeholder="Description (optional)" id="description" ng-model="album.description"></textarea>
|
<textarea ng-disabled="isSaving" ng-change="touchModel()" placeholder="Description (optional)" id="description" ng-model="album.description"></textarea>
|
||||||
<div class="error">{{errors.description}}</div>
|
<div class="error">{{errors.description}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row" ng-class="{'has-error': errors.cover != null}">
|
<div class="form-row" ng-class="{'has-error': errors.cover != null}">
|
||||||
<label class="strong">Album Cover: </label>
|
<label class="strong">Album Cover: </label>
|
||||||
<div class="cover-upload">
|
<pfm-image-upload />
|
||||||
<div class="preview" ng-class="{canOpen: isCoverLoaded}" ng-click="previewCover()"><img id="coverPreview" ng-show="isCoverLoaded" /></div>
|
|
||||||
<p>
|
|
||||||
Image must be a PNG that is at least 350x350. <br />
|
|
||||||
<input type="file" id="coverImage" onchange="angular.element(this).scope().setCoverImage(this)" />
|
|
||||||
</p>
|
|
||||||
<div class="btn-group">
|
|
||||||
<a href="#" pfm-popup="image-selector" class="btn btn-small"><i class="icon-picture"></i> Gallery</a>
|
|
||||||
<a href="#" pfm-eat-click ng-click="uploadAlbumCover()" class="btn btn-info btn-small"><i class="icon-upload"></i> Upload</a>
|
|
||||||
<a href="#" pfm-eat-click ng-click="clearAlbumCover()" class="btn btn-danger btn-small" ng-show="album.cover || album.cover_id"><i class="icon-remove"></i></a>
|
|
||||||
</div>
|
|
||||||
<div id="image-selector" class="pfm-popup image-selector" ng-controller="account-image-select">
|
|
||||||
<ul>
|
|
||||||
<li ng-repeat="image in images" ng-click="selectGalleryImage(image)">
|
|
||||||
<img ng-src="{{image.url}}" />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="error">{{errors.cover}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
|
@ -9,11 +9,11 @@
|
||||||
<div class="two-pane-view" ng-class="{open: data.isEditorOpen, closed: !data.isEditorOpen}">
|
<div class="two-pane-view" ng-class="{open: data.isEditorOpen, closed: !data.isEditorOpen}">
|
||||||
<div class="list">
|
<div class="list">
|
||||||
<ul class="account-albums-listing strech-to-bottom">
|
<ul class="account-albums-listing strech-to-bottom">
|
||||||
<li ng-repeat="album in albums" ng-class="{selected: album.id == data.selectedAlbum.id">
|
<li ng-repeat="album in albums" ng-class="{selected: album.id == data.selectedAlbum.id}">
|
||||||
<a href="/account/albums/edit/{{album.id}}">
|
<a href="/account/albums/edit/{{album.id}}">
|
||||||
<img class="image" ng-src="{{album.cover_url}}" />
|
<img class="image" ng-src="{{album.cover_url}}" />
|
||||||
<span class="title">{{albums.title}}</span>
|
<span class="title">{{album.title}}</span>
|
||||||
<span class="published">{{albums.created_at | pfmdate:'MM/dd/yyyy'}}</span>
|
<span class="published">{{album.created_at | pfmdate:'MM/dd/yyyy'}}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li ng-show="!albums.length" class="empty">
|
<li ng-show="!albums.length" class="empty">
|
||||||
|
|
|
@ -121,28 +121,9 @@
|
||||||
<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}">
|
||||||
<label class="strong">Track Cover: </label>
|
<label class="strong">Track Cover: </label>
|
||||||
<div class="cover-upload">
|
<pfm-image-upload set-image="setCover" image="edit.cover" />
|
||||||
<div class="preview" ng-class="{canOpen: isCoverLoaded}" ng-click="previewCover()"><img id="coverPreview" ng-show="isCoverLoaded" /></div>
|
|
||||||
<p>
|
|
||||||
Track cover must be a PNG that is at least 350x350. <br />
|
|
||||||
<input type="file" id="coverImage" onchange="angular.element(this).scope().setCoverImage(this)" />
|
|
||||||
</p>
|
|
||||||
<div class="btn-group">
|
|
||||||
<a href="#" pfm-popup="image-selector" class="btn btn-small"><i class="icon-picture"></i> Gallery</a>
|
|
||||||
<a href="#" pfm-eat-click ng-click="uploadTrackCover()" class="btn btn-info btn-small"><i class="icon-upload"></i> Upload</a>
|
|
||||||
<a href="#" pfm-eat-click ng-click="clearTrackCover()" class="btn btn-danger btn-small" ng-show="edit.cover || edit.cover_id"><i class="icon-remove"></i></a>
|
|
||||||
</div>
|
|
||||||
<div id="image-selector" class="pfm-popup image-selector" ng-controller="account-image-select">
|
|
||||||
<ul>
|
|
||||||
<li ng-repeat="image in images" ng-click="selectGalleryImage(image)">
|
|
||||||
<img ng-src="{{image.url}}" />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="error">{{errors.cover}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row span6" ng-class="{'has-error': errors.released_at != null}">
|
<div class="form-row span6">
|
||||||
<label for="released_at" class="strong">Release Date:</label>
|
<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" />
|
<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 class="error">{{errors.released_at}}</div>
|
||||||
|
|
20
public/templates/directives/image-upload.html
Normal file
20
public/templates/directives/image-upload.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<div class="image-upload" ng-class="{'has-error': error != null}">
|
||||||
|
<div class="preview" ng-class="{canOpen: isImageLoaded}" ng-click="previewImage()"><img ng-show="isImageLoaded" /></div>
|
||||||
|
<p>
|
||||||
|
Image must be a PNG that is at least 350x350. <br />
|
||||||
|
<input type="file" onchange="angular.element(this).scope().setImageFile(this)" />
|
||||||
|
</p>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a href="#" pfm-popup="image-selector" class="btn btn-small"><i class="icon-picture"></i> Gallery</a>
|
||||||
|
<a href="#" pfm-eat-click ng-click="uploadImage()" class="btn btn-info btn-small"><i class="icon-upload"></i> Upload</a>
|
||||||
|
<a href="#" pfm-eat-click ng-click="clearImage()" class="btn btn-danger btn-small" ng-show="isImageLoaded"><i class="icon-remove"></i></a>
|
||||||
|
</div>
|
||||||
|
<div id="image-selector" class="pfm-popup image-selector">
|
||||||
|
<ul>
|
||||||
|
<li ng-repeat="image in images" ng-click="selectGalleryImage(image)">
|
||||||
|
<img ng-src="{{image.urls.small}}" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="error" ng-show="error != null">{{error}}</div>
|
||||||
|
</div>
|
Loading…
Reference in a new issue