#4: Started work on threaded comments in the front-end gallery. There is also a settings tab dedicated to commenting now.

This commit is contained in:
Andy Heathershaw 2018-09-18 10:19:47 +01:00
parent 1f7befafab
commit c9ab590afe
11 changed files with 133 additions and 31 deletions

View File

@ -113,6 +113,7 @@ class ConfigHelper
'items_per_page' => 12,
'items_per_page_admin' => 10,
'photo_comments_require_login' => true,
'photo_comments_thread_depth' => 3,
'public_statistics' => true,
'recaptcha_enabled_registration' => false,
'recaptcha_secret_key' => '',

View File

@ -254,6 +254,7 @@ class DefaultController extends Controller
'facebook_app_secret',
'google_app_id',
'google_app_secret',
'photo_comments_thread_depth',
'sender_address',
'sender_name',
'smtp_server',

View File

@ -26,4 +26,23 @@ class PhotoComment extends Model
{
return $this->belongsTo(User::class, 'created_user_id');
}
public function depth()
{
$depth = 0;
$current = $this;
while (!is_null($current->parent))
{
$current = $current->parent;
$depth++;
}
return $depth;
}
public function parent()
{
return $this->belongsTo(PhotoComment::class, 'parent_comment_id');
}
}

View File

@ -0,0 +1,22 @@
/**
* This model is used by gallery/photo.blade.php, to handle comments and individual photo actions.
* @constructor
*/
function PhotoViewModel() {
this.el = '#photo-app';
this.data = {
is_reply_form_loading: false,
reply_comment_id: 0
};
this.methods = {
replyToComment: function(e) {
var replyButton = $(e.target).closest('.photo-comment');
this.reply_comment_id = replyButton.data('comment-id');
this.is_reply_form_loading = true;
$('#comment-reply-modal').modal('show');
}
};
}

View File

@ -202,6 +202,15 @@ return [
'security_heading' => 'Permissions',
'security_text' => 'You can assign permissions on this album to either groups (recommended) or directly to users.',
'security_users_heading' => 'User Permissions',
'select_all_action' => 'Select all',
'select_all_album_active' => 'Any action you select in the list below will apply to all photos in this album.',
'select_all_choice' => [
'all_action' => 'All in this album',
'message' => 'Do you want to select all the photos in the album, or just those that are visible on this page?',
'title' => 'Select all in album?',
'visible_action' => 'Only those visible'
],
'select_none_action' => 'Clear selection',
'settings' => [
'albums_menu_heading' => 'Albums Navigation Menu',
'albums_menu_number_items' => 'Number of albums to display:',
@ -213,6 +222,7 @@ return [
'analytics_enable_visitor_hits' => 'Enable built-in visitor hit tracking',
'analytics_enable_visitor_hits_description' => 'Visitor hits to the public gallery will be recorded in the Blue Twilight database, allowing for analysis such as the most popular album/photo.',
'analytics_tab' => 'Analytics',
'comments_tab' => 'Comments',
'permissions_cache' => 'Permissions Cache',
'permissions_cache_intro' => 'Blue Twilight maintains the permissions each user has to albums in the database. If you feel these aren\'t correct based on what\'s configured, you can rebuild the cache by clicking the button below.',
'rebuild_permissions_cache' => 'Rebuild Permissions Cache',
@ -225,15 +235,6 @@ return [
'social_tab' => 'Social',
'social_twitter' => 'Twitter'
],
'select_all_action' => 'Select all',
'select_all_album_active' => 'Any action you select in the list below will apply to all photos in this album.',
'select_all_choice' => [
'all_action' => 'All in this album',
'message' => 'Do you want to select all the photos in the album, or just those that are visible on this page?',
'title' => 'Select all in album?',
'visible_action' => 'Only those visible'
],
'select_none_action' => 'Clear selection',
'settings_email_tab' => 'E-mail',
'settings_general_tab' => 'General',
'settings_security_tab' => 'Security',

View File

@ -52,6 +52,8 @@ return [
'select_current_text' => '(current)',
'settings_allow_photo_comments' => 'Allow comments on photos',
'settings_allow_photo_comments_help' => 'With this option enabled, users can comment on individual photos.',
'settings_photo_comments_thread_depth' => 'Maximum depth for nested comments:',
'settings_photo_comments_thread_depth_help' => 'Set to zero to disable nested comments.',
'settings_photo_comments_require_login' => 'Require login before posting comments',
'settings_photo_comments_require_login_help' => 'If this option is enabled, users must login before they can post comments.',
'settings_hotlink_protection' => 'Prevent hot-linking to images',

View File

@ -35,8 +35,10 @@ return [
'other_albums_heading' => 'More Albums in :album_name',
'photo_comment_posted_successfully' => 'Your comment was posted successfully and will appear after it has been moderated.',
'photo_comments_heading' => 'Comments',
'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.',
'photo_comments_reply_modal_title' => 'Reply to comment',
'photos' => 'photo|photos',
'previous_button' => '« Previous Photo',
'show_more_albums' => '... and :count other|... and :count others',

View File

@ -24,6 +24,7 @@
@include(Theme::viewName('partials.tab'), ['active_tab' => 'general', 'tab_name' => 'security', 'tab_icon' => 'lock', 'tab_text' => trans('admin.settings_security_tab')])
@include(Theme::viewName('partials.tab'), ['active_tab' => 'general', 'tab_name' => 'analytics', 'tab_icon' => 'line-chart', 'tab_text' => trans('admin.settings.analytics_tab')])
@include(Theme::viewName('partials.tab'), ['active_tab' => 'general', 'tab_name' => 'social', 'tab_icon' => 'users', 'tab_text' => trans('admin.settings.social_tab')])
@include(Theme::viewName('partials.tab'), ['active_tab' => 'general', 'tab_name' => 'comments', 'tab_icon' => 'edit', 'tab_text' => trans('admin.settings.comments_tab')])
</ul>
{{-- Tab panes --}}
@ -329,22 +330,6 @@
{{-- Social --}}
<div role="tabpanel" class="tab-pane" id="social-tab">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="allow-photo-comments" name="allow_photo_comments" @if (old('allow_photo_comments', UserConfig::get('allow_photo_comments')))checked="checked"@endif>
<label class="form-check-label" for="allow-photo-comments">
<strong>@lang('forms.settings_allow_photo_comments')</strong><br/>
@lang('forms.settings_allow_photo_comments_help')
</label>
</div>
<div class="form-check mt-3">
<input type="checkbox" class="form-check-input" id="photo-comments-require-login" name="photo_comments_require_login" @if (old('photo_comments_require_login', UserConfig::get('photo_comments_require_login')))checked="checked"@endif>
<label class="form-check-label" for="photo-comments-require-login">
<strong>@lang('forms.settings_photo_comments_require_login')</strong><br/>
@lang('forms.settings_photo_comments_require_login_help')
</label>
</div>
<div class="form-check mt-3">
<input type="checkbox" class="form-check-input" id="social-user-profiles" name="social_user_profiles" @if (old('social_user_profiles', UserConfig::get('social_user_profiles')))checked="checked"@endif>
<label class="form-check-label" for="social-user-profiles">
@ -492,6 +477,37 @@
</div>
</div>
</div>
{{-- Comments tab --}}
<div role="tabpanel" class="tab-pane" id="comments-tab">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="allow-photo-comments" name="allow_photo_comments" @if (old('allow_photo_comments', UserConfig::get('allow_photo_comments')))checked="checked"@endif>
<label class="form-check-label" for="allow-photo-comments">
<strong>@lang('forms.settings_allow_photo_comments')</strong><br/>
@lang('forms.settings_allow_photo_comments_help')
</label>
</div>
<div class="form-check mt-3">
<input type="checkbox" class="form-check-input" id="photo-comments-require-login" name="photo_comments_require_login" @if (old('photo_comments_require_login', UserConfig::get('photo_comments_require_login')))checked="checked"@endif>
<label class="form-check-label" for="photo-comments-require-login">
<strong>@lang('forms.settings_photo_comments_require_login')</strong><br/>
@lang('forms.settings_photo_comments_require_login_help')
</label>
</div>
<div class="form-group mt-3">
<label class="form-control-label" for="photo-comments-thread-depth">@lang('forms.settings_photo_comments_thread_depth')</label>
<input type="text" class="form-control{{ $errors->has('photo_comments_thread_depth') ? ' is-invalid' : '' }}" id="photo-comments-thread-depth" name="photo_comments_thread_depth" value="{{ old('photo_comments_thread_depth', $config['photo_comments_thread_depth']) }}" style="max-width: 100px;">
<small class="form-text text-muted">@lang('forms.settings_photo_comments_thread_depth_help')</small>
@if ($errors->has('photo_comments_thread_depth'))
<div class="invalid-feedback">
<strong>{{ $errors->first('photo_comments_thread_depth') }}</strong>
</div>
@endif
</div>
</div>
</div>
<div class="pull-right" style="margin-top: 15px;">

View File

@ -10,7 +10,7 @@
@endsection
@section('content')
<div class="container">
<div class="container" id="photo-app">
<div class="row">
<div class="col">
<h1>{{ $photo->name }}</h1>
@ -157,4 +157,14 @@
</div>
</div>
</div>
@endsection
@endsection
@push('scripts')
<script type="text/javascript">
var photoViewModel = new PhotoViewModel();
$(document).ready(function() {
var app = new Vue(photoViewModel);
});
</script>
@endpush

View File

@ -10,12 +10,32 @@
@if ($photo->approvedComments()->count() > 0)
<ul>
@foreach ($photo->approvedComments as $comment)
<li>
Comment by <b>{{ $comment->createdBy->name }}</b>:<br/>
{{ $comment->comment_text }}
</li>
@include(Theme::viewName('partials.photo_single_comment'))
@endforeach
</ul>
@endif
</div>
</div>
<div class="modal" tabindex="-1" role="dialog" id="comment-reply-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">@lang('gallery.photo_comments_reply_modal_title')</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div v-if="is_reply_form_loading" class="text-center">
<p class="m-2"><img src="{{ asset('ripple.svg') }}" alt="@lang('global.please_wait')" title="@lang('global.please_wait')"></p>
<p>@lang('global.please_wait')</p>
</div>
</div>
<div class="modal-footer" v-if="!is_reply_form_loading">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,8 @@
<li class="photo-comment" data-comment-id="{{ $comment->id }}">
Comment by <b>{{ $comment->createdBy->name }}</b>:<br/>
{{ $comment->comment_text }}
@if ($comment->depth() < UserConfig::get('photo_comments_thread_depth'))
<p><button v-on:click="replyToComment" class="btn btn-sm btn-outline-primary">@lang('gallery.photo_comments_reply_action')</button></p>
@endif
</li>