mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2024-11-25 06:27:59 +01:00
Account Settings
This commit is contained in:
parent
2a8bd3c85c
commit
ab3f15b5bf
9 changed files with 236 additions and 17 deletions
38
app/controllers/Api/Web/AccountController.php
Normal file
38
app/controllers/Api/Web/AccountController.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Api\Web;
|
||||
|
||||
use Commands\CreateAlbumCommand;
|
||||
use Commands\DeleteAlbumCommand;
|
||||
use Commands\DeleteTrackCommand;
|
||||
use Commands\EditAlbumCommand;
|
||||
use Commands\EditTrackCommand;
|
||||
use Commands\SaveAccountSettingsCommand;
|
||||
use Cover;
|
||||
use Entities\Album;
|
||||
use Entities\Image;
|
||||
use Entities\Track;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
|
||||
class AccountController extends \ApiControllerBase {
|
||||
public function getSettings() {
|
||||
$user = Auth::user();
|
||||
|
||||
return Response::json([
|
||||
'bio' => $user->bio,
|
||||
'can_see_explicit_content' => $user->can_see_explicit_content == 1,
|
||||
'display_name' => $user->display_name,
|
||||
'sync_names' => $user->sync_names == 1,
|
||||
'mlpforums_name' => $user->mlpforums_name,
|
||||
'gravatar' => $user->gravatar ? $user->gravatar : $user->email,
|
||||
'avatar_url' => !$user->uses_gravatar ? $user->getAvatarUrl() : null,
|
||||
'uses_gravatar' => $user->uses_gravatar == 1
|
||||
], 200);
|
||||
}
|
||||
|
||||
public function postSave() {
|
||||
return $this->execute(new SaveAccountSettingsCommand(Input::all()));
|
||||
}
|
||||
}
|
79
app/models/Commands/SaveAccountSettingsCommand.php
Normal file
79
app/models/Commands/SaveAccountSettingsCommand.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Commands;
|
||||
|
||||
use Entities\Image;
|
||||
use Entities\Track;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class SaveAccountSettingsCommand extends CommandBase {
|
||||
private $_input;
|
||||
|
||||
function __construct($input) {
|
||||
$this->_input = $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() {
|
||||
return Auth::user() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
* @return CommandResponse
|
||||
*/
|
||||
public function execute() {
|
||||
$user = Auth::user();
|
||||
|
||||
$rules = [
|
||||
'display_name' => 'required|min:3|max:26',
|
||||
'bio' => 'textarea_length:250'
|
||||
];
|
||||
|
||||
if ($this->_input['sync_names'] == 'true')
|
||||
$this->_input['display_name'] = $user->mlpforums_name;
|
||||
|
||||
if ($this->_input['uses_gravatar'] == 'true') {
|
||||
$rules['gravatar'] = 'email';
|
||||
} else {
|
||||
$rules['avatar'] = 'image|mimes:png|min_width:350|min_height:350';
|
||||
$rules['avatar_id'] = 'exists:images,id';
|
||||
}
|
||||
|
||||
$validator = Validator::make($this->_input, $rules);
|
||||
|
||||
if ($validator->fails())
|
||||
return CommandResponse::fail($validator);
|
||||
|
||||
if ($this->_input['uses_gravatar'] != 'true') {
|
||||
if ($user->avatar_id == null && !isset($this->_input['avatar']) && !isset($this->_input['avatar_id'])) {
|
||||
$validator->messages()->add('avatar', 'You must upload or select an avatar if you are not using gravatar!');
|
||||
return CommandResponse::fail($validator);
|
||||
}
|
||||
}
|
||||
|
||||
$user->bio = $this->_input['bio'];
|
||||
$user->display_name = $this->_input['display_name'];
|
||||
$user->sync_names = $this->_input['sync_names'] == 'true';
|
||||
$user->can_see_explicit_content = $this->_input['can_see_explicit_content'] == 'true';
|
||||
$user->uses_gravatar = $this->_input['uses_gravatar'] == 'true';
|
||||
|
||||
if ($user->uses_gravatar) {
|
||||
$user->avatar_id = null;
|
||||
$user->gravatar = $this->_input['gravatar'];
|
||||
} else {
|
||||
if (isset($this->_input['avatar_id']))
|
||||
$user->avatar_id = $this->_input['avatar_id'];
|
||||
else if (isset($this->_input['avatar']))
|
||||
$user->avatar_id = Image::upload($this->_input['avatar'], $user)->id;
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
return CommandResponse::succeed();
|
||||
}
|
||||
}
|
|
@ -67,16 +67,16 @@
|
|||
|
||||
protected $table = 'images';
|
||||
|
||||
public function getUrl($type = Cover::NORMAL) {
|
||||
public function getUrl($type = self::NORMAL) {
|
||||
$type = self::$ImageTypes[$type];
|
||||
return URL::to('i' . $this->id . '/' . $type['name'] . '.png');
|
||||
}
|
||||
|
||||
public function getFile($type = Cover::NORMAL) {
|
||||
public function getFile($type = self::NORMAL) {
|
||||
return $this->getDirectory() . '/' . $this->getFilename($type);
|
||||
}
|
||||
|
||||
public function getFilename($type = Cover::NORMAL) {
|
||||
public function getFilename($type = self::NORMAL) {
|
||||
$typeInfo = self::$ImageTypes[$type];
|
||||
return $this->id . '_' . $typeInfo['name'] . '.png';
|
||||
}
|
||||
|
|
|
@ -6,16 +6,14 @@
|
|||
use Gravatar;
|
||||
use Illuminate\Auth\UserInterface;
|
||||
use Illuminate\Auth\Reminders\RemindableInterface;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Ratchet\Wamp\Exception;
|
||||
|
||||
class User extends \Eloquent implements UserInterface, RemindableInterface {
|
||||
protected $table = 'users';
|
||||
protected $hidden = ['password_hash', 'password_salt', 'bio'];
|
||||
|
||||
public function avatar() {
|
||||
return $this->hasOne('Entities\Image');
|
||||
}
|
||||
|
||||
public function cover() {
|
||||
return $this->belongsTo('Entities\Image');
|
||||
}
|
||||
|
||||
|
@ -31,9 +29,9 @@
|
|||
return $this->email;
|
||||
}
|
||||
|
||||
public function getAvatarUrl($type = Cover::NORMAL) {
|
||||
public function getAvatarUrl($type = Image::NORMAL) {
|
||||
if (!$this->uses_gravatar)
|
||||
return $this->cover->getUrl();
|
||||
return $this->avatar->getUrl();
|
||||
|
||||
$email = $this->gravatar;
|
||||
if (!strlen($email))
|
||||
|
@ -42,11 +40,11 @@
|
|||
return Gravatar::getUrl($email, Image::$ImageTypes[$type]['width']);
|
||||
}
|
||||
|
||||
public function getAvatarFile($type = Cover::NORMAL) {
|
||||
public function getAvatarFile($type = Image::NORMAL) {
|
||||
if ($this->uses_gravatar)
|
||||
return $this->user->getAvatar($type);
|
||||
throw new Exception('Cannot get avatar file if this user is configured to use Gravatar!');
|
||||
|
||||
$cover = Cover::$Covers[$type];
|
||||
return URL::to('t' . $this->id . '/cover_' . $cover['name'] . '.png?' . $this->cover_id);
|
||||
$imageType = Image::$ImageTypes[$type];
|
||||
return URL::to('t' . $this->id . '/cover_' . $imageType['name'] . '.png?' . $this->cover_id);
|
||||
}
|
||||
}
|
|
@ -50,9 +50,13 @@
|
|||
Route::post('/playlists/create', 'Api\Web\PlaylistsController@postCreate');
|
||||
Route::post('/playlists/delete/{id}', 'Api\Web\PlaylistsController@postDelete');
|
||||
Route::post('/playlists/edit/{id}', 'Api\Web\PlaylistsController@postEdit');
|
||||
|
||||
Route::post('/account/settings/save', 'Api\Web\AccountController@postSave');
|
||||
});
|
||||
|
||||
Route::group(['before' => 'auth'], function() {
|
||||
Route::get('/account/settings', 'Api\Web\AccountController@getSettings');
|
||||
|
||||
Route::get('/images/owned', 'Api\Web\ImagesController@getOwned');
|
||||
|
||||
Route::get('/tracks/owned', 'Api\Web\TracksController@getOwned');
|
||||
|
|
|
@ -1,5 +1,63 @@
|
|||
angular.module('ponyfm').controller "account-settings", [
|
||||
'$scope', 'auth'
|
||||
($scope, auth) ->
|
||||
$scope.settings = {}
|
||||
$scope.errors = {}
|
||||
$scope.isDirty = false
|
||||
|
||||
$scope.touchModel = () ->
|
||||
$scope.isDirty = true
|
||||
|
||||
$scope.refresh = () ->
|
||||
$.getJSON('/api/web/account/settings')
|
||||
.done (res) -> $scope.$apply ->
|
||||
$scope.settings = res
|
||||
|
||||
$scope.setAvatar = (image, type) ->
|
||||
delete $scope.settings.avatar_id
|
||||
delete $scope.settings.avatar
|
||||
|
||||
if type == 'file'
|
||||
$scope.settings.avatar = image
|
||||
else if type == 'gallery'
|
||||
$scope.settings.avatar_id = image.id
|
||||
|
||||
$scope.isDirty = true
|
||||
|
||||
$scope.updateAccount = () ->
|
||||
return if !$scope.isDirty
|
||||
|
||||
xhr = new XMLHttpRequest()
|
||||
xhr.onload = -> $scope.$apply ->
|
||||
$scope.isSaving = false
|
||||
response = $.parseJSON(xhr.responseText)
|
||||
if xhr.status != 200
|
||||
$scope.errors = {}
|
||||
_.each response.errors, (value, key) -> $scope.errors[key] = value.join ', '
|
||||
return
|
||||
|
||||
$scope.isDirty = false
|
||||
$scope.errors = {}
|
||||
$scope.refresh()
|
||||
|
||||
formData = new FormData()
|
||||
|
||||
_.each $scope.settings, (value, name) ->
|
||||
if name == 'avatar'
|
||||
return if value == null
|
||||
if typeof(value) == 'object'
|
||||
formData.append name, value, value.name
|
||||
else
|
||||
formData.append name, value
|
||||
|
||||
xhr.open 'POST', '/api/web/account/settings/save', true
|
||||
xhr.setRequestHeader 'X-Token', pfm.token
|
||||
$scope.isSaving = true
|
||||
xhr.send formData
|
||||
|
||||
$scope.refresh()
|
||||
|
||||
$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?')
|
||||
]
|
|
@ -15,6 +15,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.account-settings-form {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
ul.playlists {
|
||||
overflow-y: auto;
|
||||
margin: 0px;
|
||||
|
|
|
@ -25,12 +25,12 @@ html body {
|
|||
}
|
||||
|
||||
.site-content-animate-enter {
|
||||
opacity: 0;
|
||||
.transition(all 400ms ease-out);
|
||||
.transform(translate(0, -100%));
|
||||
}
|
||||
|
||||
.site-content-animate-enter.site-content-animate-enter-active {
|
||||
opacity: 1;
|
||||
.transform(translate(0, 0));
|
||||
}
|
||||
|
||||
.site-content-animate-leave {
|
||||
|
@ -39,8 +39,7 @@ html body {
|
|||
}
|
||||
|
||||
.site-content-animate-leave.site-content-animate-leave-active {
|
||||
opacity: .5;
|
||||
.transform(scale(.95));
|
||||
.transform(translate(0, 100%));
|
||||
}
|
||||
|
||||
header {
|
||||
|
|
|
@ -1,3 +1,42 @@
|
|||
<div>
|
||||
<h1>Account Settings</h1>
|
||||
<form ng-submit="updateAccount()" class="pfm-form account-settings-form">
|
||||
<ul class="toolbar">
|
||||
<li>
|
||||
<button type="submit" class="btn" ng-class="{disabled: !isDirty || isSaving, 'btn-primary': isDirty}">
|
||||
Save Changes
|
||||
<i ng-show="isSaving" class="icon-cog icon-spin icon-large"></i>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="stretch-to-bottom">
|
||||
<div class="form-row" ng-class="{'has-error': errors.display_name != null}">
|
||||
<label for="sync_names" class="strong"><input ng-disabled="isSaving" ng-change="touchModel();" id="sync_names" type="checkbox" ng-model="settings.sync_names" /> Sync my MLP Forums display name with Pony.fm</label>
|
||||
<input type="text" ng-disabled="isSaving" ng-change="touchModel()" ng-show="!settings.sync_names" placeholder="Display Name" id="display_name" ng-model="settings.display_name" />
|
||||
<div ng-show="settings.sync_names" class="alert alert-info">Your current MLP Forums display name is <strong>{{settings.mlpforums_name}}</strong></div>
|
||||
<div class="error">{{errors.display_name}}</div>
|
||||
</div>
|
||||
<div class="form-row" ng-class="{'has-error': errors.bio != null}">
|
||||
<label class="strong" for="bio">Bio</label>
|
||||
<textarea id="bio" placeholder="bio (optional)" ng-model="settings.bio" ng-disabled="isLoading" ng-change="touchModel()"></textarea>
|
||||
<div class="error">{{errors.description}}</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="form-row span6" ng-class="{'has-error': errors.avatar != null || errors.gravatar != null}">
|
||||
<label for="uses_gravatar">
|
||||
<input ng-change="touchModel()" ng-disabled="isLoading" id="uses_gravatar" type="checkbox" ng-model="settings.uses_gravatar" /> Use Gravatar
|
||||
</label>
|
||||
<div ng-show="!settings.uses_gravatar">
|
||||
<pfm-image-upload set-image="setAvatar" image="settings.avatar_url" />
|
||||
</div>
|
||||
<input type="text" ng-disabled="isSaving" ng-change="touchModel()" ng-show="settings.uses_gravatar" placeholder="Gravatar Email" ng-model="settings.gravatar" />
|
||||
<div class="error" ng-show="errors.avatar != null">{{errors.avatar}}</div>
|
||||
<div class="error" ng-show="errors.gravatar != null">{{errors.gravatar}}</div>
|
||||
</div>
|
||||
<div class="form-row span6">
|
||||
<label for="can_see_explicit_content"><input ng-change="touchModel()" ng-disabled="isLoading" id="can_see_explicit_content" type="checkbox" ng-model="settings.can_see_explicit_content" /> Can See Explicit Content</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
Loading…
Reference in a new issue