mirror of
https://github.com/wassname/talk.git
synced 2026-07-08 09:51:49 +08:00
Merge pull request #751 from coralproject/talk-plugin-avatar
Talk Plugin Avatar
This commit is contained in:
@@ -2,24 +2,23 @@
|
||||
margin-left: 20px;
|
||||
margin-bottom: 16px;
|
||||
position: relative;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.rootLevel0:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.root:first-child {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.rootLevel0 {
|
||||
margin-left: 0px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.comment {
|
||||
padding-left: 20px;
|
||||
padding-left: 15px;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
}
|
||||
|
||||
.commentLevel0 {
|
||||
@@ -43,7 +42,7 @@
|
||||
}
|
||||
|
||||
.highlightedComment {
|
||||
padding-left: 20px;
|
||||
padding-left: 15px;
|
||||
border-left: 3px solid rgb(35,118,216);
|
||||
}
|
||||
|
||||
@@ -158,6 +157,18 @@
|
||||
animation: enter 1000ms;
|
||||
}
|
||||
|
||||
.commentContainer {
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.commentAvatar {
|
||||
max-width: 60px;
|
||||
}
|
||||
|
||||
.commentAvatar:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.timerIcon {
|
||||
vertical-align: middle;
|
||||
font-size: 14px;
|
||||
|
||||
@@ -430,26 +430,10 @@ export default class Comment extends React.Component {
|
||||
id={`c_${comment.id}`}
|
||||
>
|
||||
<div className={commentClassName}>
|
||||
<AuthorName author={comment.user} className={'talk-stream-comment-user-name'} />
|
||||
{isStaff(comment.tags) ? <TagLabel>Staff</TagLabel> : null}
|
||||
|
||||
{commentIsBest(comment)
|
||||
? <TagLabel><BestIndicator /></TagLabel>
|
||||
: null }
|
||||
|
||||
<span className={`${styles.bylineSecondary} talk-stream-comment-user-byline`} >
|
||||
<PubDate created_at={comment.created_at} className={'talk-stream-comment-published-date'} />
|
||||
{
|
||||
(comment.editing && comment.editing.edited)
|
||||
? <span> <span className={styles.editedMarker}>({t('comment.edited')})</span></span>
|
||||
: null
|
||||
}
|
||||
</span>
|
||||
|
||||
<Slot
|
||||
className={styles.commentInfoBar}
|
||||
fill="commentInfoBar"
|
||||
depth={depth}
|
||||
className={styles.commentAvatar}
|
||||
fill="commentAvatar"
|
||||
comment={comment}
|
||||
commentId={comment.id}
|
||||
data={this.props.data}
|
||||
@@ -457,157 +441,189 @@ export default class Comment extends React.Component {
|
||||
inline
|
||||
/>
|
||||
|
||||
{ (currentUser && (comment.user.id === currentUser.id)) &&
|
||||
<div className={styles.commentContainer}>
|
||||
|
||||
<AuthorName author={comment.user} className={'talk-stream-comment-user-name'} />
|
||||
{isStaff(comment.tags) ? <TagLabel>Staff</TagLabel> : null}
|
||||
|
||||
/* User can edit/delete their own comment for a short window after posting */
|
||||
<span className={cn(styles.topRight)}>
|
||||
{commentIsBest(comment)
|
||||
? <TagLabel><BestIndicator /></TagLabel>
|
||||
: null }
|
||||
|
||||
<span className={`${styles.bylineSecondary} talk-stream-comment-user-byline`} >
|
||||
<PubDate created_at={comment.created_at} className={'talk-stream-comment-published-date'} />
|
||||
{
|
||||
commentIsStillEditable(comment) &&
|
||||
<a
|
||||
className={cn(styles.link, {[styles.active]: this.state.isEditing})}
|
||||
onClick={this.onClickEdit}>Edit</a>
|
||||
(comment.editing && comment.editing.edited)
|
||||
? <span> <span className={styles.editedMarker}>({t('comment.edited')})</span></span>
|
||||
: null
|
||||
}
|
||||
</span>
|
||||
}
|
||||
{ (currentUser && (comment.user.id !== currentUser.id)) &&
|
||||
|
||||
/* TopRightMenu allows currentUser to ignore other users' comments */
|
||||
<span className={cn(styles.topRight, styles.topRightMenu)}>
|
||||
<TopRightMenu
|
||||
comment={comment}
|
||||
ignoreUser={ignoreUser}
|
||||
addNotification={addNotification} />
|
||||
<Slot
|
||||
className={styles.commentInfoBar}
|
||||
fill="commentInfoBar"
|
||||
depth={depth}
|
||||
comment={comment}
|
||||
commentId={comment.id}
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
inline
|
||||
/>
|
||||
|
||||
{ (currentUser && (comment.user.id === currentUser.id)) &&
|
||||
|
||||
/* User can edit/delete their own comment for a short window after posting */
|
||||
<span className={cn(styles.topRight)}>
|
||||
{
|
||||
commentIsStillEditable(comment) &&
|
||||
<a
|
||||
className={cn(styles.link, {[styles.active]: this.state.isEditing})}
|
||||
onClick={this.onClickEdit}>Edit</a>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
{
|
||||
this.state.isEditing
|
||||
? <EditableCommentContent
|
||||
editComment={this.editComment}
|
||||
addNotification={addNotification}
|
||||
comment={comment}
|
||||
currentUser={currentUser}
|
||||
charCountEnable={charCountEnable}
|
||||
maxCharCount={maxCharCount}
|
||||
parentId={parentId}
|
||||
stopEditing={this.stopEditing}
|
||||
/>
|
||||
: <div>
|
||||
<Slot fill="commentContent" comment={comment} defaultComponent={CommentContent} />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
{ (currentUser && (comment.user.id !== currentUser.id)) &&
|
||||
|
||||
<div className="commentActionsLeft comment__action-container">
|
||||
<Slot
|
||||
fill="commentReactions"
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
comment={comment}
|
||||
commentId={comment.id}
|
||||
inline
|
||||
/>
|
||||
<ActionButton>
|
||||
<IfUserCanModifyBest user={currentUser}>
|
||||
<BestButton
|
||||
isBest={commentIsBest(comment)}
|
||||
addBest={addBestTag}
|
||||
removeBest={removeBestTag}
|
||||
/>
|
||||
</IfUserCanModifyBest>
|
||||
</ActionButton>
|
||||
{!disableReply &&
|
||||
<ActionButton>
|
||||
<ReplyButton
|
||||
onClick={this.showReplyBox}
|
||||
parentCommentId={parentId || comment.id}
|
||||
currentUserId={currentUser && currentUser.id}
|
||||
/>
|
||||
</ActionButton>}
|
||||
</div>
|
||||
<div className="commentActionsRight comment__action-container">
|
||||
<Slot
|
||||
fill="commentActions"
|
||||
wrapperComponent={ActionButton}
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
asset={asset}
|
||||
comment={comment}
|
||||
commentId={comment.id}
|
||||
inline
|
||||
/>
|
||||
<ActionButton>
|
||||
<FlagComment
|
||||
flaggedByCurrentUser={!!myFlag}
|
||||
flag={myFlag}
|
||||
id={comment.id}
|
||||
author_id={comment.user.id}
|
||||
postFlag={postFlag}
|
||||
addNotification={addNotification}
|
||||
postDontAgree={postDontAgree}
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
currentUser={currentUser}
|
||||
/>
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
{activeReplyBox === comment.id
|
||||
? <ReplyBox
|
||||
commentPostedHandler={() => {
|
||||
setActiveReplyBox('');
|
||||
}}
|
||||
charCountEnable={charCountEnable}
|
||||
maxCharCount={maxCharCount}
|
||||
setActiveReplyBox={setActiveReplyBox}
|
||||
parentId={(depth < THREADING_LEVEL) ? comment.id : parentId}
|
||||
addNotification={addNotification}
|
||||
postComment={postComment}
|
||||
currentUser={currentUser}
|
||||
assetId={asset.id}
|
||||
/>
|
||||
: null}
|
||||
/* TopRightMenu allows currentUser to ignore other users' comments */
|
||||
<span className={cn(styles.topRight, styles.topRightMenu)}>
|
||||
<TopRightMenu
|
||||
comment={comment}
|
||||
ignoreUser={ignoreUser}
|
||||
addNotification={addNotification} />
|
||||
</span>
|
||||
}
|
||||
{
|
||||
this.state.isEditing
|
||||
? <EditableCommentContent
|
||||
editComment={this.editComment}
|
||||
addNotification={addNotification}
|
||||
comment={comment}
|
||||
currentUser={currentUser}
|
||||
charCountEnable={charCountEnable}
|
||||
maxCharCount={maxCharCount}
|
||||
parentId={parentId}
|
||||
stopEditing={this.stopEditing}
|
||||
/>
|
||||
: <div>
|
||||
<Slot fill="commentContent" comment={comment} defaultComponent={CommentContent} />
|
||||
</div>
|
||||
}
|
||||
|
||||
<TransitionGroup>
|
||||
{view.map((reply) => {
|
||||
return commentIsIgnored(reply)
|
||||
? <IgnoredCommentTombstone key={reply.id} />
|
||||
: <Comment
|
||||
<div className="commentActionsLeft comment__action-container">
|
||||
<Slot
|
||||
fill="commentReactions"
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
comment={comment}
|
||||
commentId={comment.id}
|
||||
inline
|
||||
/>
|
||||
<ActionButton>
|
||||
<IfUserCanModifyBest user={currentUser}>
|
||||
<BestButton
|
||||
isBest={commentIsBest(comment)}
|
||||
addBest={addBestTag}
|
||||
removeBest={removeBestTag}
|
||||
/>
|
||||
</IfUserCanModifyBest>
|
||||
</ActionButton>
|
||||
{!disableReply &&
|
||||
<ActionButton>
|
||||
<ReplyButton
|
||||
onClick={this.showReplyBox}
|
||||
parentCommentId={parentId || comment.id}
|
||||
currentUserId={currentUser && currentUser.id}
|
||||
/>
|
||||
</ActionButton>}
|
||||
</div>
|
||||
<div className="commentActionsRight comment__action-container">
|
||||
<Slot
|
||||
fill="commentActions"
|
||||
wrapperComponent={ActionButton}
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
setActiveReplyBox={setActiveReplyBox}
|
||||
disableReply={disableReply}
|
||||
activeReplyBox={activeReplyBox}
|
||||
addNotification={addNotification}
|
||||
parentId={comment.id}
|
||||
postComment={postComment}
|
||||
editComment={this.props.editComment}
|
||||
depth={depth + 1}
|
||||
asset={asset}
|
||||
highlighted={highlighted}
|
||||
currentUser={currentUser}
|
||||
postFlag={postFlag}
|
||||
deleteAction={deleteAction}
|
||||
addTag={addTag}
|
||||
removeTag={removeTag}
|
||||
loadMore={loadMore}
|
||||
ignoreUser={ignoreUser}
|
||||
comment={comment}
|
||||
commentId={comment.id}
|
||||
inline
|
||||
/>
|
||||
<ActionButton>
|
||||
<FlagComment
|
||||
flaggedByCurrentUser={!!myFlag}
|
||||
flag={myFlag}
|
||||
id={comment.id}
|
||||
author_id={comment.user.id}
|
||||
postFlag={postFlag}
|
||||
addNotification={addNotification}
|
||||
postDontAgree={postDontAgree}
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
currentUser={currentUser}
|
||||
/>
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{activeReplyBox === comment.id
|
||||
? <ReplyBox
|
||||
commentPostedHandler={() => {
|
||||
setActiveReplyBox('');
|
||||
}}
|
||||
charCountEnable={charCountEnable}
|
||||
maxCharCount={maxCharCount}
|
||||
showSignInDialog={showSignInDialog}
|
||||
commentIsIgnored={commentIsIgnored}
|
||||
liveUpdates={liveUpdates}
|
||||
key={reply.id}
|
||||
comment={reply}
|
||||
/>;
|
||||
})}
|
||||
</TransitionGroup>
|
||||
<div className="talk-load-more-replies">
|
||||
<LoadMore
|
||||
topLevel={false}
|
||||
replyCount={moreRepliesCount}
|
||||
moreComments={hasMoreComments}
|
||||
loadMore={this.loadNewReplies}
|
||||
loadingState={loadingState}
|
||||
/>
|
||||
setActiveReplyBox={setActiveReplyBox}
|
||||
parentId={(depth < THREADING_LEVEL) ? comment.id : parentId}
|
||||
addNotification={addNotification}
|
||||
postComment={postComment}
|
||||
currentUser={currentUser}
|
||||
assetId={asset.id}
|
||||
/>
|
||||
: null}
|
||||
|
||||
<TransitionGroup>
|
||||
{view.map((reply) => {
|
||||
return commentIsIgnored(reply)
|
||||
? <IgnoredCommentTombstone key={reply.id} />
|
||||
: <Comment
|
||||
data={this.props.data}
|
||||
root={this.props.root}
|
||||
setActiveReplyBox={setActiveReplyBox}
|
||||
disableReply={disableReply}
|
||||
activeReplyBox={activeReplyBox}
|
||||
addNotification={addNotification}
|
||||
parentId={comment.id}
|
||||
postComment={postComment}
|
||||
editComment={this.props.editComment}
|
||||
depth={depth + 1}
|
||||
asset={asset}
|
||||
highlighted={highlighted}
|
||||
currentUser={currentUser}
|
||||
postFlag={postFlag}
|
||||
deleteAction={deleteAction}
|
||||
addTag={addTag}
|
||||
removeTag={removeTag}
|
||||
loadMore={loadMore}
|
||||
ignoreUser={ignoreUser}
|
||||
charCountEnable={charCountEnable}
|
||||
maxCharCount={maxCharCount}
|
||||
showSignInDialog={showSignInDialog}
|
||||
commentIsIgnored={commentIsIgnored}
|
||||
liveUpdates={liveUpdates}
|
||||
reactKey={reply.id}
|
||||
key={reply.id}
|
||||
comment={reply}
|
||||
/>;
|
||||
})}
|
||||
</TransitionGroup>
|
||||
<div className="talk-load-more-replies">
|
||||
<LoadMore
|
||||
topLevel={false}
|
||||
replyCount={moreRepliesCount}
|
||||
moreComments={hasMoreComments}
|
||||
loadMore={this.loadNewReplies}
|
||||
loadingState={loadingState}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -10,7 +10,8 @@ const pluginFragments = getSlotsFragments([
|
||||
'commentInfoBar',
|
||||
'commentActions',
|
||||
'commentContent',
|
||||
'commentReactions'
|
||||
'commentReactions',
|
||||
'commentAvatar'
|
||||
]);
|
||||
|
||||
export default withFragments({
|
||||
|
||||
@@ -16,10 +16,10 @@ export function getSlotComponents(slot) {
|
||||
return flatten(plugins
|
||||
|
||||
// Filter out components that have slots and have been disabled in `plugin_config`
|
||||
.filter((o) => o.module.slots && (!pluginConfig || !pluginConfig[o.name] || !pluginConfig[o.name].disable_components))
|
||||
.filter((o) => o.module.slots && (!pluginConfig || !pluginConfig[o.name] || !pluginConfig[o.name].disable_components))
|
||||
|
||||
.filter((o) => o.module.slots[slot])
|
||||
.map((o) => o.module.slots[slot])
|
||||
.filter((o) => o.module.slots[slot])
|
||||
.map((o) => o.module.slots[slot])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -78,8 +78,8 @@ export function getSlotsFragments(slots) {
|
||||
}
|
||||
const components = uniq(flattenDeep(slots.map((slot) => {
|
||||
return plugins
|
||||
.filter((o) => o.module.slots ? o.module.slots[slot] : false)
|
||||
.map((o) => o.module.slots[slot]);
|
||||
.filter((o) => o.module.slots ? o.module.slots[slot] : false)
|
||||
.map((o) => o.module.slots[slot]);
|
||||
})));
|
||||
|
||||
const fragments = getComponentFragments(components);
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
"env-rewrite": "^1.0.2",
|
||||
"express": "^4.15.2",
|
||||
"express-session": "^1.15.1",
|
||||
"file-loader": "^0.11.2",
|
||||
"form-data": "^2.1.2",
|
||||
"fs-extra": "^3.0.1",
|
||||
"gql-merge": "^0.0.4",
|
||||
@@ -209,6 +210,7 @@
|
||||
"style-loader": "^0.16.0",
|
||||
"supertest": "^2.0.1",
|
||||
"timeago.js": "^2.0.3",
|
||||
"url-loader": "^0.5.9",
|
||||
"webpack": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export {default as withReaction} from './withReaction';
|
||||
export {default as withFragments} from 'coral-framework/hocs/withFragments';
|
||||
|
||||
@@ -70,10 +70,6 @@ const config = {
|
||||
],
|
||||
test: /.css$/,
|
||||
},
|
||||
{
|
||||
loader: 'url-loader?limit=100000',
|
||||
test: /\.png$/
|
||||
},
|
||||
{
|
||||
loader: 'file-loader',
|
||||
test: /\.(jpg|png|gif|svg)$/
|
||||
|
||||
@@ -3119,6 +3119,12 @@ file-entry-cache@^2.0.0:
|
||||
flat-cache "^1.2.1"
|
||||
object-assign "^4.0.1"
|
||||
|
||||
file-loader@^0.11.2:
|
||||
version "0.11.2"
|
||||
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-0.11.2.tgz#4ff1df28af38719a6098093b88c82c71d1794a34"
|
||||
dependencies:
|
||||
loader-utils "^1.0.2"
|
||||
|
||||
file-uri-to-path@0:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-0.0.2.tgz#37cdd1b5b905404b3f05e1b23645be694ff70f82"
|
||||
@@ -5245,7 +5251,7 @@ mime-types@~2.0.3:
|
||||
dependencies:
|
||||
mime-db "~1.12.0"
|
||||
|
||||
mime@1.3.4, mime@^1.3.4:
|
||||
mime@1.3.4, mime@1.3.x, mime@^1.3.4:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
|
||||
|
||||
@@ -8305,6 +8311,13 @@ urijs@1.16.1:
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.16.1.tgz#859ad31890f5f9528727be89f1932c94fb4731e2"
|
||||
|
||||
url-loader@^0.5.9:
|
||||
version "0.5.9"
|
||||
resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-0.5.9.tgz#cc8fea82c7b906e7777019250869e569e995c295"
|
||||
dependencies:
|
||||
loader-utils "^1.0.2"
|
||||
mime "1.3.x"
|
||||
|
||||
url-search-params@^0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/url-search-params/-/url-search-params-0.9.0.tgz#e71d7764a6503533cbfe9771b2963cb61ea1c225"
|
||||
|
||||
Reference in New Issue
Block a user