Changing comment actions to flex row. Fixes #611

pull/722/head
Dessalines 2020-03-21 00:15:45 -04:00
parent 1f0439badd
commit 32c85599b6
1 changed files with 372 additions and 426 deletions

View File

@ -147,88 +147,79 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
this.props.node.comment.parent_id && this.props.node.comment.parent_id &&
'ml-2'}`} 'ml-2'}`}
> >
<ul class="list-inline mb-1 text-muted small"> <div class="d-flex align-items-center mb-1 mt-1 text-muted small">
<li className="mt-1 list-inline-item"> <Link
<Link className="mr-2 text-body font-weight-bold"
className="text-body font-weight-bold" to={`/u/${node.comment.creator_name}`}
to={`/u/${node.comment.creator_name}`} >
> {node.comment.creator_avatar && showAvatars() && (
{node.comment.creator_avatar && showAvatars() && ( <img
<img height="32"
height="32" width="32"
width="32" src={pictshareAvatarThumbnail(node.comment.creator_avatar)}
src={pictshareAvatarThumbnail( class="rounded-circle mr-1"
node.comment.creator_avatar />
)} )}
class="rounded-circle mr-1" <span>{node.comment.creator_name}</span>
/> </Link>
)}
<span>{node.comment.creator_name}</span>
</Link>
</li>
{this.isMod && ( {this.isMod && (
<li className="list-inline-item badge badge-light d-none d-sm-inline"> <div className="badge badge-light d-none d-sm-inline mr-2">
{i18n.t('mod')} {i18n.t('mod')}
</li> </div>
)} )}
{this.isAdmin && ( {this.isAdmin && (
<li className="list-inline-item badge badge-light d-none d-sm-inline"> <div className="badge badge-light d-none d-sm-inline mr-2">
{i18n.t('admin')} {i18n.t('admin')}
</li> </div>
)} )}
{this.isPostCreator && ( {this.isPostCreator && (
<li className="list-inline-item badge badge-light d-none d-sm-inline"> <div className="badge badge-light d-none d-sm-inline mr-2">
{i18n.t('creator')} {i18n.t('creator')}
</li> </div>
)} )}
{(node.comment.banned_from_community || node.comment.banned) && ( {(node.comment.banned_from_community || node.comment.banned) && (
<li className="list-inline-item badge badge-danger"> <div className="badge badge-danger mr-2">
{i18n.t('banned')} {i18n.t('banned')}
</li>
)}
<li className="list-inline-item">
<div
className="unselectable pointer text-monospace"
onClick={linkEvent(this, this.handleCommentCollapse)}
>
{this.state.collapsed ? (
<svg class="icon icon-inline">
<use xlinkHref="#icon-plus-square"></use>
</svg>
) : (
<svg class="icon icon-inline">
<use xlinkHref="#icon-minus-square"></use>
</svg>
)}
</div> </div>
</li> )}
{this.props.showCommunity && ( {this.props.showCommunity && (
<li className="list-inline-item"> <>
<span> {i18n.t('to')} </span> <span class="mx-1">{i18n.t('to')}</span>
<Link to={`/c/${node.comment.community_name}`}> <Link class="mr-2" to={`/c/${node.comment.community_name}`}>
{node.comment.community_name} {node.comment.community_name}
</Link> </Link>
</li> </>
)} )}
<li className="ml-3 list-inline-item"> <div
<span className="mr-lg-4 flex-grow-1 flex-lg-grow-0 unselectable pointer mr-2"
className={`unselectable pointer ${this.scoreColor}`} onClick={linkEvent(this, this.handleCommentCollapse)}
onClick={linkEvent(node, this.handleCommentUpvote)} >
data-tippy-content={this.pointsTippy} {this.state.collapsed ? (
> <svg class="icon icon-inline">
<svg class="icon icon-inline mr-1"> <use xlinkHref="#icon-plus-square"></use>
<use xlinkHref="#icon-zap"></use>
</svg> </svg>
{this.state.score} ) : (
</span> <svg class="icon icon-inline">
</li> <use xlinkHref="#icon-minus-square"></use>
<li className="list-inline-item"></li> </svg>
<li className="list-inline-item"> )}
<span> </div>
<MomentTime data={node.comment} /> <span
</span> className={`unselectable pointer ${this.scoreColor}`}
</li> onClick={linkEvent(node, this.handleCommentUpvote)}
</ul> data-tippy-content={this.pointsTippy}
>
<svg class="icon icon-inline mr-1">
<use xlinkHref="#icon-zap"></use>
</svg>
<span class="mr-1">{this.state.score}</span>
</span>
<span className="mr-1"></span>
<span>
<MomentTime data={node.comment} />
</span>
</div>
{/* end of user row */}
{this.state.showEdit && ( {this.state.showEdit && (
<CommentForm <CommentForm
node={node} node={node}
@ -249,124 +240,107 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
)} )}
/> />
)} )}
<ul class="list-inline mb-0 text-muted font-weight-bold small"> <div class="d-flex justify-content-between justify-content-lg-start flex-wrap text-muted font-weight-bold">
{this.props.showContext && this.linkBtn} {this.props.showContext && this.linkBtn}
{this.props.markable && ( {this.props.markable && (
<li className="list-inline-item"> <button
<button class="btn btn-link btn-animate text-muted"
class="btn btn-link btn-sm btn-animate text-muted" onClick={linkEvent(this, this.handleMarkRead)}
onClick={linkEvent(this, this.handleMarkRead)} data-tippy-content={
data-tippy-content={ node.comment.read
node.comment.read ? i18n.t('mark_as_unread')
? i18n.t('mark_as_unread') : i18n.t('mark_as_read')
: i18n.t('mark_as_read') }
} >
> {this.state.readLoading ? (
{this.state.readLoading ? ( this.loadingIcon
this.loadingIcon ) : (
) : ( <svg
<svg class={`icon icon-inline ${node.comment.read &&
class={`icon icon-inline ${node.comment.read && 'text-success'}`}
'text-success'}`} >
> <use xlinkHref="#icon-check"></use>
<use xlinkHref="#icon-check"></use> </svg>
</svg> )}
)} </button>
</button>
</li>
)} )}
{UserService.Instance.user && !this.props.viewOnly && ( {UserService.Instance.user && !this.props.viewOnly && (
<> <>
<li className="list-inline-item"> <button
className={`btn btn-link btn-animate ${
this.state.my_vote == 1 ? 'text-info' : 'text-muted'
}`}
onClick={linkEvent(node, this.handleCommentUpvote)}
data-tippy-content={i18n.t('upvote')}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-arrow-up"></use>
</svg>
{this.state.upvotes !== this.state.score && (
<span class="ml-1">{this.state.upvotes}</span>
)}
</button>
{WebSocketService.Instance.site.enable_downvotes && (
<button <button
className={`btn btn-link btn-sm btn-animate ${ className={`btn btn-link btn-animate ${
this.state.my_vote == 1 ? 'text-info' : 'text-muted' this.state.my_vote == -1
? 'text-danger'
: 'text-muted'
}`} }`}
onClick={linkEvent(node, this.handleCommentUpvote)} onClick={linkEvent(node, this.handleCommentDownvote)}
data-tippy-content={i18n.t('upvote')} data-tippy-content={i18n.t('downvote')}
> >
<svg class="icon icon-inline"> <svg class="icon icon-inline">
<use xlinkHref="#icon-arrow-up"></use> <use xlinkHref="#icon-arrow-down"></use>
</svg> </svg>
{this.state.upvotes !== this.state.score && ( {this.state.upvotes !== this.state.score && (
<span class="ml-1">{this.state.upvotes}</span> <span class="ml-1">{this.state.downvotes}</span>
)} )}
</button> </button>
</li>
{WebSocketService.Instance.site.enable_downvotes && (
<li className="list-inline-item">
<button
className={`btn btn-link btn-sm btn-animate ${
this.state.my_vote == -1
? 'text-danger'
: 'text-muted'
}`}
onClick={linkEvent(
node,
this.handleCommentDownvote
)}
data-tippy-content={i18n.t('downvote')}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-arrow-down"></use>
</svg>
{this.state.upvotes !== this.state.score && (
<span class="ml-1">{this.state.downvotes}</span>
)}
</button>
</li>
)} )}
<li className="list-inline-item"> <button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleSaveCommentClick)}
data-tippy-content={
node.comment.saved ? i18n.t('unsave') : i18n.t('save')
}
>
{this.state.saveLoading ? (
this.loadingIcon
) : (
<svg
class={`icon icon-inline ${node.comment.saved &&
'text-warning'}`}
>
<use xlinkHref="#icon-star"></use>
</svg>
)}
</button>
<button
class="btn btn-link 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>
</button>
{!this.state.showAdvanced ? (
<button <button
class="btn btn-link btn-sm btn-animate text-muted" className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleSaveCommentClick)} onClick={linkEvent(this, this.handleShowAdvanced)}
data-tippy-content={ data-tippy-content={i18n.t('more')}
node.comment.saved
? i18n.t('unsave')
: i18n.t('save')
}
>
{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">
<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"> <svg class="icon icon-inline">
<use xlinkHref="#icon-reply1"></use> <use xlinkHref="#icon-more-vertical"></use>
</svg> </svg>
</button> </button>
</li>
{!this.state.showAdvanced ? (
<li className="list-inline-item">
<button
className="btn btn-link btn-sm btn-animate text-muted"
onClick={linkEvent(this, this.handleShowAdvanced)}
data-tippy-content={i18n.t('more')}
>
<svg class="icon icon-inline">
<use xlinkHref="#icon-more-vertical"></use>
</svg>
</button>
</li>
) : ( ) : (
<> <>
{!this.myComment && ( {!this.myComment && (
<li className="list-inline-item"> <button class="btn btn-link btn-animate">
<Link <Link
class="btn btn-link btn-sm btn-animate text-muted" class="text-muted"
to={`/create_private_message?recipient_id=${node.comment.creator_id}`} to={`/create_private_message?recipient_id=${node.comment.creator_id}`}
title={i18n.t('message').toLowerCase()} title={i18n.t('message').toLowerCase()}
> >
@ -374,320 +348,292 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<use xlinkHref="#icon-mail"></use> <use xlinkHref="#icon-mail"></use>
</svg> </svg>
</Link> </Link>
</li> </button>
)} )}
{!this.props.showContext && this.linkBtn} {!this.props.showContext && this.linkBtn}
<li className="list-inline-item"> <button
<button className="btn btn-link btn-animate text-muted"
className="btn btn-link btn-sm btn-animate text-muted" onClick={linkEvent(this, this.handleViewSource)}
onClick={linkEvent(this, this.handleViewSource)} data-tippy-content={i18n.t('view_source')}
data-tippy-content={i18n.t('view_source')} >
<svg
class={`icon icon-inline ${this.state
.viewSource && 'text-success'}`}
> >
<svg <use xlinkHref="#icon-file-text"></use>
class={`icon icon-inline ${this.state </svg>
.viewSource && 'text-success'}`} </button>
>
<use xlinkHref="#icon-file-text"></use>
</svg>
</button>
</li>
{this.myComment && ( {this.myComment && (
<> <>
<li className="list-inline-item"></li> <button
<li className="list-inline-item"> class="btn btn-link btn-animate text-muted"
<button onClick={linkEvent(this, this.handleEditClick)}
class="btn btn-link btn-sm btn-animate text-muted" data-tippy-content={i18n.t('edit')}
onClick={linkEvent( >
this, <svg class="icon icon-inline">
this.handleEditClick <use xlinkHref="#icon-edit"></use>
)} </svg>
data-tippy-content={i18n.t('edit')} </button>
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleDeleteClick
)}
data-tippy-content={
!node.comment.deleted
? i18n.t('delete')
: i18n.t('restore')
}
>
<svg
class={`icon icon-inline ${node.comment
.deleted && 'text-danger'}`}
> >
<svg class="icon icon-inline"> <use xlinkHref="#icon-trash"></use>
<use xlinkHref="#icon-edit"></use> </svg>
</svg> </button>
</button>
</li>
<li className="list-inline-item">
<button
class="btn btn-link btn-sm btn-animate text-muted"
onClick={linkEvent(
this,
this.handleDeleteClick
)}
data-tippy-content={
!node.comment.deleted
? i18n.t('delete')
: i18n.t('restore')
}
>
<svg
class={`icon icon-inline ${node.comment
.deleted && 'text-danger'}`}
>
<use xlinkHref="#icon-trash"></use>
</svg>
</button>
</li>
</> </>
)} )}
{/* Admins and mods can remove comments */} {/* Admins and mods can remove comments */}
{(this.canMod || this.canAdmin) && ( {(this.canMod || this.canAdmin) && (
<> <>
<li className="list-inline-item"> {!node.comment.removed ? (
{!node.comment.removed ? ( <button
<span class="btn btn-link btn-animate text-muted"
class="pointer" onClick={linkEvent(
onClick={linkEvent( this,
this, this.handleModRemoveShow
this.handleModRemoveShow )}
)} >
> {i18n.t('remove')}
{i18n.t('remove')} </button>
</span> ) : (
) : ( <button
<span class="btn btn-link btn-animate text-muted"
class="pointer" onClick={linkEvent(
onClick={linkEvent( this,
this, this.handleModRemoveSubmit
this.handleModRemoveSubmit )}
)} >
> {i18n.t('restore')}
{i18n.t('restore')} </button>
</span> )}
)}
</li>
</> </>
)} )}
{/* Mods can ban from community, and appoint as mods to community */} {/* Mods can ban from community, and appoint as mods to community */}
{this.canMod && ( {this.canMod && (
<> <>
{!this.isMod && ( {!this.isMod &&
<li className="list-inline-item"> (!node.comment.banned_from_community ? (
{!node.comment.banned_from_community ? ( <button
<span class="btn btn-link btn-animate text-muted"
class="pointer" onClick={linkEvent(
this,
this.handleModBanFromCommunityShow
)}
>
{i18n.t('ban')}
</button>
) : (
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleModBanFromCommunitySubmit
)}
>
{i18n.t('unban')}
</button>
))}
{!node.comment.banned_from_community &&
(!this.state.showConfirmAppointAsMod ? (
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleShowConfirmAppointAsMod
)}
>
{this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')}
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
</button>
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent( onClick={linkEvent(
this, this,
this.handleModBanFromCommunityShow this.handleAddModToCommunity
)} )}
> >
{i18n.t('ban')} {i18n.t('yes')}
</span> </button>
) : ( <button
<span class="btn btn-link btn-animate text-muted"
class="pointer"
onClick={linkEvent( onClick={linkEvent(
this, this,
this.handleModBanFromCommunitySubmit this.handleCancelConfirmAppointAsMod
)} )}
> >
{i18n.t('unban')} {i18n.t('no')}
</span> </button>
)} </>
</li> ))}
)}
{!node.comment.banned_from_community && (
<li className="list-inline-item">
{!this.state.showConfirmAppointAsMod ? (
<span
class="pointer"
onClick={linkEvent(
this,
this.handleShowConfirmAppointAsMod
)}
>
{this.isMod
? i18n.t('remove_as_mod')
: i18n.t('appoint_as_mod')}
</span>
) : (
<>
<span class="d-inline-block mr-1">
{i18n.t('are_you_sure')}
</span>
<span
class="pointer d-inline-block mr-1"
onClick={linkEvent(
this,
this.handleAddModToCommunity
)}
>
{i18n.t('yes')}
</span>
<span
class="pointer d-inline-block"
onClick={linkEvent(
this,
this.handleCancelConfirmAppointAsMod
)}
>
{i18n.t('no')}
</span>
</>
)}
</li>
)}
</> </>
)} )}
{/* Community creators and admins can transfer community to another mod */} {/* Community creators and admins can transfer community to another mod */}
{(this.amCommunityCreator || this.canAdmin) && {(this.amCommunityCreator || this.canAdmin) &&
this.isMod && ( this.isMod &&
<li className="list-inline-item"> (!this.state.showConfirmTransferCommunity ? (
{!this.state.showConfirmTransferCommunity ? ( <button
<span class="btn btn-link btn-animate text-muted"
class="pointer" onClick={linkEvent(
onClick={linkEvent( this,
this, this.handleShowConfirmTransferCommunity
this.handleShowConfirmTransferCommunity
)}
>
{i18n.t('transfer_community')}
</span>
) : (
<>
<span class="d-inline-block mr-1">
{i18n.t('are_you_sure')}
</span>
<span
class="pointer d-inline-block mr-1"
onClick={linkEvent(
this,
this.handleTransferCommunity
)}
>
{i18n.t('yes')}
</span>
<span
class="pointer d-inline-block"
onClick={linkEvent(
this,
this
.handleCancelShowConfirmTransferCommunity
)}
>
{i18n.t('no')}
</span>
</>
)} )}
</li> >
)} {i18n.t('transfer_community')}
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
</button>
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleTransferCommunity
)}
>
{i18n.t('yes')}
</button>
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this
.handleCancelShowConfirmTransferCommunity
)}
>
{i18n.t('no')}
</button>
</>
))}
{/* Admins can ban from all, and appoint other admins */} {/* Admins can ban from all, and appoint other admins */}
{this.canAdmin && ( {this.canAdmin && (
<> <>
{!this.isAdmin && ( {!this.isAdmin &&
<li className="list-inline-item"> (!node.comment.banned ? (
{!node.comment.banned ? ( <button
<span class="btn btn-link btn-animate text-muted"
class="pointer" onClick={linkEvent(
this,
this.handleModBanShow
)}
>
{i18n.t('ban_from_site')}
</button>
) : (
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleModBanSubmit
)}
>
{i18n.t('unban_from_site')}
</button>
))}
{!node.comment.banned &&
(!this.state.showConfirmAppointAsAdmin ? (
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleShowConfirmAppointAsAdmin
)}
>
{this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')}
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
</button>
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent( onClick={linkEvent(
this, this,
this.handleModBanShow this.handleAddAdmin
)} )}
> >
{i18n.t('ban_from_site')} {i18n.t('yes')}
</span> </button>
) : ( <button
<span class="btn btn-link btn-animate text-muted"
class="pointer"
onClick={linkEvent( onClick={linkEvent(
this, this,
this.handleModBanSubmit this.handleCancelConfirmAppointAsAdmin
)} )}
> >
{i18n.t('unban_from_site')} {i18n.t('no')}
</span> </button>
)} </>
</li> ))}
)}
{!node.comment.banned && (
<li className="list-inline-item">
{!this.state.showConfirmAppointAsAdmin ? (
<span
class="pointer"
onClick={linkEvent(
this,
this.handleShowConfirmAppointAsAdmin
)}
>
{this.isAdmin
? i18n.t('remove_as_admin')
: i18n.t('appoint_as_admin')}
</span>
) : (
<>
<span class="d-inline-block mr-1">
{i18n.t('are_you_sure')}
</span>
<span
class="pointer d-inline-block mr-1"
onClick={linkEvent(
this,
this.handleAddAdmin
)}
>
{i18n.t('yes')}
</span>
<span
class="pointer d-inline-block"
onClick={linkEvent(
this,
this.handleCancelConfirmAppointAsAdmin
)}
>
{i18n.t('no')}
</span>
</>
)}
</li>
)}
</> </>
)} )}
{/* Site Creator can transfer to another admin */} {/* Site Creator can transfer to another admin */}
{this.amSiteCreator && this.isAdmin && ( {this.amSiteCreator &&
<li className="list-inline-item"> this.isAdmin &&
{!this.state.showConfirmTransferSite ? ( (!this.state.showConfirmTransferSite ? (
<span <button
class="pointer" class="btn btn-link btn-animate text-muted"
onClick={linkEvent(
this,
this.handleShowConfirmTransferSite
)}
>
{i18n.t('transfer_site')}
</button>
) : (
<>
<button class="btn btn-link btn-animate text-muted">
{i18n.t('are_you_sure')}
</button>
<button
class="btn btn-link btn-animate text-muted"
onClick={linkEvent( onClick={linkEvent(
this, this,
this.handleShowConfirmTransferSite this.handleTransferSite
)} )}
> >
{i18n.t('transfer_site')} {i18n.t('yes')}
</span> </button>
) : ( <button
<> class="btn btn-link btn-animate text-muted"
<span class="d-inline-block mr-1"> onClick={linkEvent(
{i18n.t('are_you_sure')} this,
</span> this.handleCancelShowConfirmTransferSite
<span )}
class="pointer d-inline-block mr-1" >
onClick={linkEvent( {i18n.t('no')}
this, </button>
this.handleTransferSite </>
)} ))}
>
{i18n.t('yes')}
</span>
<span
class="pointer d-inline-block"
onClick={linkEvent(
this,
this.handleCancelShowConfirmTransferSite
)}
>
{i18n.t('no')}
</span>
</>
)}
</li>
)}
</> </>
)} )}
</> </>
)} )}
</ul> </div>
{/* end of button group */}
</div> </div>
)} )}
</div> </div>
@ -761,9 +707,9 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
get linkBtn() { get linkBtn() {
let node = this.props.node; let node = this.props.node;
return ( return (
<li className="list-inline-item"> <button className="btn btn-link btn-animate">
<Link <Link
className="btn btn-link btn-sm btn-animate text-muted" class="text-muted"
to={`/post/${node.comment.post_id}/comment/${node.comment.id}`} to={`/post/${node.comment.post_id}/comment/${node.comment.id}`}
title={ title={
this.props.showContext ? i18n.t('show_context') : i18n.t('link') this.props.showContext ? i18n.t('show_context') : i18n.t('link')
@ -773,7 +719,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
<use xlinkHref="#icon-link"></use> <use xlinkHref="#icon-link"></use>
</svg> </svg>
</Link> </Link>
</li> </button>
); );
} }