Comments: Updated reply-to and general styling

Updated reply inidicator to fit with new nesting system, only showing on
view when nest within nesting structure.

Updated the general design to be a bit cleaner and better adapt on
mobile.

Tested on FF+Chrome, inc. dark mode.
This commit is contained in:
Dan Brown 2023-06-09 17:36:30 +01:00
parent 3bede42121
commit 19e39ddd1f
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
6 changed files with 98 additions and 69 deletions

View File

@ -365,6 +365,7 @@ return [
'comment_new' => 'New Comment', 'comment_new' => 'New Comment',
'comment_created' => 'commented :createDiff', 'comment_created' => 'commented :createDiff',
'comment_updated' => 'Updated :updateDiff by :username', 'comment_updated' => 'Updated :updateDiff by :username',
'comment_updated_indicator' => 'Updated',
'comment_deleted_success' => 'Comment deleted', 'comment_deleted_success' => 'Comment deleted',
'comment_created_success' => 'Comment added', 'comment_created_success' => 'Comment added',
'comment_updated_success' => 'Comment updated', 'comment_updated_success' => 'Comment updated',

View File

@ -25,14 +25,22 @@ export class PageComment extends Component {
} }
setupListeners() { setupListeners() {
this.replyButton.addEventListener('click', () => this.$emit('reply', { if (this.replyButton) {
id: this.commentLocalId, this.replyButton.addEventListener('click', () => this.$emit('reply', {
element: this.container, id: this.commentLocalId,
})); element: this.container,
this.editButton.addEventListener('click', this.startEdit.bind(this)); }));
this.deleteButton.addEventListener('click', this.delete.bind(this)); }
this.form.addEventListener('submit', this.update.bind(this));
this.formCancel.addEventListener('click', () => this.toggleEditMode(false)); if (this.editButton) {
this.editButton.addEventListener('click', this.startEdit.bind(this));
this.form.addEventListener('submit', this.update.bind(this));
this.formCancel.addEventListener('click', () => this.toggleEditMode(false));
}
if (this.deleteButton) {
this.deleteButton.addEventListener('click', this.delete.bind(this));
}
} }
toggleEditMode(show) { toggleEditMode(show) {

View File

@ -16,6 +16,7 @@ export class PageComments extends Component {
this.formContainer = this.$refs.formContainer; this.formContainer = this.$refs.formContainer;
this.form = this.$refs.form; this.form = this.$refs.form;
this.formInput = this.$refs.formInput; this.formInput = this.$refs.formInput;
this.formReplyLink = this.$refs.formReplyLink;
this.addCommentButton = this.$refs.addCommentButton; this.addCommentButton = this.$refs.addCommentButton;
this.hideFormButton = this.$refs.hideFormButton; this.hideFormButton = this.$refs.hideFormButton;
this.removeReplyToButton = this.$refs.removeReplyToButton; this.removeReplyToButton = this.$refs.removeReplyToButton;
@ -26,6 +27,7 @@ export class PageComments extends Component {
// Internal State // Internal State
this.parentId = null; this.parentId = null;
this.formReplyText = this.formReplyLink.textContent;
this.setupListeners(); this.setupListeners();
} }
@ -86,13 +88,15 @@ export class PageComments extends Component {
resetForm() { resetForm() {
this.formInput.value = ''; this.formInput.value = '';
this.removeReplyTo(); this.parentId = null;
this.replyToRow.toggleAttribute('hidden', true);
this.container.append(this.formContainer); this.container.append(this.formContainer);
} }
showForm() { showForm() {
this.formContainer.toggleAttribute('hidden', false); this.formContainer.toggleAttribute('hidden', false);
this.addButtonContainer.toggleAttribute('hidden', true); this.addButtonContainer.toggleAttribute('hidden', true);
this.formContainer.scrollIntoView({behavior: 'smooth', block: 'nearest'});
setTimeout(() => { setTimeout(() => {
this.formInput.focus(); this.formInput.focus();
}, 100); }, 100);
@ -115,19 +119,20 @@ export class PageComments extends Component {
setReply(commentLocalId, commentElement) { setReply(commentLocalId, commentElement) {
const targetFormLocation = commentElement.closest('.comment-branch').querySelector('.comment-branch-children'); const targetFormLocation = commentElement.closest('.comment-branch').querySelector('.comment-branch-children');
this.showForm();
targetFormLocation.append(this.formContainer); targetFormLocation.append(this.formContainer);
this.formContainer.scrollIntoView({behavior: 'smooth', block: 'nearest'}); this.showForm();
this.parentId = commentLocalId; this.parentId = commentLocalId;
this.replyToRow.toggleAttribute('hidden', false); this.replyToRow.toggleAttribute('hidden', false);
const replyLink = this.replyToRow.querySelector('a'); const replyLink = this.replyToRow.querySelector('a');
replyLink.textContent = `#${this.parentId}`; replyLink.textContent = this.formReplyText.replace('1234', this.parentId);
replyLink.href = `#comment${this.parentId}`; replyLink.href = `#comment${this.parentId}`;
} }
removeReplyTo() { removeReplyTo() {
this.parentId = null; this.parentId = null;
this.replyToRow.toggleAttribute('hidden', true); this.replyToRow.toggleAttribute('hidden', true);
this.container.append(this.formContainer);
this.showForm();
} }
} }

View File

@ -691,26 +691,28 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
.actions button:focus { .actions button:focus {
outline: 1px dotted var(--color-primary); outline: 1px dotted var(--color-primary);
} }
@include smaller-than($m) {
.actions {
opacity: 1;
}
}
} }
.comment-box .header { .comment-box .header {
.meta { border-bottom: 1px solid #DDD;
img, a, span { @include lightDark(border-color, #DDD, #000);
display: inline-block; button {
vertical-align: top; font-size: .8rem;
} }
a, span { a {
padding: $-xxs 0 $-xxs 0; color: inherit;
line-height: 1.6;
}
a { color: #666; }
span {
padding-inline-start: $-xxs;
}
} }
.text-muted { .text-muted {
color: #999; color: #999;
} }
.right-meta .text-muted {
opacity: .8;
}
} }
.comment-thread-indicator { .comment-thread-indicator {
@ -725,6 +727,14 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
display: none; display: none;
} }
.comment-reply {
display: none;
}
.comment-branch .comment-branch .comment-branch .comment-branch .comment-reply {
display: block;
}
#tag-manager .drag-card { #tag-manager .drag-card {
max-width: 500px; max-width: 500px;
} }

View File

@ -7,63 +7,68 @@
id="comment{{$comment->local_id}}" id="comment{{$comment->local_id}}"
class="comment-box"> class="comment-box">
<div class="header p-s"> <div class="header p-s">
<div class="grid half left-focus no-gap v-center"> <div class="flex-container-row justify-space-between wrap">
<div class="meta text-muted text-small"> <div class="meta text-muted flex-container-row items-center">
<a href="#comment{{$comment->local_id}}">#{{$comment->local_id}}</a>
&nbsp;&nbsp;
@if ($comment->createdBy) @if ($comment->createdBy)
<img width="50" src="{{ $comment->createdBy->getAvatar(50) }}" class="avatar" alt="{{ $comment->createdBy->name }}"> <img width="50" src="{{ $comment->createdBy->getAvatar(50) }}" class="avatar mx-xs" alt="{{ $comment->createdBy->name }}">
&nbsp; &nbsp;
<a href="{{ $comment->createdBy->getProfileUrl() }}">{{ $comment->createdBy->name }}</a> <a href="{{ $comment->createdBy->getProfileUrl() }}">{{ $comment->createdBy->getShortName(16) }}</a>
@else @else
<span>{{ trans('common.deleted_user') }}</span> {{ trans('common.deleted_user') }}
@endif @endif
<span title="{{ $comment->created_at }}">{{ trans('entities.comment_created', ['createDiff' => $comment->created]) }}</span> <span title="{{ $comment->created_at }}">&nbsp;{{ trans('entities.comment_created', ['createDiff' => $comment->created]) }}</span>
@if($comment->isUpdated()) @if($comment->isUpdated())
<span title="{{ $comment->updated_at }}"> <span class="mx-xs">&bull;</span>
&bull;&nbsp; <span title="{{ trans('entities.comment_updated', ['updateDiff' => $comment->updated_at, 'username' => $comment->updatedBy->name ?? trans('common.deleted_user')]) }}">
{{ trans('entities.comment_updated', ['updateDiff' => $comment->updated, 'username' => $comment->updatedBy? $comment->updatedBy->name : trans('common.deleted_user')]) }} {{ trans('entities.comment_updated_indicator') }}
</span> </span>
@endif @endif
</div> </div>
<div class="actions text-right"> <div class="right-meta flex-container-row justify-flex-end items-center px-s">
@if(userCan('comment-update', $comment)) <div class="actions mr-s">
<button refs="page-comment@edit-button" type="button" class="text-button icon p-xs" aria-label="{{ trans('common.edit') }}" title="{{ trans('common.edit') }}">@icon('edit')</button> @if(userCan('comment-create-all'))
@endif <button refs="page-comment@reply-button" type="button" class="text-button text-muted hover-underline p-xs">@icon('reply') {{ trans('common.reply') }}</button>
@if(userCan('comment-create-all')) @endif
<button refs="page-comment@reply-button" type="button" class="text-button icon p-xs" aria-label="{{ trans('common.reply') }}" title="{{ trans('common.reply') }}">@icon('reply')</button> @if(userCan('comment-update', $comment))
@endif <button refs="page-comment@edit-button" type="button" class="text-button text-muted hover-underline p-xs">@icon('edit') {{ trans('common.edit') }}</button>
@if(userCan('comment-delete', $comment)) @endif
<div component="dropdown" class="dropdown-container"> @if(userCan('comment-delete', $comment))
<button type="button" refs="dropdown@toggle" aria-haspopup="true" aria-expanded="false" class="text-button icon p-xs" title="{{ trans('common.delete') }}">@icon('delete')</button> <div component="dropdown" class="dropdown-container">
<ul refs="dropdown@menu" class="dropdown-menu" role="menu"> <button type="button" refs="dropdown@toggle" aria-haspopup="true" aria-expanded="false" class="text-button text-muted hover-underline p-xs">@icon('delete') {{ trans('common.delete') }}</button>
<li class="px-m text-small text-muted pb-s">{{trans('entities.comment_delete_confirm')}}</li> <ul refs="dropdown@menu" class="dropdown-menu" role="menu">
<li> <li class="px-m text-small text-muted pb-s">{{trans('entities.comment_delete_confirm')}}</li>
<button refs="page-comment@delete-button" type="button" class="text-button text-neg icon-item"> <li>
@icon('delete') <button refs="page-comment@delete-button" type="button" class="text-button text-neg icon-item">
<div>{{ trans('common.delete') }}</div> @icon('delete')
</button> <div>{{ trans('common.delete') }}</div>
</li> </button>
</ul> </li>
</div> </ul>
@endif </div>
@endif
<span class="text-muted">
&nbsp;&bull;&nbsp;
</span>
</div>
<div>
<a class="bold text-muted" href="#comment{{$comment->local_id}}">#{{$comment->local_id}}</a>
</div>
</div> </div>
</div> </div>
</div> </div>
@if ($comment->parent_id) <div refs="page-comment@content-container" class="content px-m py-s">
<div class="reply-row primary-background-light text-muted px-s py-xs mb-s"> @if ($comment->parent_id)
{!! trans('entities.comment_in_reply_to', ['commentId' => '<a href="#comment'.$comment->parent_id.'">#'.$comment->parent_id.'</a>']) !!} <p class="comment-reply mb-xxs">
</div> <a class="text-muted text-small" href="#comment{{ $comment->parent_id }}">@icon('reply'){{ trans('entities.comment_in_reply_to', ['commentId' => '#' . $comment->parent_id]) }}</a>
@endif </p>
@endif
<div refs="page-comment@content-container" class="content px-s pb-s">
{!! $comment->html !!} {!! $comment->html !!}
</div> </div>
@if(userCan('comment-update', $comment)) @if(userCan('comment-update', $comment))
<form novalidate refs="page-comment@form" hidden class="content px-s block"> <form novalidate refs="page-comment@form" hidden class="content pt-s px-s block">
<div class="form-group description-input"> <div class="form-group description-input">
<textarea refs="page-comment@input" name="markdown" rows="3" placeholder="{{ trans('entities.comment_placeholder') }}">{{ $comment->text }}</textarea> <textarea refs="page-comment@input" name="markdown" rows="3" placeholder="{{ trans('entities.comment_placeholder') }}">{{ $comment->text }}</textarea>
</div> </div>

View File

@ -2,10 +2,10 @@
<div class="comment-box"> <div class="comment-box">
<div class="header p-s">{{ trans('entities.comment_new') }}</div> <div class="header p-s">{{ trans('entities.comment_new') }}</div>
<div refs="page-comments@reply-to-row" hidden class="primary-background-light text-muted px-s py-xs mb-s"> <div refs="page-comments@reply-to-row" hidden class="primary-background-light text-muted px-s py-xs">
<div class="grid left-focus v-center"> <div class="grid left-focus v-center">
<div> <div>
{!! trans('entities.comment_in_reply_to', ['commentId' => '<a href=""></a>']) !!} <a refs="page-comments@form-reply-link" href="#">{{ trans('entities.comment_in_reply_to', ['commentId' => '1234']) }}</a>
</div> </div>
<div class="text-right"> <div class="text-right">
<button refs="page-comments@remove-reply-to-button" class="text-button">{{ trans('common.remove') }}</button> <button refs="page-comments@remove-reply-to-button" class="text-button">{{ trans('common.remove') }}</button>
@ -13,7 +13,7 @@
</div> </div>
</div> </div>
<div class="content px-s"> <div class="content px-s pt-s">
<form refs="page-comments@form" novalidate> <form refs="page-comments@form" novalidate>
<div class="form-group description-input"> <div class="form-group description-input">
<textarea refs="page-comments@form-input" name="markdown" <textarea refs="page-comments@form-input" name="markdown"