#29: Labels can now be added and managed through the admin panel
This commit is contained in:
parent
aa99d76ae5
commit
6280766d70
@ -11,6 +11,7 @@ use App\Helpers\ConfigHelper;
|
||||
use App\Helpers\DbHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\SaveSettingsRequest;
|
||||
use App\Label;
|
||||
use App\Mail\TestMailConfig;
|
||||
use App\Photo;
|
||||
use App\User;
|
||||
@ -36,12 +37,14 @@ class DefaultController extends Controller
|
||||
$albumCount = DbHelper::getAlbumsForCurrentUser()->count();
|
||||
$photoCount = Photo::all()->count();
|
||||
$groupCount = Group::all()->count();
|
||||
$labelCount = Label::all()->count();
|
||||
$userCount = User::where('is_activated', true)->count();
|
||||
|
||||
return Theme::render('admin.index', [
|
||||
'album_count' => $albumCount,
|
||||
'app_version' => config('app.version'),
|
||||
'group_count' => $groupCount,
|
||||
'label_count' => $labelCount,
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'photo_count' => $photoCount,
|
||||
'php_version' => phpversion(),
|
||||
|
92
app/Http/Controllers/Admin/LabelController.php
Normal file
92
app/Http/Controllers/Admin/LabelController.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Facade\Theme;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\StoreLabelRequest;
|
||||
use App\Label;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class LabelController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(['auth', 'max_post_size_exceeded']);
|
||||
View::share('is_admin', true);
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$this->authorizeAccessToAdminPanel();
|
||||
|
||||
$label = $this->loadLabel($id);
|
||||
return Theme::render('admin.delete_label', ['label' => $label]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Request $request, $id)
|
||||
{
|
||||
$this->authorizeAccessToAdminPanel('admin:manage-labels');
|
||||
|
||||
$label = $this->loadLabel($id);
|
||||
$label->delete();
|
||||
|
||||
$request->session()->flash('success', trans('admin.delete_label_success_message', ['name' => $label->name]));
|
||||
|
||||
return redirect(route('labels.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$labels = Label::withCount('photos')->get();
|
||||
return Theme::render('admin.list_labels', [
|
||||
'labels' => $labels
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreLabelRequest $request)
|
||||
{
|
||||
$this->authorizeAccessToAdminPanel('admin:manage-labels');
|
||||
|
||||
$label = new Label();
|
||||
$label->fill($request->only(['name']));
|
||||
$label->save();
|
||||
|
||||
return redirect(route('labels.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return Album
|
||||
*/
|
||||
private function loadLabel($id)
|
||||
{
|
||||
$label = Label::where('id', intval($id))->first();
|
||||
if (is_null($label))
|
||||
{
|
||||
App::abort(404);
|
||||
return null;
|
||||
}
|
||||
|
||||
return $label;
|
||||
}
|
||||
}
|
28
app/Http/Requests/StoreLabelRequest.php
Normal file
28
app/Http/Requests/StoreLabelRequest.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreLabelRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return ['name' => 'required:max:255|unique:labels,name'];
|
||||
}
|
||||
}
|
22
app/Label.php
Normal file
22
app/Label.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Label extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name'
|
||||
];
|
||||
|
||||
public function photos()
|
||||
{
|
||||
return $this->belongsToMany(Photo::class, 'photo_labels');
|
||||
}
|
||||
}
|
@ -56,6 +56,10 @@ class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
return $this->userHasAdminPermission($user, 'manage-groups');
|
||||
});
|
||||
Gate::define('admin:manage-labels', function ($user)
|
||||
{
|
||||
return $this->userHasAdminPermission($user, 'manage-labels');
|
||||
});
|
||||
Gate::define('admin:manage-storage', function ($user)
|
||||
{
|
||||
return $this->userHasAdminPermission($user, 'manage-storage');
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
return [
|
||||
// Version number of Blue Twilight
|
||||
'version' => '2.0.1',
|
||||
'version' => '2.1.0-beta.1',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreatePhotoLabelsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('labels', function ($table) {
|
||||
$table->increments('id');
|
||||
$table->string('name');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('photo_labels', function ($table) {
|
||||
$table->unsignedBigInteger('photo_id');
|
||||
$table->unsignedInteger('label_id');
|
||||
|
||||
$table->foreign('photo_id')
|
||||
->references('id')->on('photos')
|
||||
->onDelete('cascade');
|
||||
$table->foreign('label_id')
|
||||
->references('id')->on('labels')
|
||||
->onDelete('cascade');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('photo_labels');
|
||||
Schema::dropIfExists('labels');
|
||||
}
|
||||
}
|
@ -64,6 +64,14 @@ class PermissionsSeeder extends Seeder
|
||||
'is_default' => false,
|
||||
'sort_order' => 0
|
||||
]);
|
||||
|
||||
// admin:manage-labels = controls if photo labels can be managed
|
||||
DatabaseSeeder::createOrUpdate('permissions', [
|
||||
'section' => 'admin',
|
||||
'description' => 'manage-labels',
|
||||
'is_default' => false,
|
||||
'sort_order' => 0
|
||||
]);
|
||||
}
|
||||
|
||||
private function seedAlbumPermissions()
|
||||
|
@ -46,6 +46,8 @@ return [
|
||||
'create_album_no_storage' => 'There are currently no storage locations set up. Please create a location to store your photos before creating an album.',
|
||||
'create_group' => 'Create a group',
|
||||
'create_group_intro' => 'Complete the form below to create a group in which to organise your users.',
|
||||
'create_label_intro' => 'Use the form below to add a new label that can be added to your photos.',
|
||||
'create_label_title' => 'Create a label',
|
||||
'create_redirect_heading' => 'Add a Redirect',
|
||||
'create_redirect_success_message' => 'The redirect was added successfully.',
|
||||
'create_redirect_text' => 'Enter the source address you would like to redirect and click the Create button to add a new redirect to this album.',
|
||||
@ -66,6 +68,9 @@ return [
|
||||
'delete_group' => 'Delete group: :name',
|
||||
'delete_group_confirm' => 'Are you sure you want to permanently remove the ":name" group? Users who are members of this group may lose permissions.',
|
||||
'delete_group_warning' => 'This is a permanent action that cannot be reversed!',
|
||||
'delete_label' => 'Delete label: :name',
|
||||
'delete_label_confirm' => 'Are you sure you want to permanently remove the ":name" label?',
|
||||
'delete_label_success_message' => 'The :name label was deleted successfully.',
|
||||
'delete_photo_message' => 'Are you sure you want to delete this photo? This action cannot be undone!',
|
||||
'delete_photo_successful_message' => 'The photo ":name" was deleted successfully.',
|
||||
'delete_photo_title' => 'Delete photo',
|
||||
@ -103,11 +108,14 @@ return [
|
||||
'group_users_tab' => 'Users',
|
||||
'inactive_storage_legend' => 'Inactive storage location that cannot be used for new albums.',
|
||||
'is_uploading' => 'Uploading in progress...',
|
||||
'labels_intro' => 'Your labels are displayed below. The number in brackets indicates the number of photos linked to that label. Click a label to delete it.',
|
||||
'legend' => 'Legend/Key',
|
||||
'list_albums_intro' => 'Albums contain collections of individual photographs in the same way as a physical photo album or memory book.',
|
||||
'list_albums_title' => 'Albums',
|
||||
'list_groups_intro' => 'Organise your users into categories or types by using groups. You can assign permissions on albums to groups of users to make administration and management easier.',
|
||||
'list_groups_title' => 'Groups',
|
||||
'list_labels_intro' => 'Organise your photos differently using labels. Assign one or more labels to your photos and your visitors can view all photos with a specific tag in a single view.',
|
||||
'list_labels_title' => 'Labels',
|
||||
'list_storages_intro' => 'Storage locations specify the physical location where your photograph files are held. This may be on your local server\'s filesystem, or on a cloud storage provider such as Rackspace or Amazon S3.',
|
||||
'list_storages_title' => 'Storage Locations',
|
||||
'list_users_intro' => 'User accounts allow people to login to your gallery to manage your albums. If you have disabled self-registration, you can create user accounts here to allow people to login.',
|
||||
@ -121,6 +129,8 @@ return [
|
||||
'no_albums_title' => 'No Photo Albums',
|
||||
'no_groups_text' => 'You have no groups yet. Click the button below to create one.',
|
||||
'no_groups_title' => 'No Groups',
|
||||
'no_labels_text' => 'You have no labels yet. Use the form below to create one.',
|
||||
'no_labels_title' => 'No Labels',
|
||||
'no_photo_selected_message' => 'Please select at least one photo.',
|
||||
'no_storages_text' => 'You need a storage location to store your uploaded photographs.',
|
||||
'no_storages_text2' => 'This can be on your server\'s local filesystem or a cloud location such as Amazon S3 or Rackspace.',
|
||||
@ -182,6 +192,7 @@ return [
|
||||
'stats_widget' => [
|
||||
'albums' => 'album|albums',
|
||||
'groups' => 'group|groups',
|
||||
'labels' => 'label|labels',
|
||||
'panel_header' => 'Statistics',
|
||||
'photos' => 'photo|photos',
|
||||
'users' => 'user|users',
|
||||
|
@ -9,6 +9,7 @@ return [
|
||||
'create_user' => 'Create user',
|
||||
'delete_album' => 'Delete album',
|
||||
'delete_group' => 'Delete group',
|
||||
'delete_label' => 'Delete label',
|
||||
'delete_storage' => 'Delete storage location',
|
||||
'delete_user' => 'Delete user',
|
||||
'edit_album' => 'Edit album',
|
||||
@ -16,6 +17,7 @@ return [
|
||||
'edit_storage' => 'Edit storage location',
|
||||
'edit_user' => 'Edit user',
|
||||
'groups' => 'Groups',
|
||||
'labels' => 'Labels',
|
||||
'home' => 'Gallery',
|
||||
'settings' => 'Settings',
|
||||
'storage' => 'Storage',
|
||||
|
@ -5,6 +5,7 @@ return [
|
||||
'configure' => 'Configure the application',
|
||||
'manage-albums' => 'Manage photo albums',
|
||||
'manage-groups' => 'Manage user groups',
|
||||
'manage-labels' => 'Manage photo labels',
|
||||
'manage-storage' => 'Manage storage locations',
|
||||
'manage-users' => 'Manage users'
|
||||
],
|
||||
|
34
resources/views/themes/base/admin/delete_label.blade.php
Normal file
34
resources/views/themes/base/admin/delete_label.blade.php
Normal file
@ -0,0 +1,34 @@
|
||||
@extends('themes.base.layout')
|
||||
@section('title', trans('admin.delete_label', ['name' => $label->name]))
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('labels.index') }}">@lang('navigation.breadcrumb.labels')</a></li>
|
||||
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.delete_label')</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 ml-md-auto mr-md-auto">
|
||||
<div class="card bg-danger">
|
||||
<div class="card-header text-white">@yield('title')</div>
|
||||
<div class="card-body bg-light">
|
||||
<p>@lang('admin.delete_label_confirm', ['name' => $label->name])</p>
|
||||
<p class="text-danger"><b>@lang('admin.delete_group_warning')</b></p>
|
||||
|
||||
<div class="text-right">
|
||||
<form action="{{ route('labels.destroy', [$label->id]) }}" method="post">
|
||||
{{ csrf_field() }}
|
||||
{{ method_field('DELETE') }}
|
||||
<a href="{{ route('labels.index') }}" class="btn btn-link">@lang('forms.cancel_action')</a>
|
||||
<button type="submit" class="btn btn-danger"><i class="fa fa-fw fa-trash"></i> @lang('forms.delete_action')</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
@ -83,6 +83,10 @@
|
||||
'permission' => Theme::getPermission($all_permissions, 'admin', 'manage-albums')
|
||||
])
|
||||
|
||||
@include(Theme::viewName('partials.permission_checkbox'), [
|
||||
'permission' => Theme::getPermission($all_permissions, 'admin', 'manage-labels')
|
||||
])
|
||||
|
||||
@include(Theme::viewName('partials.permission_checkbox'), [
|
||||
'permission' => Theme::getPermission($all_permissions, 'admin', 'manage-users')
|
||||
])
|
||||
|
73
resources/views/themes/base/admin/list_labels.blade.php
Normal file
73
resources/views/themes/base/admin/list_labels.blade.php
Normal file
@ -0,0 +1,73 @@
|
||||
@extends('themes.base.layout')
|
||||
@section('title', trans('admin.list_labels_title'))
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}"><i class="fa fa-fw fa-home"></i></a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin') }}">@lang('navigation.breadcrumb.admin')</a></li>
|
||||
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.labels')</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>@yield('title')</h1>
|
||||
<div class="alert alert-info mb-4">
|
||||
<i class="fa fa-fw fa-info"></i> @lang('admin.list_labels_intro')
|
||||
</div>
|
||||
|
||||
@if (count($labels) == 0)
|
||||
<div class="text-center mb-4">
|
||||
<h4 class="text-danger"><b>@lang('admin.no_labels_title')</b></h4>
|
||||
<p>@lang('admin.no_labels_text')</p>
|
||||
</div>
|
||||
@else
|
||||
<p>@lang('admin.labels_intro')</p>
|
||||
<ul class="nav nav-pills">
|
||||
@foreach ($labels as $label)
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('labels.delete', [$label->id]) }}">
|
||||
{{ $label->name }} ({{ number_format($label->photos_count, 0) }})
|
||||
<i class="fa fa-trash text-danger"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
|
||||
<hr/>
|
||||
<h3>@lang('admin.create_label_title')</h3>
|
||||
<p class="mb-5">@lang('admin.create_label_intro')</p>
|
||||
|
||||
<form action="{{ route('labels.store') }}" method="POST">
|
||||
{{ csrf_field() }}
|
||||
<div class="form-group row">
|
||||
<label class="form-control-label col-md-1" for="label-name">@lang('forms.name_label')</label>
|
||||
<div class="col-md-9 mb-3">
|
||||
<input type="text" class="form-control{{ $errors->has('name') ? ' is-invalid' : '' }}" id="label-name" name="name" value="{{ old('name') }}">
|
||||
|
||||
@if ($errors->has('name'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('name') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-md-2 text-right">
|
||||
<button type="submit" class="btn btn-success" style="width: 100%;"><i class="fa fa-check"></i> @lang('forms.create_action')</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('#label-name').focus();
|
||||
});
|
||||
</script>
|
||||
@endpush
|
@ -2,6 +2,7 @@
|
||||
$canConfigure = Auth::user()->can('admin:configure');
|
||||
$canManageAlbums = Auth::user()->can('admin:manage-albums');
|
||||
$canManageGroups = Auth::user()->can('admin:manage-groups');
|
||||
$canManageLabels = Auth::user()->can('admin:manage-labels');
|
||||
$canManageStorage = Auth::user()->can('admin:manage-storage');
|
||||
$canManageUsers = Auth::user()->can('admin:manage-users');
|
||||
@endphp
|
||||
@ -13,6 +14,9 @@
|
||||
@if ($canManageAlbums)
|
||||
<a class="btn btn-link" href="{{ route('albums.index') }}"><i class="fa fa-fw fa-picture-o"></i> @lang('navigation.breadcrumb.albums')</a>
|
||||
@endif
|
||||
@if ($canManageLabels)
|
||||
<a class="btn btn-link" href="{{ route('labels.index') }}"><i class="fa fa-fw fa-tags"></i> @lang('navigation.breadcrumb.labels')</a>
|
||||
@endif
|
||||
@if ($canManageUsers)
|
||||
<a class="btn btn-link" href="{{ route('users.index') }}"><i class="fa fa-fw fa-user"></i> @lang('navigation.breadcrumb.users')</a>
|
||||
@endif
|
||||
|
@ -1,8 +1,9 @@
|
||||
<div class="card admin-sidebar-card">
|
||||
<div class="card-header">@lang('admin.stats_widget.panel_header')</div>
|
||||
<div class="card-body">
|
||||
<b>{{ $album_count }}</b> {{ trans_choice('admin.stats_widget.albums', $album_count) }}<br/>
|
||||
<b>{{ $photo_count }}</b> {{ trans_choice('admin.stats_widget.photos', $photo_count) }}
|
||||
<b>{{ $album_count }}</b> {{ trans_choice('admin.stats_widget.albums', $album_count) }} ·
|
||||
<b>{{ $photo_count }}</b> {{ trans_choice('admin.stats_widget.photos', $photo_count) }}<br/>
|
||||
<b>{{ $label_count }}</b> {{ trans_choice('admin.stats_widget.labels', $label_count) }}
|
||||
@can('admin:access')
|
||||
<br/>
|
||||
<b>{{ $user_count }}</b> {{ trans_choice('admin.stats_widget.users', $user_count) }} / <b>{{ $group_count }}</b> {{ trans_choice('admin.stats_widget.groups', $group_count) }}
|
||||
|
@ -39,6 +39,10 @@ Route::group(['prefix' => 'admin'], function () {
|
||||
Route::put('photos/update-bulk/{albumId}', 'Admin\PhotoController@updateBulk')->name('photos.updateBulk');
|
||||
Route::resource('photos', 'Admin\PhotoController');
|
||||
|
||||
// Label management
|
||||
Route::get('labels/{id}/delete', 'Admin\LabelController@delete')->name('labels.delete');
|
||||
Route::resource('labels', 'Admin\LabelController');
|
||||
|
||||
// Storage management
|
||||
Route::get('storage/{id}/delete', 'Admin\StorageController@delete')->name('storage.delete');
|
||||
Route::resource('storage', 'Admin\StorageController');
|
||||
|
Loading…
Reference in New Issue
Block a user