#4: It's now possible to delete single comments and bulk-delete multiple comments in the admin screen

This commit is contained in:
Andy Heathershaw 2018-10-05 22:17:41 +01:00
parent 62659c13f7
commit 734e88bfc7
9 changed files with 273 additions and 31 deletions

View File

@ -34,7 +34,7 @@ class GroupController extends Controller
public function delete($id)
{
$this->authorizeAccessToAdminPanel();
$this->authorizeAccessToAdminPanel('admin:manage-groups');
$group = Group::where('id', intval($id))->first();
if (is_null($group))

View File

@ -6,6 +6,7 @@ use App\Facade\Theme;
use App\Facade\UserConfig;
use App\Http\Controllers\Controller;
use App\PhotoComment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\View;
class PhotoCommentController extends Controller
@ -16,17 +17,141 @@ class PhotoCommentController extends Controller
View::share('is_admin', true);
}
public function index()
public function applyBulkAction(Request $request)
{
$this->authorizeAccessToAdminPanel();
$this->authorizeAccessToAdminPanel('admin:manage-comments');
$commentIDs = $request->get('comment_ids');
if (is_null($commentIDs) || !is_array($commentIDs) || count($commentIDs) == 0)
{
$request->session()->flash('warning', trans('admin.no_comments_selected_message'));
return redirect(route('comments.index'));
}
$comments = PhotoComment::whereIn('id', $commentIDs)->get();
$commentsActioned = 0;
if ($request->has('bulk_delete'))
{
/** @var PhotoComment $comment */
foreach ($comments as $comment)
{
$comment->delete();
$commentsActioned++;
}
$request->session()->flash('success', trans_choice('admin.bulk_comments_deleted', $commentsActioned, ['number' => $commentsActioned]));
}
return redirect(route('comments.index'));
}
public function bulkAction(Request $request)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
$commentIDs = $request->get('comment_ids');
if (is_null($commentIDs) || !is_array($commentIDs) || count($commentIDs) == 0)
{
$request->session()->flash('warning', trans('admin.no_comments_selected_message'));
return redirect(route('comments.index'));
}
if ($request->has('bulk_delete'))
{
if (count($commentIDs) == 1)
{
// Single comment selected - redirect to the single delete page
return redirect(route('comments.delete', ['id' => $commentIDs[0]]));
}
// Show the view to confirm the delete
return Theme::render('admin.bulk_delete_comments', [
'comment_count' => count($commentIDs),
'comment_ids' => $commentIDs
]);
}
// Unrecognised action - simply redirect back to the index page
return redirect(route('comments.index'));
}
public function delete($id)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
$comment = PhotoComment::where('id', intval($id))->first();
if (is_null($comment))
{
App::abort(404);
}
return Theme::render('admin.delete_comment', ['comment' => $comment]);
}
public function destroy(Request $request, $id)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
/** @var PhotoComment $comment */
$comment = PhotoComment::where('id', intval($id))->first();
if (is_null($comment))
{
App::abort(404);
}
$comment->delete();
$request->session()->flash('success', trans('admin.comment_deletion_successful', [
'author_name' => $comment->authorDisplayName()
]));
return redirect(route('comments.index'));
}
public function index(Request $request)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
$validStatusList = [
'all',
'pending',
'approved',
'rejected'
];
$filterStatus = $request->get('status', 'all');
if (!in_array($filterStatus, $validStatusList))
{
$filterStatus = $validStatusList[0];
}
$comments = PhotoComment::with('photo')
->with('photo.album')
->orderBy('created_at', 'desc')
->paginate(UserConfig::get('items_per_page'));
->orderBy('created_at', 'desc');
switch (strtolower($filterStatus))
{
case 'approved':
$comments->whereNotNull('approved_at')
->whereNull('rejected_at');
break;
case 'pending':
$comments->whereNull('approved_at')
->whereNull('rejected_at');
break;
case 'rejected':
$comments->whereNull('approved_at')
->whereNotNull('rejected_at');
break;
}
return Theme::render('admin.list_comments', [
'comments' => $comments
'comments' => $comments->paginate(UserConfig::get('items_per_page')),
'filter_status' => $filterStatus,
'success' => $request->session()->get('success'),
'warning' => $request->session()->get('warning')
]);
}
}

View File

@ -59,11 +59,13 @@ return [
'analyse_photos_failed' => 'The following items could not be analysed and were removed:',
'analyse_photos_failed_metadata' => 'The following items could not be analysed:',
'anonymous_users' => 'Anonymous (not logged in)',
'bulk_comments_deleted' => ':number comment was deleted successfully.|:number comments were deleted successfully.',
'bulk_photos_changed' => ':number photo was updated successfully.|:number photos were updated successfully.',
'cannot_delete_own_user_account' => 'It is not possible to delete your own user account. Please ask another administrator to delete it for you.',
'cannot_remove_own_admin' => 'You cannot remove your own administrator permissions. Please ask another administrator to remove the administrator permissions for you.',
'change_album_message' => 'Please select the album to move the photo(s) to:',
'change_album_title' => 'Move photo(s) to another album',
'comment_deletion_successful' => 'The comment by ":author_name" was removed successfully.',
'comment_summary' => ':album_name / :photo_name / :comment_date',
'create_album' => 'Create a photo album',
'create_album_intro' => 'Photo albums contain individual photographs together in the same way as a physical photo album or memory book.',
@ -94,6 +96,12 @@ return [
'delete_album_failed_children' => 'The album ":album" contains child albums and cannot be deleted. Please delete or move the child albums first.',
'delete_album_success_message' => 'The album ":album" was deleted successfully.',
'delete_album_warning' => 'This is a permanent action that cannot be undone!',
'delete_comment' => 'Delete comment by :author_name',
'delete_comment_confirm' => 'Are you sure you want to permanently remove this comment by ":author_name"?',
'delete_comment_warning' => 'This is a permanent action that cannot be reversed!',
'delete_comments' => 'Delete :number comments',
'delete_comments_confirm' => 'Are you sure you want to permanently remove these :number comments?',
'delete_comments_warning' => 'This is a permanent action that cannot be reversed!',
'delete_bulk_photos_message' => 'Are you sure you want to delete the selected photos? This action cannot be undone!',
'delete_bulk_photos_title' => 'Delete selected photos',
'delete_group' => 'Delete group: :name',
@ -145,6 +153,12 @@ return [
'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_comments_intro' => 'Comments are messages left on your photos by visitors and users.',
'list_comments_status' => [
'all' => '- All -',
'approved' => 'Approved',
'pending' => 'Pending moderation',
'rejected' => 'Rejected',
],
'list_comments_title' => 'Comments',
'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',
@ -176,6 +190,10 @@ return [
'move_successful_message' => 'The photo ":name" was moved successfully to the ":album" album.',
'no_albums_text' => 'You have no photo albums yet. Click the button below to create one.',
'no_albums_title' => 'No Photo Albums',
'no_comments_selected_message' => 'Please select at least one comment.',
'no_comments_text' => 'You have no comments that match the filter selected.',
'no_comments_text_2' => 'Comments will show here when they are posted on a photo in the gallery, or you can try changing the filter above.',
'no_comments_title' => 'No Comments Found',
'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.',

View File

@ -21,6 +21,7 @@ return [
'default_album_view_label' => 'Default view mode in the gallery:',
'default_storage_label' => 'Use as the default storage location for new albums',
'delete_action' => 'Delete',
'delete_selected_action' => 'Delete selected',
'description_label' => 'Description:',
'download_action' => 'Download',
'edit_action' => 'Edit',
@ -28,6 +29,7 @@ return [
'email_label' => 'E-mail address:',
'email_placeholder' => 'name@example.com',
'enable_profile_page_label' => 'Allow others to see my profile page',
'filter_comments_status_label' => 'Show comments that are:',
'inherit_album_permissions' => 'Inherit permissions from parent album / default settings',
'labels_label' => 'Labels:',
'login_action' => 'Login',

View File

@ -11,6 +11,7 @@ return [
'create_user' => 'Create user',
'default_album_permissions' => 'Default album permissions',
'delete_album' => 'Delete album',
'delete_comment' => 'Delete comment',
'delete_group' => 'Delete group',
'delete_label' => 'Delete label',
'delete_storage' => 'Delete storage location',

View File

@ -0,0 +1,39 @@
@extends(Theme::viewName('layout'))
@section('title', trans('admin.delete_comments', ['number' => $comment_count]))
@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('comments.index') }}">@lang('navigation.breadcrumb.comments')</a></li>
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.delete_comments')</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_comments_confirm', ['number' => $comment_count])</p>
<p class="text-danger"><b>@lang('admin.delete_comments_warning')</b></p>
<div class="text-right">
<form action="{{ route('comments.applyBulkAction') }}" method="post">
{{ csrf_field() }}
<input type="hidden" name="bulk_delete" value="1" />
@foreach ($comment_ids as $comment_id)
<input type="hidden" name="comment_ids[]" value="{{ $comment_id }}" />
@endforeach
<a href="{{ route('comments.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

View File

@ -0,0 +1,37 @@
@extends(Theme::viewName('layout'))
@section('title', trans('admin.delete_comment', ['author_name' => $comment->authorDisplayName()]))
@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('comments.index') }}">@lang('navigation.breadcrumb.comments')</a></li>
<li class="breadcrumb-item active">@lang('navigation.breadcrumb.delete_comment')</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_comment_confirm', ['author_name' => $comment->authorDisplayName()])</p>
{!! $comment->textAsHtml() !!}
<p class="text-danger"><b>@lang('admin.delete_comment_warning')</b></p>
<div class="text-right">
<form action="{{ route('comments.destroy', [$comment->id]) }}" method="post">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<a href="{{ route('comments.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

View File

@ -16,34 +16,52 @@
<i class="fa fa-fw fa-info"></i> @lang('admin.list_comments_intro')
</div>
<form action="{{ url()->current() }}" method="get" class="form-inline">
<label for="comment-filter-status" class="mr-2 mb-3">@lang('forms.filter_comments_status_label')</label>
<select class="form-control mb-3 mr-2 custom-select" name="status" id="comment-filter-status">
<option value="all"{{ $filter_status == 'all' ? ' selected="selected"' : '' }}>@lang('admin.list_comments_status.all')</option>
<option value="pending"{{ $filter_status == 'pending' ? ' selected="selected"' : '' }}>@lang('admin.list_comments_status.pending')</option>
<option value="approved"{{ $filter_status == 'approved' ? ' selected="selected"' : '' }}>@lang('admin.list_comments_status.approved')</option>
<option value="rejected"{{ $filter_status == 'rejected' ? ' selected="selected"' : '' }}>@lang('admin.list_comments_status.rejected')</option>
</select>
<button type="submit" class="btn btn-primary mb-3">@lang('forms.apply_action')</button>
</form>
@if (count($comments) == 0)
<div class="text-center">
<h4 class="text-danger"><b>@lang('admin.no_comments_title')</b></h4>
<p>@lang('admin.no_comments_text')</p>
<p style="margin-top: 40px;">
<a href="{{ route('comments.create') }}" class="btn btn-lg btn-success">@lang('admin.create_comment')</a>
</p>
<div class="text-center mt-4">
<h4 class="text-danger mb-3"><b>@lang('admin.no_comments_title')</b></h4>
<p class="mb-1">@lang('admin.no_comments_text')</p>
<p>@lang('admin.no_comments_text_2')</p>
</div>
@else
<table class="table table-hover table-striped">
<tbody>
@foreach ($comments as $comment)
<tr>
<td class="text-center" style="width: 40px;"><input type="checkbox" name="comment_id" value="{{ $comment->id }}" /></td>
<td>
<p>
<a href="{{ route('comments.edit', ['id' => $comment->id]) }}"><span style="font-size: 1.3em;">{{ $comment->name }}</span></a><br/>
<span class="text-muted" style="font-size: smaller;">{{ trans('admin.comment_summary', ['album_name' => $comment->photo->album->name, 'photo_name' => $comment->photo->name, 'comment_date' => date(UserConfig::get('date_format'), strtotime($comment->created_at))]) }}</span>
</p>
<blockquote>{!! $comment->textAsHtml() !!}</blockquote>
</td>
<td class="text-right">
<a href="{{ route('comments.delete', ['id' => $comment->id]) }}" class="btn btn-danger">@lang('forms.delete_action')</a>
</td>
</tr>
@endforeach
</tbody>
</table>
<form action="{{ route('comments.bulkAction') }}" method="post">
{{ csrf_field() }}
<table class="table table-hover table-striped">
<tbody>
@foreach ($comments as $comment)
<tr>
<td class="text-center" style="width: 40px;">
<input type="checkbox" name="comment_ids[]" value="{{ $comment->id }}" />
</td>
<td>
<p>
<a href="{{ route('comments.edit', ['id' => $comment->id]) }}"><span style="font-size: 1.3em;">{{ $comment->name }}</span></a><br/>
<span class="text-muted" style="font-size: smaller;">{{ trans('admin.comment_summary', ['album_name' => $comment->photo->album->name, 'photo_name' => $comment->photo->name, 'comment_date' => date(UserConfig::get('date_format'), strtotime($comment->created_at))]) }}</span>
</p>
<blockquote>{!! $comment->textAsHtml() !!}</blockquote>
</td>
<td class="text-right">
<a href="{{ route('comments.delete', ['id' => $comment->id]) }}" class="btn btn-danger">@lang('forms.delete_action')</a>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="btn-group mb-4" role="group">
<button type="submit" name="bulk_delete" class="btn btn-danger">@lang('forms.delete_selected_action')</button>
</div>
</form>
<div class="text-center">
{{ $comments->links() }}

View File

@ -69,6 +69,8 @@ Route::group(['prefix' => 'admin'], function () {
// Comments management
Route::get('comments/{id}/delete', 'Admin\PhotoCommentController@delete')->name('comments.delete');
Route::post('comments/bulk-action', 'Admin\PhotoCommentController@bulkAction')->name('comments.bulkAction');
Route::post('comments/apply-bulk-action', 'Admin\PhotoCommentController@applyBulkAction')->name('comments.applyBulkAction');
Route::resource('comments', 'Admin\PhotoCommentController');
});