From bf831d839a765aca23f7e5f8727bcab7e8cc4e73 Mon Sep 17 00:00:00 2001 From: Peter Deltchev Date: Wed, 6 Jan 2016 04:50:44 -0800 Subject: [PATCH] #20: Added the genre creation tool. --- app/Commands/CreateGenreCommand.php | 75 +++++++++++++++++ .../Controllers/Api/Web/GenresController.php | 6 ++ app/Http/routes.php | 1 + app/Models/Genre.php | 2 - app/Providers/AuthServiceProvider.php | 4 + ...2016_01_06_123513_add_genre_timestamps.php | 49 +++++++++++ public/templates/admin/genres.html | 84 ++++++++++++------- .../app/controllers/admin-genres.coffee | 20 +++++ .../scripts/app/services/admin-genres.coffee | 11 +++ resources/assets/styles/admin.less | 3 + resources/assets/styles/body.less | 6 +- 11 files changed, 227 insertions(+), 34 deletions(-) create mode 100644 app/Commands/CreateGenreCommand.php create mode 100644 database/migrations/2016_01_06_123513_add_genre_timestamps.php diff --git a/app/Commands/CreateGenreCommand.php b/app/Commands/CreateGenreCommand.php new file mode 100644 index 00000000..23e7d2df --- /dev/null +++ b/app/Commands/CreateGenreCommand.php @@ -0,0 +1,75 @@ +. + */ + +namespace Poniverse\Ponyfm\Commands; + +use Gate; +use Illuminate\Support\Str; +use Poniverse\Ponyfm\Models\Genre; +use Validator; + +class CreateGenreCommand extends CommandBase +{ + /** @var Genre */ + private $_genreName; + + public function __construct($genreName) + { + $this->_genreName = $genreName; + } + + /** + * @return bool + */ + public function authorize() + { + return Gate::allows('create-genre'); + } + + /** + * @throws \Exception + * @return CommandResponse + */ + public function execute() + { + $slug = Str::slug($this->_genreName); + + $rules = [ + 'name' => 'required|unique:genres,name,NULL,id,deleted_at,NULL|max:50', + 'slug' => 'required|unique:genres,slug,NULL,id,deleted_at,NULL' + ]; + + $validator = Validator::make([ + 'name' => $this->_genreName, + 'slug' => $slug + ], $rules); + + if ($validator->fails()) { + return CommandResponse::fail($validator); + } + + Genre::create([ + 'name' => $this->_genreName, + 'slug' => $slug + ]); + + return CommandResponse::succeed(['message' => 'Genre created!']); + } +} diff --git a/app/Http/Controllers/Api/Web/GenresController.php b/app/Http/Controllers/Api/Web/GenresController.php index 1d00b956..0de4fb38 100644 --- a/app/Http/Controllers/Api/Web/GenresController.php +++ b/app/Http/Controllers/Api/Web/GenresController.php @@ -21,6 +21,7 @@ namespace Poniverse\Ponyfm\Http\Controllers\Api\Web; use Input; +use Poniverse\Ponyfm\Commands\CreateGenreCommand; use Poniverse\Ponyfm\Commands\DeleteGenreCommand; use Poniverse\Ponyfm\Commands\RenameGenreCommand; use Poniverse\Ponyfm\Models\Genre; @@ -45,6 +46,11 @@ class GenresController extends ApiControllerBase ], 200); } + public function postCreate() + { + $command = new CreateGenreCommand(Input::get('name')); + return $this->execute($command); + } public function putRename($genreId) { diff --git a/app/Http/routes.php b/app/Http/routes.php index 64842676..ec54763b 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -153,6 +153,7 @@ Route::group(['prefix' => 'api/web'], function() { Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'can:access-admin-area']], function() { Route::get('/genres', 'Api\Web\GenresController@getIndex'); + Route::post('/genres', 'Api\Web\GenresController@postCreate'); Route::put('/genres/{id}', 'Api\Web\GenresController@putRename')->where('id', '\d+'); Route::delete('/genres/{id}', 'Api\Web\GenresController@deleteGenre')->where('id', '\d+'); }); diff --git a/app/Models/Genre.php b/app/Models/Genre.php index 1d1f3914..967bf7b3 100644 --- a/app/Models/Genre.php +++ b/app/Models/Genre.php @@ -49,8 +49,6 @@ class Genre extends Model protected $appends = ['track_count', 'url']; protected $hidden = ['trackCountRelation']; - public $timestamps = false; - use SlugTrait, SoftDeletes, RevisionableTrait; public function tracks(){ diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 820d57e3..96b1b6c1 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -52,6 +52,10 @@ class AuthServiceProvider extends ServiceProvider return $user->hasRole('admin'); }); + $gate->define('create-genre', function(User $user) { + return $user->hasRole('admin'); + }); + $this->registerPolicies($gate); } } diff --git a/database/migrations/2016_01_06_123513_add_genre_timestamps.php b/database/migrations/2016_01_06_123513_add_genre_timestamps.php new file mode 100644 index 00000000..207e50b2 --- /dev/null +++ b/database/migrations/2016_01_06_123513_add_genre_timestamps.php @@ -0,0 +1,49 @@ +. + */ + +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +class AddGenreTimestamps extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::table('genres', function(Blueprint $table) { + $table->nullableTimestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('genres', function(Blueprint $table) { + $table->dropTimestamps(); + }); + } +} diff --git a/public/templates/admin/genres.html b/public/templates/admin/genres.html index acb709e5..b307d26f 100644 --- a/public/templates/admin/genres.html +++ b/public/templates/admin/genres.html @@ -1,33 +1,55 @@

Genre Editor

-
- - - - - - - - - - - - - -
Genre# of tracks (including deleted)Actions
- -
- {{ genre.errorMessage }} -
-
{{ genre.track_count }} - - - -
-
+
+ +
+

Add genre

+ +

Enter a genre name and press enter to create it!

+ + +
+ {{ createGenreError }} +
+
+ +
+

Rename & delete genres

+ + + + + + + + + + + + + + +
Genre# of tracks (including deleted)Actions
+ +
+ {{ genre.errorMessage }} +
+
{{ genre.track_count }} + + + +
+
+
diff --git a/resources/assets/scripts/app/controllers/admin-genres.coffee b/resources/assets/scripts/app/controllers/admin-genres.coffee index 4893ecc0..4677ff15 100644 --- a/resources/assets/scripts/app/controllers/admin-genres.coffee +++ b/resources/assets/scripts/app/controllers/admin-genres.coffee @@ -20,6 +20,11 @@ angular.module('ponyfm').controller 'admin-genres', [ $scope.genres = [] + $scope.isCreating = false + $scope.genreToCreate = '' + $scope.hasCreationError = false + $scope.createGenreError = '' + # Used for merging/deleting genres $scope.mergeInProgress = false $scope.genreToDelete = null @@ -37,6 +42,21 @@ angular.module('ponyfm').controller 'admin-genres', [ loadGenres() + $scope.createGenre = (genreName) -> + $scope.isCreating = true + genres.create(genreName) + .done (response) -> + $scope.hasCreationError = false + $scope.genreToCreate = '' + loadGenres() + .fail (response) -> + $scope.hasCreationError = true + $scope.createGenreError = response + console.log(response) + .always (response) -> + $scope.isCreating = false + + # Renames the given genre $scope.renameGenre = (genre) -> genre.isSaving = true diff --git a/resources/assets/scripts/app/services/admin-genres.coffee b/resources/assets/scripts/app/services/admin-genres.coffee index 4aa28c89..0e91f94e 100644 --- a/resources/assets/scripts/app/services/admin-genres.coffee +++ b/resources/assets/scripts/app/services/admin-genres.coffee @@ -28,6 +28,17 @@ angular.module('ponyfm').factory('admin-genres', [ def.resolve(genres['genres']) def.promise() + create: (name) -> + url = '/api/web/admin/genres' + def = new $.Deferred() + $http.post(url, {name: name}) + .success (response) -> + def.resolve(response) + .error (response) -> + def.reject(response) + + def.promise() + rename: (genre_id, new_name) -> url = "/api/web/admin/genres/#{genre_id}" def = new $.Deferred() diff --git a/resources/assets/styles/admin.less b/resources/assets/styles/admin.less index eaae7f6a..5fdeba59 100644 --- a/resources/assets/styles/admin.less +++ b/resources/assets/styles/admin.less @@ -19,6 +19,9 @@ @import 'base/bootstrap/bootstrap'; @import 'mixins'; +.genre-creator { + max-width: 400px; +} .genre-list { .-status { diff --git a/resources/assets/styles/body.less b/resources/assets/styles/body.less index dd16d1b9..8ed21270 100644 --- a/resources/assets/styles/body.less +++ b/resources/assets/styles/body.less @@ -31,7 +31,7 @@ a { .box-sizing(border-box); padding: 10px; - h1 { + h1, h2 { margin: 1px 1px 5px; font-size: 15pt; color: #C2889C; @@ -39,6 +39,10 @@ a { overflow: hidden; font-weight: normal; } + + h2 { + font-size: 14pt; + } } .static-page {