upvotes: number;
downvotes: number;
borderColor: string;
+ readLoading: boolean;
+ saveLoading: boolean;
}
interface CommentNodeProps {
borderColor: this.props.node.comment.depth
? colorList[this.props.node.comment.depth % colorList.length]
: colorList[0],
+ readLoading: false,
+ saveLoading: false,
};
constructor(props: any, context: any) {
this.state.upvotes = nextProps.node.comment.upvotes;
this.state.downvotes = nextProps.node.comment.downvotes;
this.state.score = nextProps.node.comment.score;
+ this.state.readLoading = false;
+ this.state.saveLoading = false;
this.setState(this.state);
}
: i18n.t('mark_as_read')
}
>
- <svg
- class={`icon icon-inline ${node.comment.read &&
- 'text-success'}`}
- >
- <use xlinkHref="#icon-check"></use>
- </svg>
+ {this.state.readLoading ? (
+ this.loadingIcon
+ ) : (
+ <svg
+ class={`icon icon-inline ${node.comment.read &&
+ 'text-success'}`}
+ >
+ <use xlinkHref="#icon-check"></use>
+ </svg>
+ )}
</button>
</li>
)}
<li className="list-inline-item">
<button
class="btn btn-link btn-sm btn-animate text-muted"
- onClick={linkEvent(this, this.handleReplyClick)}
- data-tippy-content={i18n.t('reply')}
+ onClick={linkEvent(this, this.handleSaveCommentClick)}
+ data-tippy-content={
+ node.comment.saved
+ ? i18n.t('unsave')
+ : i18n.t('save')
+ }
>
- <svg class="icon icon-inline">
- <use xlinkHref="#icon-reply1"></use>
- </svg>
+ {this.state.saveLoading ? (
+ this.loadingIcon
+ ) : (
+ <svg
+ class={`icon icon-inline ${node.comment.saved &&
+ 'text-warning'}`}
+ >
+ <use xlinkHref="#icon-star"></use>
+ </svg>
+ )}
</button>
</li>
<li className="list-inline-item">
- <Link
- className="btn btn-link btn-sm btn-animate text-muted"
- to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}
- title={i18n.t('link')}
+ <button
+ class="btn btn-link btn-sm btn-animate text-muted"
+ onClick={linkEvent(this, this.handleReplyClick)}
+ data-tippy-content={i18n.t('reply')}
>
<svg class="icon icon-inline">
- <use xlinkHref="#icon-link"></use>
+ <use xlinkHref="#icon-reply1"></use>
</svg>
- </Link>
+ </button>
</li>
+ {this.props.markable && this.linkBtn}
{!this.state.showAdvanced ? (
<li className="list-inline-item">
<button
</Link>
</li>
)}
- <li className="list-inline-item">
- <button
- class="btn btn-link btn-sm btn-animate text-muted"
- onClick={linkEvent(
- this,
- this.handleSaveCommentClick
- )}
- data-tippy-content={
- node.comment.saved
- ? i18n.t('unsave')
- : i18n.t('save')
- }
- >
- <svg
- class={`icon icon-inline ${node.comment.saved &&
- 'text-warning'}`}
- >
- <use xlinkHref="#icon-star"></use>
- </svg>
- </button>
- </li>
+ {!this.props.markable && this.linkBtn}
<li className="list-inline-item">
<button
className="btn btn-link btn-sm btn-animate text-muted"
);
}
+ get linkBtn() {
+ let node = this.props.node;
+ return (
+ <li className="list-inline-item">
+ <Link
+ className="btn btn-link btn-sm btn-animate text-muted"
+ to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}
+ title={i18n.t('link')}
+ >
+ <svg class="icon icon-inline">
+ <use xlinkHref="#icon-link"></use>
+ </svg>
+ </Link>
+ </li>
+ );
+ }
+
+ get loadingIcon() {
+ return (
+ <svg class="icon icon-spinner spin">
+ <use xlinkHref="#icon-spinner"></use>
+ </svg>
+ );
+ }
+
get myComment(): boolean {
return (
UserService.Instance.user &&
};
WebSocketService.Instance.saveComment(form);
+
+ i.state.saveLoading = true;
+ i.setState(this.state);
}
handleReplyCancel() {
};
WebSocketService.Instance.editComment(form);
}
+
+ i.state.readLoading = true;
+ i.setState(this.state);
}
handleModBanFromCommunityShow(i: CommentNode) {
render() {
let message = this.props.privateMessage;
return (
- <div class="mb-2">
+ <div class="border-top border-light">
<div>
<ul class="list-inline mb-0 text-muted small">
<li className="list-inline-item">
dangerouslySetInnerHTML={mdToHtml(this.messageUnlessRemoved)}
/>
)}
- <ul class="list-inline mb-1 text-muted h5 font-weight-bold">
+ <ul class="list-inline mb-0 text-muted font-weight-bold">
{!this.mine && (
<>
- <li className="list-inline-item-action">
- <span
- class="pointer"
+ <li className="list-inline-item">
+ <button
+ class="btn btn-link btn-sm btn-animate text-muted"
onClick={linkEvent(this, this.handleMarkRead)}
data-tippy-content={
message.read
>
<use xlinkHref="#icon-check"></use>
</svg>
- </span>
+ </button>
</li>
- <li className="list-inline-item-action">
- <span
- class="pointer"
+ <li className="list-inline-item">
+ <button
+ class="btn btn-link btn-sm btn-animate text-muted"
onClick={linkEvent(this, this.handleReplyClick)}
data-tippy-content={i18n.t('reply')}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-reply1"></use>
</svg>
- </span>
+ </button>
</li>
</>
)}
{this.mine && (
<>
- <li className="list-inline-item-action">
- <span
- class="pointer"
+ <li className="list-inline-item">
+ <button
+ class="btn btn-link btn-sm btn-animate text-muted"
onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={i18n.t('edit')}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-edit"></use>
</svg>
- </span>
+ </button>
</li>
- <li className="list-inline-item-action">
- <span
- class="pointer"
+ <li className="list-inline-item">
+ <button
+ class="btn btn-link btn-sm btn-animate text-muted"
onClick={linkEvent(this, this.handleDeleteClick)}
data-tippy-content={
!message.deleted
>
<use xlinkHref="#icon-trash"></use>
</svg>
- </span>
+ </button>
</li>
</>
)}
- <li className="list-inline-item-action">
- <span
- className="pointer"
+ <li className="list-inline-item">
+ <button
+ class="btn btn-link btn-sm btn-animate text-muted"
onClick={linkEvent(this, this.handleViewSource)}
data-tippy-content={i18n.t('view_source')}
>
>
<use xlinkHref="#icon-file-text"></use>
</svg>
- </span>
+ </button>
</li>
</ul>
</div>