mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2024-11-22 04:58:01 +01:00
#20: Implemented the genre merging tool.
This commit is contained in:
parent
3ba8467870
commit
07bb5e2c3a
18 changed files with 404 additions and 15 deletions
76
app/Commands/DeleteGenreCommand.php
Normal file
76
app/Commands/DeleteGenreCommand.php
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<?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\Commands;
|
||||||
|
|
||||||
|
use Gate;
|
||||||
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
|
use Poniverse\Ponyfm\Genre;
|
||||||
|
use Poniverse\Ponyfm\Jobs\DeleteGenre;
|
||||||
|
use Validator;
|
||||||
|
|
||||||
|
class DeleteGenreCommand extends CommandBase
|
||||||
|
{
|
||||||
|
use DispatchesJobs;
|
||||||
|
|
||||||
|
|
||||||
|
/** @var Genre */
|
||||||
|
private $_genreToDelete;
|
||||||
|
private $_destinationGenre;
|
||||||
|
|
||||||
|
public function __construct($genreId, $destinationGenreId) {
|
||||||
|
$this->_genreToDelete = Genre::find($genreId);
|
||||||
|
$this->_destinationGenre = Genre::find($destinationGenreId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize() {
|
||||||
|
return Gate::allows('delete', $this->_genreToDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
* @return CommandResponse
|
||||||
|
*/
|
||||||
|
public function execute() {
|
||||||
|
$rules = [
|
||||||
|
'genre_to_delete' => 'required',
|
||||||
|
'destination_genre' => 'required',
|
||||||
|
];
|
||||||
|
|
||||||
|
// The validation will fail if the genres don't exist
|
||||||
|
// because they'll be null.
|
||||||
|
$validator = Validator::make([
|
||||||
|
'genre_to_delete' => $this->_genreToDelete,
|
||||||
|
'destination_genre' => $this->_destinationGenre,
|
||||||
|
], $rules);
|
||||||
|
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return CommandResponse::fail($validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->dispatch(new DeleteGenre($this->_genreToDelete, $this->_destinationGenre));
|
||||||
|
|
||||||
|
return CommandResponse::succeed(['message' => 'Genre deleted!']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,7 +33,7 @@ class RenameGenreCommand extends CommandBase
|
||||||
|
|
||||||
public function __construct($genreId, $newName)
|
public function __construct($genreId, $newName)
|
||||||
{
|
{
|
||||||
$this->_genre = Genre::find($genreId);;
|
$this->_genre = Genre::find($genreId);
|
||||||
$this->_newName = $newName;
|
$this->_newName = $newName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace Poniverse\Ponyfm;
|
||||||
|
|
||||||
use DB;
|
use DB;
|
||||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Poniverse\Ponyfm\Traits\SlugTrait;
|
use Poniverse\Ponyfm\Traits\SlugTrait;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use URL;
|
use URL;
|
||||||
|
@ -30,13 +31,14 @@ use Venturecraft\Revisionable\RevisionableTrait;
|
||||||
class Genre extends Model
|
class Genre extends Model
|
||||||
{
|
{
|
||||||
protected $table = 'genres';
|
protected $table = 'genres';
|
||||||
|
|
||||||
protected $fillable = ['name', 'slug'];
|
protected $fillable = ['name', 'slug'];
|
||||||
protected $appends = ['track_count', 'url'];
|
protected $appends = ['track_count', 'url'];
|
||||||
protected $hidden = ['trackCountRelation'];
|
protected $hidden = ['trackCountRelation'];
|
||||||
|
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
use SlugTrait, RevisionableTrait;
|
use SlugTrait, SoftDeletes, RevisionableTrait;
|
||||||
|
|
||||||
public function tracks(){
|
public function tracks(){
|
||||||
return $this->hasMany(Track::class, 'genre_id');
|
return $this->hasMany(Track::class, 'genre_id');
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
namespace Poniverse\Ponyfm\Http\Controllers\Api\Web;
|
namespace Poniverse\Ponyfm\Http\Controllers\Api\Web;
|
||||||
|
|
||||||
use Input;
|
use Input;
|
||||||
|
use Poniverse\Ponyfm\Commands\DeleteGenreCommand;
|
||||||
use Poniverse\Ponyfm\Commands\RenameGenreCommand;
|
use Poniverse\Ponyfm\Commands\RenameGenreCommand;
|
||||||
use Poniverse\Ponyfm\Genre;
|
use Poniverse\Ponyfm\Genre;
|
||||||
use Poniverse\Ponyfm\Http\Controllers\ApiControllerBase;
|
use Poniverse\Ponyfm\Http\Controllers\ApiControllerBase;
|
||||||
|
@ -50,4 +51,11 @@ class GenresController extends ApiControllerBase
|
||||||
$command = new RenameGenreCommand($genreId, Input::get('name'));
|
$command = new RenameGenreCommand($genreId, Input::get('name'));
|
||||||
return $this->execute($command);
|
return $this->execute($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function deleteGenre($genreId)
|
||||||
|
{
|
||||||
|
$command = new DeleteGenreCommand($genreId, Input::get('destination_genre_id'));
|
||||||
|
return $this->execute($command);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,7 @@ Route::group(['prefix' => 'api/web'], function() {
|
||||||
Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'can:access-admin-area']], function() {
|
Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'can:access-admin-area']], function() {
|
||||||
Route::get('/genres', 'Api\Web\GenresController@getIndex');
|
Route::get('/genres', 'Api\Web\GenresController@getIndex');
|
||||||
Route::put('/genres/{id}', 'Api\Web\GenresController@putRename')->where('id', '\d+');
|
Route::put('/genres/{id}', 'Api\Web\GenresController@putRename')->where('id', '\d+');
|
||||||
|
Route::delete('/genres/{id}', 'Api\Web\GenresController@deleteGenre')->where('id', '\d+');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::post('/auth/logout', 'Api\Web\AuthController@postLogout');
|
Route::post('/auth/logout', 'Api\Web\AuthController@postLogout');
|
||||||
|
|
78
app/Jobs/DeleteGenre.php
Normal file
78
app/Jobs/DeleteGenre.php
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?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\Jobs;
|
||||||
|
|
||||||
|
use Auth;
|
||||||
|
use Poniverse\Ponyfm\Genre;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Contracts\Bus\SelfHandling;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Poniverse\Ponyfm\Track;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
class DeleteGenre extends Job implements SelfHandling, ShouldQueue
|
||||||
|
{
|
||||||
|
use InteractsWithQueue, SerializesModels;
|
||||||
|
|
||||||
|
protected $executingUser;
|
||||||
|
protected $genreToDelete;
|
||||||
|
protected $destinationGenre;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @param Genre $genreToDelete
|
||||||
|
* @param Genre $destinationGenre
|
||||||
|
*/
|
||||||
|
public function __construct(Genre $genreToDelete, Genre $destinationGenre)
|
||||||
|
{
|
||||||
|
$this->executingUser = Auth::user();
|
||||||
|
$this->genreToDelete = $genreToDelete;
|
||||||
|
$this->destinationGenre = $destinationGenre;
|
||||||
|
|
||||||
|
// The genre is deleted synchronously before the job is executed in
|
||||||
|
// order to prevent race conditions.
|
||||||
|
$this->genreToDelete->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
// The user who kicked off this job is used when generating revision log entries.
|
||||||
|
Auth::login($this->executingUser);
|
||||||
|
|
||||||
|
// This is done instead of a single UPDATE query in order to
|
||||||
|
// generate revision logs for the change.
|
||||||
|
$this->genreToDelete->tracks()->chunk(200, function ($tracks) {
|
||||||
|
foreach ($tracks as $track) {
|
||||||
|
/** @var Track $track */
|
||||||
|
|
||||||
|
$track->genre_id = $this->destinationGenre->id;
|
||||||
|
$track->save();
|
||||||
|
$track->updateTags();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
48
app/Library/SerializesModels.php
Normal file
48
app/Library/SerializesModels.php
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Database\ModelIdentifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SerializesModels
|
||||||
|
* This version of the SerializesModel trait overrides a method to make it work
|
||||||
|
* with soft-deletable models.
|
||||||
|
*
|
||||||
|
* @link https://github.com/laravel/framework/issues/9347#issuecomment-120803564
|
||||||
|
*/
|
||||||
|
trait SerializesModels {
|
||||||
|
use \Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the restored property value after deserialization.
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function getRestoredPropertyValue($value) {
|
||||||
|
if ($value instanceof ModelIdentifier) {
|
||||||
|
return method_exists($value->class, 'withTrashed')
|
||||||
|
? (new $value->class)->withTrashed()->findOrFail($value->id)
|
||||||
|
: (new $value->class)->findOrFail($value->id);
|
||||||
|
} else {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,4 +28,8 @@ class GenrePolicy
|
||||||
public function rename(User $user, Genre $genre) {
|
public function rename(User $user, Genre $genre) {
|
||||||
return $user->hasRole('admin');
|
return $user->hasRole('admin');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function delete(User $user, Genre $genre) {
|
||||||
|
return $user->hasRole('admin');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ use Auth;
|
||||||
use Cache;
|
use Cache;
|
||||||
use Config;
|
use Config;
|
||||||
use DB;
|
use DB;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
||||||
use Poniverse\Ponyfm\Traits\SlugTrait;
|
use Poniverse\Ponyfm\Traits\SlugTrait;
|
||||||
use Exception;
|
use Exception;
|
||||||
use External;
|
use External;
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
"barryvdh/laravel-ide-helper": "^2.1",
|
"barryvdh/laravel-ide-helper": "^2.1",
|
||||||
"guzzlehttp/guzzle": "~6.0",
|
"guzzlehttp/guzzle": "~6.0",
|
||||||
"doctrine/dbal": "^2.5",
|
"doctrine/dbal": "^2.5",
|
||||||
"venturecraft/revisionable": "^1.23"
|
"venturecraft/revisionable": "^1.23",
|
||||||
|
"pda/pheanstalk": "~3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fzaninotto/faker": "~1.4",
|
"fzaninotto/faker": "~1.4",
|
||||||
|
|
54
composer.lock
generated
54
composer.lock
generated
|
@ -4,8 +4,8 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "5f66a059010df46b5b6e50c3e4056e17",
|
"hash": "edca1732ab37f49b64614d5729d652d3",
|
||||||
"content-hash": "07e7a5fff5a8914a7ced3d14959d194f",
|
"content-hash": "b476009ee841e5b048e73b4fab8372ee",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "barryvdh/laravel-ide-helper",
|
"name": "barryvdh/laravel-ide-helper",
|
||||||
|
@ -1622,6 +1622,56 @@
|
||||||
],
|
],
|
||||||
"time": "2015-07-14 17:31:05"
|
"time": "2015-07-14 17:31:05"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "pda/pheanstalk",
|
||||||
|
"version": "v3.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/pda/pheanstalk.git",
|
||||||
|
"reference": "430e77c551479aad0c6ada0450ee844cf656a18b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/pda/pheanstalk/zipball/430e77c551479aad0c6ada0450ee844cf656a18b",
|
||||||
|
"reference": "430e77c551479aad0c6ada0450ee844cf656a18b",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "~4.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.0-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Pheanstalk\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Paul Annesley",
|
||||||
|
"email": "paul@annesley.cc",
|
||||||
|
"homepage": "http://paul.annesley.cc/",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP client for beanstalkd queue",
|
||||||
|
"homepage": "https://github.com/pda/pheanstalk",
|
||||||
|
"keywords": [
|
||||||
|
"beanstalkd"
|
||||||
|
],
|
||||||
|
"time": "2015-08-07 21:42:41"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-docblock",
|
"name": "phpdocumentor/reflection-docblock",
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddDeletedAtColumnToGenres extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('genres', function(Blueprint $table) {
|
||||||
|
$table->softDeletes()->index();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('genres', function(Blueprint $table) {
|
||||||
|
$table->dropSoftDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class CreateFailedJobsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('failed_jobs', function (Blueprint $table) {
|
||||||
|
$table->increments('id');
|
||||||
|
$table->text('connection');
|
||||||
|
$table->text('queue');
|
||||||
|
$table->longText('payload');
|
||||||
|
$table->timestamp('failed_at');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::drop('failed_jobs');
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
<th>Genre</th>
|
<th>Genre</th>
|
||||||
<th class="-status"></th>
|
<th class="-status"></th>
|
||||||
<th># of tracks (including deleted)</th>
|
<th># of tracks (including deleted)</th>
|
||||||
<th>Actions</th>
|
<th class="-actions">Actions</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tr ng-repeat="genre in genres">
|
<tr ng-repeat="genre in genres">
|
||||||
<td>
|
<td>
|
||||||
|
@ -23,8 +23,10 @@
|
||||||
</td>
|
</td>
|
||||||
<td><i ng-show="genre.isSaving" class="icon-cog icon-spin icon-large"></i></td>
|
<td><i ng-show="genre.isSaving" class="icon-cog icon-spin icon-large"></i></td>
|
||||||
<td><a ng-href="{{ genre.url }}">{{ genre.track_count }}</a></td>
|
<td><a ng-href="{{ genre.url }}">{{ genre.track_count }}</a></td>
|
||||||
<td>
|
<td class="-actions">
|
||||||
<button class="btn btn-warning" disabled>Merge…</button>
|
<button class="btn btn-warning" ng-hide="mergeInProgress" ng-click="startMerge(genre)">Merge…</button>
|
||||||
|
<button class="btn btn-danger" ng-show="mergeInProgress && genreToDelete.id != genre.id" ng-click="finishMerge(genre)">Merge in <em>{{ genreToDelete.name }}</em>…</button>
|
||||||
|
<button class="btn btn-warning" ng-show="mergeInProgress && genreToDelete.id == genre.id" ng-click="cancelMerge()">Cancel merge</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -20,13 +20,21 @@ angular.module('ponyfm').controller 'admin-genres', [
|
||||||
|
|
||||||
$scope.genres = []
|
$scope.genres = []
|
||||||
|
|
||||||
|
# Used for merging/deleting genres
|
||||||
|
$scope.mergeInProgress = false
|
||||||
|
$scope.genreToDelete = null
|
||||||
|
|
||||||
setGenres = (genres) ->
|
setGenres = (genres) ->
|
||||||
|
$scope.genres = []
|
||||||
for genre in genres
|
for genre in genres
|
||||||
genre.isSaving = false
|
genre.isSaving = false
|
||||||
genre.isError = false
|
genre.isError = false
|
||||||
$scope.genres.push(genre)
|
$scope.genres.push(genre)
|
||||||
|
|
||||||
genres.fetch().done setGenres
|
loadGenres = () ->
|
||||||
|
genres.fetch().done setGenres
|
||||||
|
|
||||||
|
loadGenres()
|
||||||
|
|
||||||
|
|
||||||
# Renames the given genre
|
# Renames the given genre
|
||||||
|
@ -42,7 +50,17 @@ angular.module('ponyfm').controller 'admin-genres', [
|
||||||
genre.isSaving = false
|
genre.isSaving = false
|
||||||
|
|
||||||
|
|
||||||
# Merges genre1 into genre2
|
$scope.startMerge = (genreToDelete) ->
|
||||||
mergeGenre = (genre1, genre2) ->
|
$scope.genreToDelete = genreToDelete
|
||||||
# stub method
|
$scope.mergeInProgress = true
|
||||||
|
|
||||||
|
$scope.cancelMerge = () ->
|
||||||
|
$scope.genreToDelete = null
|
||||||
|
$scope.mergeInProgress = false
|
||||||
|
|
||||||
|
$scope.finishMerge = (destinationGenre) ->
|
||||||
|
$scope.mergeInProgress = false
|
||||||
|
genres.merge($scope.genreToDelete.id, destinationGenre.id)
|
||||||
|
.done (response) ->
|
||||||
|
loadGenres()
|
||||||
]
|
]
|
||||||
|
|
|
@ -41,5 +41,17 @@ angular.module('ponyfm').factory('admin-genres', [
|
||||||
|
|
||||||
def.promise()
|
def.promise()
|
||||||
|
|
||||||
|
merge: (genre_id_to_delete, destination_genre_id) ->
|
||||||
|
url = "/api/web/admin/genres/#{genre_id_to_delete}"
|
||||||
|
def = new $.Deferred()
|
||||||
|
|
||||||
|
$http.delete(url, {params: {destination_genre_id: destination_genre_id}})
|
||||||
|
.success (response)->
|
||||||
|
def.resolve(response)
|
||||||
|
|
||||||
|
.error (response)->
|
||||||
|
def.reject(response)
|
||||||
|
|
||||||
|
def.promise()
|
||||||
self
|
self
|
||||||
])
|
])
|
||||||
|
|
4
resources/assets/styles/admin.less
vendored
4
resources/assets/styles/admin.less
vendored
|
@ -24,4 +24,8 @@
|
||||||
.-status {
|
.-status {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.-actions {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,5 +36,9 @@ cp -n "/vagrant/resources/environments/.env.local" "/vagrant/.env"
|
||||||
php artisan migrate
|
php artisan migrate
|
||||||
php artisan db:seed
|
php artisan db:seed
|
||||||
|
|
||||||
echo "Now - if you haven't already, SSH into the VM and run \`php artisan poni:setup\`!"
|
echo ""
|
||||||
echo "See the README for more details."
|
echo "+-----------------------------------------------+"
|
||||||
|
echo "| Now - if you haven't already, SSH into the VM |"
|
||||||
|
echo "| and run \`php artisan poni:setup\`! |"
|
||||||
|
echo "| See the README for more details. |"
|
||||||
|
echo "+-----------------------------------------------+"
|
||||||
|
|
Loading…
Reference in a new issue