#4: Comments can now be individually approved/rejected through the admin screen.

This commit is contained in:
Andy Heathershaw 2018-10-05 22:57:39 +01:00
parent 734e88bfc7
commit 17359e0cbe
11 changed files with 208 additions and 18 deletions

View File

@ -46,6 +46,15 @@ class PhotoCommentController extends Controller
return redirect(route('comments.index'));
}
public function approve($id)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
$comment = $this->loadCommentByID($id);
return Theme::render('admin.approve_comment', ['comment' => $comment]);
}
public function bulkAction(Request $request)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
@ -76,15 +85,57 @@ class PhotoCommentController extends Controller
return redirect(route('comments.index'));
}
public function confirmApprove(Request $request, $id)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
$comment = $this->loadCommentByID($id);
// Mark as approved
$comment->approved_at = new \DateTime();
$comment->approved_user_id = $this->getUser()->id;
// The comment may have already been rejected - remove the data if so
$comment->rejected_at = null;
$comment->rejected_user_id = null;
$comment->save();
$request->session()->flash('success', trans('admin.comment_approval_successful', [
'author_name' => $comment->authorDisplayName()
]));
return redirect(route('comments.index'));
}
public function confirmReject(Request $request, $id)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
$comment = $this->loadCommentByID($id);
// Mark as rejected
$comment->rejected_at = new \DateTime();
$comment->rejected_user_id = $this->getUser()->id;
// The comment may have already been approved - remove the data if so
$comment->approved_at = null;
$comment->approved_user_id = null;
$comment->save();
$request->session()->flash('success', trans('admin.comment_rejection_successful', [
'author_name' => $comment->authorDisplayName()
]));
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);
}
$comment = $this->loadCommentByID($id);
return Theme::render('admin.delete_comment', ['comment' => $comment]);
}
@ -94,11 +145,7 @@ class PhotoCommentController extends Controller
$this->authorizeAccessToAdminPanel('admin:manage-comments');
/** @var PhotoComment $comment */
$comment = PhotoComment::where('id', intval($id))->first();
if (is_null($comment))
{
App::abort(404);
}
$comment = $this->loadCommentByID($id);
$comment->delete();
$request->session()->flash('success', trans('admin.comment_deletion_successful', [
@ -154,4 +201,29 @@ class PhotoCommentController extends Controller
'warning' => $request->session()->get('warning')
]);
}
public function reject($id)
{
$this->authorizeAccessToAdminPanel('admin:manage-comments');
$comment = $this->loadCommentByID($id);
return Theme::render('admin.reject_comment', ['comment' => $comment]);
}
/**
* Loads a given comment by its ID.
* @param $id
* @return PhotoComment
*/
private function loadCommentByID($id)
{
$comment = PhotoComment::where('id', intval($id))->first();
if (is_null($comment))
{
App::abort(404);
}
return $comment;
}
}

View File

@ -61,6 +61,11 @@ class PhotoComment extends Model
return (!is_null($this->approved_at) || !is_null($this->rejected_at));
}
public function isRejected()
{
return (!is_null($this->rejected_at) && is_null($this->approved_at));
}
public function parent()
{
return $this->belongsTo(PhotoComment::class, 'parent_comment_id');

View File

@ -59,13 +59,22 @@ 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)',
'approve_comment' => 'Approve comment by :author_name',
'approve_comment_confirm' => 'Are you sure you want to approve this comment by ":author_name"?',
'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_approval_successful' => 'The comment by ":author_name" was approved successfully.',
'comment_badge' => [
'approved' => 'Approved',
'new' => 'New',
'rejected' => 'Rejected'
],
'comment_deletion_successful' => 'The comment by ":author_name" was removed successfully.',
'comment_rejection_successful' => 'The comment by ":author_name" was rejected 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.',
@ -222,6 +231,8 @@ return [
'redirects_actions_heading' => 'Actions',
'redirects_source_url_heading' => 'Source Address',
'redirects_text' => 'To access this album using different addresses, you can use redirects. This is useful when you have moved the album to a different parent and the old address no longer works.',
'reject_comment' => 'Reject comment by :author_name',
'reject_comment_confirm' => 'Are you sure you want to reject this comment by ":author_name"?',
'replace_image_message' => 'If your photo isn\'t quite perfect, don\'t worry - just upload a new image using the field below and we\'ll replace it.',
'replace_image_title' => 'Replace photo',
'save_changes_heading' => 'Save changes',

View File

@ -10,6 +10,7 @@ return [
'album_source_label' => 'Storage location:',
'album_view_label' => 'View as:',
'apply_action' => 'Apply',
'approve_action' => 'Approve',
'bulk_edit_photos_label' => 'Bulk edit selected photos:',
'bulk_edit_photos_placeholder' => 'Select an action',
'cancel_action' => 'Cancel',
@ -48,6 +49,7 @@ return [
'quick_upload_file_label' => 'Photo:',
'realname_label' => 'Your name:',
'register_action' => 'Create account',
'reject_action' => 'Reject',
'remember_me_label' => 'Remember me',
'remove_action' => 'Remove',
'review_photo_comment_action' => 'Approve/reject comment',

View File

@ -39,9 +39,7 @@ return [
'photo_comment_posted_successfully' => 'Your comment was posted successfully.',
'photo_comment_posted_successfully_pending_moderation' => 'Your comment was posted successfully and will appear after it has been moderated.',
'photo_comment_rejected_successfully' => 'The comment was rejected.',
'photo_comments_approve_action' => 'Approve',
'photo_comments_heading' => 'Comments',
'photo_comments_reject_action' => 'Reject',
'photo_comments_reply_action' => 'Reply',
'photo_comments_reply_form_heading' => 'Leave a reply',
'photo_comments_reply_form_p1' => 'Complete the form below to start a new reply thread.',

View File

@ -4,6 +4,7 @@ return [
'about' => 'About',
'admin' => 'Admin',
'albums' => 'Albums',
'approve_comment' => 'Approve comment',
'comments' => 'Comments',
'create_album' => 'Create album',
'create_group' => 'Create group',
@ -25,6 +26,7 @@ return [
'home' => 'Gallery',
'labels' => 'Labels',
'metadata_upgrade' => 'Update Photo Metadata',
'reject_comment' => 'Reject comment',
'settings' => 'Settings',
'storage' => 'Storage',
'users' => 'Users'

View File

@ -0,0 +1,34 @@
@extends(Theme::viewName('layout'))
@section('title', trans('admin.approve_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.approve_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-info">
<div class="card-header text-white">@yield('title')</div>
<div class="card-body bg-light">
<p>@lang('admin.approve_comment_confirm', ['author_name' => $comment->authorDisplayName()])</p>
{!! $comment->textAsHtml() !!}
<div class="text-right">
<form action="{{ route('comments.confirmApprove', [$comment->id]) }}" method="post">
{{ csrf_field() }}
<a href="{{ route('comments.index') }}" class="btn btn-link">@lang('forms.cancel_action')</a>
<button type="submit" class="btn btn-info"><i class="fa fa-fw fa-check"></i> @lang('forms.approve_action')</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -45,13 +45,38 @@
</td>
<td>
<p>
<a href="{{ route('comments.edit', ['id' => $comment->id]) }}"><span style="font-size: 1.3em;">{{ $comment->name }}</span></a><br/>
<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>
<p class="text-right">
@if (!$comment->isModerated())
<span class="badge badge-primary" style="font-size: 85%;">@lang('admin.comment_badge.new')</span>
@elseif ($comment->isApproved())
<span class="badge badge-success" style="font-size: 85%;">@lang('admin.comment_badge.approved')</span>
@elseif ($comment->isRejected())
<span class="badge badge-warning" style="font-size: 85%;">@lang('admin.comment_badge.rejected')</span>
@endif
</p>
<div class="btn-toolbar pull-right">
<div class="btn-group mr-2">
@if (!$comment->isModerated())
<a href="{{ route('comments.approve', ['id' => $comment->id]) }}" class="btn btn-outline-info">@lang('forms.approve_action')</a>
<a href="{{ route('comments.reject', ['id' => $comment->id]) }}" class="btn btn-outline-info">@lang('forms.reject_action')</a>
@elseif ($comment->isApproved())
<a href="{{ route('comments.reject', ['id' => $comment->id]) }}" class="btn btn-outline-info">@lang('forms.reject_action')</a>
@elseif ($comment->isRejected())
<a href="{{ route('comments.approve', ['id' => $comment->id]) }}" class="btn btn-outline-info">@lang('forms.approve_action')</a>
@endif
</div>
<a href="{{ route('comments.delete', ['id' => $comment->id]) }}" class="btn btn-danger">@lang('forms.delete_action')</a>
</div>
</td>
</tr>
@endforeach

View File

@ -0,0 +1,34 @@
@extends(Theme::viewName('layout'))
@section('title', trans('admin.reject_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.reject_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-info">
<div class="card-header text-white">@yield('title')</div>
<div class="card-body bg-light">
<p>@lang('admin.reject_comment_confirm', ['author_name' => $comment->authorDisplayName()])</p>
{!! $comment->textAsHtml() !!}
<div class="text-right">
<form action="{{ route('comments.confirmReject', [$comment->id]) }}" method="post">
{{ csrf_field() }}
<a href="{{ route('comments.index') }}" class="btn btn-link">@lang('forms.cancel_action')</a>
<button type="submit" class="btn btn-info"><i class="fa fa-fw fa-check"></i> @lang('forms.reject_action')</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -10,8 +10,8 @@
<form action="{{ $photo->moderateCommentUrl($comment->id) }}" method="post">
{{ csrf_field() }}
<button type="submit" name="approve" class="btn btn-success card-link">@lang('gallery.photo_comments_approve_action')</button>
<button type="submit" name="reject" class="btn btn-outline-danger card-link">@lang('gallery.photo_comments_reject_action')</button>
<button type="submit" name="approve" class="btn btn-success card-link">@lang('forms.approve_action')</button>
<button type="submit" name="reject" class="btn btn-outline-danger card-link">@lang('forms.reject_action')</button>
</form>
</div>
</div>

View File

@ -68,9 +68,16 @@ Route::group(['prefix' => 'admin'], function () {
Route::resource('groups', 'Admin\GroupController');
// Comments management
Route::get('comments/{id}/approve', 'Admin\PhotoCommentController@approve')->name('comments.approve');
Route::post('comments/{id}/approve', 'Admin\PhotoCommentController@confirmApprove')->name('comments.confirmApprove');
Route::get('comments/{id}/reject', 'Admin\PhotoCommentController@reject')->name('comments.reject');
Route::post('comments/{id}/reject', 'Admin\PhotoCommentController@confirmReject')->name('comments.confirmReject');
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::post('comments/bulk-action', 'Admin\PhotoCommentController@bulkAction')->name('comments.bulkAction');
Route::resource('comments', 'Admin\PhotoCommentController');
});