Merge pull request #70 from Poniverse/feature/moderate-profiles

Feature/moderate profiles
This commit is contained in:
Peter Deltchev 2016-03-19 01:15:22 -07:00
commit d3ea7cccb6
26 changed files with 125 additions and 258 deletions

View file

@ -34,6 +34,7 @@ class AccountController extends ApiControllerBase
$user = Auth::user();
return Response::json([
'id' => $user->id,
'bio' => $user->bio,
'can_see_explicit_content' => $user->can_see_explicit_content == 1,
'display_name' => $user->display_name,

View file

@ -20,6 +20,7 @@
namespace Poniverse\Ponyfm\Http\Controllers\Api\Web;
use Gate;
use Poniverse\Ponyfm\Models\Album;
use Poniverse\Ponyfm\Models\Comment;
use Poniverse\Ponyfm\Models\Favourite;
@ -158,7 +159,7 @@ class ArtistsController extends ApiControllerBase
return Response::json([
'artist' => [
'id' => (int)$user->id,
'id' => $user->id,
'name' => $user->display_name,
'slug' => $user->slug,
'is_archived' => (bool)$user->is_archived,
@ -174,7 +175,10 @@ class ArtistsController extends ApiControllerBase
'bio' => $user->bio,
'mlpforums_username' => $user->username,
'message_url' => $user->message_url,
'user_data' => $userData
'user_data' => $userData,
'permissions' => [
'edit' => Gate::allows('edit', $user)
]
]
], 200);
}

View file

@ -1,41 +0,0 @@
<?php
/**
* Pony.fm - A community for pony fan music.
* Copyright (C) 2015 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/>.
*/
namespace Poniverse\Ponyfm\Http\Controllers;
use View;
class FavouritesController extends Controller
{
public function getTracks()
{
return View::make('shared.null');
}
public function getAlbums()
{
return View::make('shared.null');
}
public function getPlaylists()
{
return View::make('shared.null');
}
}

View file

@ -158,22 +158,6 @@ Route::group(['prefix' => 'api/web'], function() {
Route::post('/auth/logout', 'Api\Web\AuthController@postLogout');
});
Route::group(['prefix' => 'account', 'middleware' => 'auth'], function() {
Route::get('/favourites/tracks', 'FavouritesController@getTracks');
Route::get('/favourites/albums', 'FavouritesController@getAlbums');
Route::get('/favourites/playlists', 'FavouritesController@getPlaylists');
Route::get('/tracks', 'ContentController@getTracks');
Route::get('/tracks/edit/{id}', 'ContentController@getTracks');
Route::get('/albums', 'ContentController@getAlbums');
Route::get('/albums/edit/{id}', 'ContentController@getAlbums');
Route::get('/albums/create', 'ContentController@getAlbums');
Route::get('/playlists', 'ContentController@getPlaylists');
Route::get('/uploader', 'UploaderController@getIndex');
Route::get('/', 'AccountController@getIndex');
});
Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'can:access-admin-area']], function() {
Route::get('/genres', 'AdminController@getGenres');
@ -182,9 +166,27 @@ Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'can:access-admin-ar
Route::get('u{id}', 'ArtistsController@getShortlink')->where('id', '\d+');
Route::get('users/{id}-{slug}', 'ArtistsController@getShortlink')->where('id', '\d+');
Route::get('{slug}', 'ArtistsController@getProfile');
Route::get('{slug}/content', 'ArtistsController@getContent');
Route::get('{slug}/favourites', 'ArtistsController@getFavourites');
Route::group(['prefix' => '{slug}'], function() {
Route::get('/', 'ArtistsController@getProfile');
Route::get('/content', 'ArtistsController@getContent');
Route::get('/favourites', 'ArtistsController@getFavourites');
Route::group(['prefix' => 'account', 'middleware' => 'auth'], function() {
Route::get('/tracks', 'ContentController@getTracks');
Route::get('/tracks/edit/{id}', 'ContentController@getTracks');
Route::get('/albums', 'ContentController@getAlbums');
Route::get('/albums/edit/{id}', 'ContentController@getAlbums');
Route::get('/albums/create', 'ContentController@getAlbums');
Route::get('/playlists', 'ContentController@getPlaylists');
Route::get('/uploader', 'UploaderController@getIndex');
Route::get('/', 'AccountController@getIndex');
});
});
Route::get('/', 'HomeController@getIndex');

View file

@ -241,7 +241,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
* @param string $roleName
* @return bool
*/
public function hasRole($roleName)
public function hasRole($roleName):bool
{
foreach ($this->roles as $role) {
if ($role->name === $roleName) {

View file

@ -31,4 +31,8 @@ class UserPolicy
public function getImages(User $userToAuthorize, User $user) {
return $userToAuthorize->id === $user->id || $userToAuthorize->hasRole('admin');
}
public function edit(User $userToAuthorize, User $user) {
return $userToAuthorize->id === $user->id;
}
}

View file

@ -1,8 +1,19 @@
<ul class="tabs">
<li ng-class="{active: stateIncludes('account.tracks')}"><a href="/account/tracks">Tracks</a></li>
<li ng-class="{active: stateIncludes('account.albums')}"><a href="/account/albums">Albums</a></li>
<li ng-class="{active: stateIncludes('account.playlists')}"><a href="/account/playlists">Playlists</a></li>
<li ng-class="{active: stateIncludes('account.settings')}"><a href="/account">Settings</a></li>
<li ui-sref-active="active">
<a ui-sref=".uploader">Upload music!</a>
</li>
<li ui-sref-active="active">
<a ui-sref=".tracks">Tracks</a>
</li>
<li ui-sref-active="active">
<a ui-sref=".albums">Albums</a>
</li>
<li ui-sref-active="active">
<a ui-sref=".playlists">Playlists</a>
</li>
<li ui-sref-active="active">
<a ui-sref=".settings">Settings</a>
</li>
</ul>
<ui-view></ui-view>

View file

@ -22,7 +22,7 @@
</div>
<div class="form-row" ng-class="{'has-error': errors.cover != null}">
<label class="strong">Album Cover: </label>
<pfm-image-upload set-image="setCover" image="album.cover" />
<pfm-image-upload set-image="setCover" image="album.cover" user-id="album.user_id"></pfm-image-upload>
</div>
<div class="form-row track-selector">
<a pfm-popup="track-selector,right" pfm-popup-close-on-click href="#" class="btn btn-small pull-right btn-info">Add Tracks</a>

View file

@ -1,7 +1,7 @@
<div>
<ul class="dropdowns">
<li class="dropdown">
<a class="btn" href="/account/albums/create" ng-class="{'btn-primary': data.isEditorOpen && data.selectedAlbum == null}">
<a class="btn" ui-sref=".create" ng-class="{'btn-primary': data.isEditorOpen && data.selectedAlbum == null}">
<i class="icon-plus"></i> Create Album
</a>
</li>
@ -11,7 +11,7 @@
<div class="list">
<ul class="account-albums-listing stretch-to-bottom">
<li ng-repeat="album in albums track by album.id" ng-class="{selected: album.id == data.selectedAlbum.id}">
<a href="/account/albums/edit/{{album.id}}">
<a ui-sref=".edit({album_id: {{::album.id}}})">
<img pfm-src-loader="album.covers.normal" pfm-src-size="normal" class="image" />
<span class="title">{{album.title}}</span>
<span class="published">{{album.created_at | date:'MM/dd/yyyy'}}</span>

View file

@ -27,7 +27,7 @@
<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" />
<pfm-image-upload set-image="setAvatar" image="settings.avatar_url" user-id="settings.id"></pfm-image-upload>
</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>

View file

@ -2,7 +2,7 @@
<div class="list">
<ul class="account-tracks-listing stretch-to-bottom">
<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 ui-sref=".edit({track_id: {{::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 | date:'MM/dd/yyyy'}}</span>

View file

@ -10,11 +10,12 @@
<header>
<h1>{{::artist.name}}</h1>
<ul class="tabs">
<li ng-class="{active: stateIncludes('content.artist.profile')}"><a ng-href="{{::artist.slug}}">Profile</a></li>
<li ng-class="{active: stateIncludes('content.artist.content')}"><a ng-href="{{::artist.slug}}/content">Content</a></li>
<li ng-hide="::artist.is_archived" ng-class="::{active: stateIncludes('content.artist.favourites')}">
<a ng-href="{{::artist.slug}}/favourites">Favourites</a>
<li ui-sref-active="active"><a ui-sref=".profile">Profile</a></li>
<li ui-sref-active="active"><a ui-sref=".content">Content</a></li>
<li ng-if="::!artist.is_archived" ui-sref-active="active">
<a ui-sref=".favourites">Favourites</a>
</li>
<li ng-if="::artist.permissions.edit" ui-sref-active="{active: '.account'}"><a ui-sref=".account.settings">Manage Account</a></li>
</ul>
</header>
<div class="stretch-to-bottom">

View file

@ -18,6 +18,6 @@
</div>
<div class="span6 cover-image">
<h2>Recent Tracks</h2>
<pfm-tracks-list tracks="::artist.latest_tracks" class="two-columns no-artist" />
<pfm-tracks-list tracks="::artist.latest_tracks" class="two-columns no-artist"></pfm-tracks-list>
</div>
</div>

View file

@ -1,9 +0,0 @@
<div>
<ul class="tabs">
<li ng-class="{active: stateIncludes('favourites.tracks')}"><a href="/account/favourites/tracks">Tracks</a></li>
<li ng-class="{active: stateIncludes('favourites.albums')}"><a href="/account/favourites/albums">Albums</a></li>
<li ng-class="{active: stateIncludes('favourites.playlists')}"><a href="/account/favourites/playlists">Playlists</a></li>
</ul>
<ui-view></ui-view>
</div>

View file

@ -1,3 +0,0 @@
<div class="stretch-to-bottom">
<pfm-albums-list albums="albums" />
</div>

View file

@ -1,3 +0,0 @@
<div class="stretch-to-bottom">
<pfm-playlists-list playlists="playlists"></pfm-playlists-list>
</div>

View file

@ -1,3 +0,0 @@
<div class="stretch-to-bottom">
<pfm-tracks-list tracks="tracks" class="three-columns"></pfm-tracks-list>
</div>

View file

@ -24,7 +24,7 @@
</span>
<span ng-show="upload.success">
<a href="/account/tracks/edit/{{upload.trackId}}" class="btn btn-small btn-primary">
<a ui-sref="content.artist.account.tracks.edit({slug: auth.user.slug, track_id: upload.trackId})" class="btn btn-small btn-primary">
Publish
</a>
{{upload.name}}

View file

@ -141,75 +141,6 @@ ponyfm.config [
url: '/errors/invalid'
templateUrl: '/templates/errors/400.html'
# Upload
state.state 'uploader',
url: '/account/uploader'
templateUrl: '/templates/uploader/index.html'
controller: 'uploader'
# Account
state.state 'account',
url: '/account'
abstract: true
templateUrl: '/templates/account/_layout.html'
state.state 'account.settings',
url: ''
templateUrl: '/templates/account/settings.html'
controller: 'account-settings'
state.state 'account.tracks',
url: '/tracks'
templateUrl: '/templates/account/tracks.html'
controller: 'account-tracks'
state.state 'account.tracks.edit',
url: '/edit/:track_id'
templateUrl: '/templates/account/track.html'
controller: 'account-track'
state.state 'account.albums',
url: '/albums'
templateUrl: '/templates/account/albums.html'
controller: 'account-albums'
state.state 'account.albums.create',
url: '/create'
templateUrl: '/templates/account/album.html'
controller: 'account-albums-edit'
state.state 'account.albums.edit',
url: '/edit/:album_id'
templateUrl: '/templates/account/album.html'
controller: 'account-albums-edit'
state.state 'account.playlists',
url: '/playlists'
templateUrl: '/templates/account/playlists.html'
controller: 'account-playlists'
state.state 'favourites',
url: '/account/favourites'
abstract: true
templateUrl: '/templates/favourites/_layout.html'
state.state 'favourites.tracks',
url: '/tracks'
templateUrl: '/templates/favourites/tracks.html'
controller: 'favourites-tracks'
state.state 'favourites.playlists',
url: '/playlists'
templateUrl: '/templates/favourites/playlists.html'
controller: 'favourites-playlists'
state.state 'favourites.albums',
url: '/albums'
templateUrl: '/templates/favourites/albums.html'
controller: 'favourites-albums'
# Tracks
state.state 'content',
@ -368,6 +299,57 @@ ponyfm.config [
templateUrl: '/templates/artists/favourites.html'
controller: 'artist-favourites'
# Account
state.state 'content.artist.account',
url: '/account'
abstract: true
templateUrl: '/templates/account/_layout.html'
# Upload
state.state 'content.artist.account.uploader',
url: '/uploader'
templateUrl: '/templates/uploader/index.html'
controller: 'uploader'
state.state 'content.artist.account.settings',
url: ''
templateUrl: '/templates/account/settings.html'
controller: 'account-settings'
state.state 'content.artist.account.tracks',
url: '/tracks'
templateUrl: '/templates/account/tracks.html'
controller: 'account-tracks'
state.state 'content.artist.account.tracks.edit',
url: '/edit/:track_id'
templateUrl: '/templates/account/track.html'
controller: 'account-track'
state.state 'content.artist.account.albums',
url: '/albums'
templateUrl: '/templates/account/albums.html'
controller: 'account-albums'
state.state 'content.artist.account.albums.create',
url: '/create'
templateUrl: '/templates/account/album.html'
controller: 'account-albums-edit'
state.state 'content.artist.account.albums.edit',
url: '/edit/:album_id'
templateUrl: '/templates/account/album.html'
controller: 'account-albums-edit'
state.state 'content.artist.account.playlists',
url: '/playlists'
templateUrl: '/templates/account/playlists.html'
controller: 'account-playlists'
location.html5Mode(true);
$dialogProvider.options
dialogFade: true

View file

@ -89,7 +89,7 @@ module.exports = angular.module('ponyfm').controller "account-albums-edit", [
if $scope.isNew
$scope.isDirty = false
$scope.$emit 'album-created'
$state.transitionTo 'account.albums.edit', {album_id: response.id}
$state.go '^.edit', {album_id: response.id}
else
$scope.isDirty = false
$scope.data.selectedAlbum.title = $scope.album.title
@ -120,7 +120,7 @@ module.exports = angular.module('ponyfm').controller "account-albums-edit", [
$.post('/api/web/albums/delete/' + $scope.album.id)
.then -> $scope.$apply ->
$scope.$emit 'album-deleted'
$state.transitionTo 'account.albums'
$state.go '^'
$scope.setCover = (image, type) ->
delete $scope.album.cover_id
@ -139,6 +139,7 @@ module.exports = angular.module('ponyfm').controller "account-albums-edit", [
albums.getEdit($state.params.album_id).done (album) ->
$scope.album =
id: album.id
user_id: album.user_id
title: album.title
description: album.description
remove_cover: false

View file

@ -15,9 +15,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
window.pfm.preloaders['account-albums'] = [
'account-tracks', 'account-albums'
(tracks, albums) ->
$.when.all [tracks.refresh('published=true&in_album=false', true), albums.refresh(true)]
'account-tracks'
(tracks) ->
tracks.refresh('published=true&in_album=false', true)
]
module.exports = angular.module('ponyfm').controller "account-albums", [

View file

@ -55,4 +55,8 @@ module.exports = angular.module('ponyfm').controller "account-tracks", [
$state.transitionTo 'account.tracks'
tracks.clearCache()
tracks.refresh(null, true).done setTracks
$scope.$on 'track-updated', () ->
tracks.clearCache()
tracks.refresh(null, true).done setTracks
]

View file

@ -1,28 +0,0 @@
# Pony.fm - A community for pony fan music.
# Copyright (C) 2015 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/>.
window.pfm.preloaders['favourites-albums'] = [
'favourites'
(favourites) ->
favourites.fetchAlbums(true)
]
module.exports = angular.module('ponyfm').controller "favourites-albums", [
'$scope', 'favourites'
($scope, favourites) ->
favourites.fetchAlbums().done (res) ->
$scope.albums = res.albums
]

View file

@ -1,28 +0,0 @@
# Pony.fm - A community for pony fan music.
# Copyright (C) 2015 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/>.
window.pfm.preloaders['favourites-playlists'] = [
'favourites'
(favourites) ->
favourites.fetchPlaylists(true)
]
module.exports = angular.module('ponyfm').controller "favourites-playlists", [
'$scope', 'favourites'
($scope, favourites) ->
favourites.fetchPlaylists().done (res) ->
$scope.playlists = res.playlists
]

View file

@ -1,28 +0,0 @@
# Pony.fm - A community for pony fan music.
# Copyright (C) 2015 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/>.
window.pfm.preloaders['favourites-tracks'] = [
'favourites'
(favourites) ->
favourites.fetchTracks(true)
]
module.exports = angular.module('ponyfm').controller "favourites-tracks", [
'$scope', 'favourites'
($scope, favourites) ->
favourites.fetchTracks().done (res) ->
$scope.tracks = res.tracks
]

View file

@ -54,8 +54,8 @@
</a>
<ul class="dropdown-menu">
<li><a href="{{Auth::user()->url}}">Your Profile</a></li>
<li ng-class="{active: stateIncludes('favourites')}"><a href="/account/favourites/tracks">Favourites</a></li>
<li ng-class="{active: stateIncludes('account')}"><a href="/account/tracks">Account</a></li>
<li ui-sref-active="active"><a ui-sref="content.artist.favourites({slug: auth.user.slug})">Favourites</a></li>
<li ui-sref-active="active"><a ui-sref="content.artist.account.settings({slug: auth.user.slug})">Account</a></li>
<li><a href="#" pfm-eat-click ng-click="logout()">Logout</a></li>
</ul>
</div>
@ -77,8 +77,8 @@
<li><a href="https://mlpforums.com/forum/62-ponyfm/" title="Pony.fm Forum" target="_blank">Forum</a></li>
@if (Auth::check())
<li class="uploader" ng-class="{selected: stateIncludes('uploader')}">
<a href="/account/uploader">Upload Music</a>
<li class="uploader" ui-sref-active="selected">
<a ui-sref="content.artist.account.uploader({slug: auth.user.slug})">Upload Music</a>
</li>
@can('access-admin-area')