diff options
-rw-r--r-- | webapp/actions/user_actions.jsx | 10 | ||||
-rw-r--r-- | webapp/components/post_view/components/post_body.jsx | 5 | ||||
-rw-r--r-- | webapp/components/post_view/components/reaction.jsx | 38 | ||||
-rw-r--r-- | webapp/components/post_view/components/reaction_container.jsx | 88 | ||||
-rw-r--r-- | webapp/components/post_view/components/reaction_list_container.jsx | 4 | ||||
-rw-r--r-- | webapp/components/post_view/components/reaction_list_view.jsx | 4 | ||||
-rw-r--r-- | webapp/components/rhs_comment.jsx | 5 | ||||
-rw-r--r-- | webapp/components/rhs_root_post.jsx | 5 |
8 files changed, 122 insertions, 37 deletions
diff --git a/webapp/actions/user_actions.jsx b/webapp/actions/user_actions.jsx index 231b09f11..3b1fa96a8 100644 --- a/webapp/actions/user_actions.jsx +++ b/webapp/actions/user_actions.jsx @@ -882,3 +882,13 @@ export function loadProfiles(offset = UserStore.getPagingOffset(), limit = Const } ); } + +export function getMissingProfiles(ids, success, error) { + const missingIds = ids.filter((id) => !UserStore.hasProfile(id)); + + if (missingIds.length === 0) { + return; + } + + AsyncClient.getProfilesByIds(missingIds, success, error); +} diff --git a/webapp/components/post_view/components/post_body.jsx b/webapp/components/post_view/components/post_body.jsx index eb1159987..741722ceb 100644 --- a/webapp/components/post_view/components/post_body.jsx +++ b/webapp/components/post_view/components/post_body.jsx @@ -196,10 +196,7 @@ export default class PostBody extends React.Component { <div className={'post__body ' + mentionHighlightClass}> {messageWithAdditionalContent} {fileAttachmentHolder} - <ReactionListContainer - post={post} - currentUserId={this.props.currentUser.id} - /> + <ReactionListContainer post={post}/> </div> </div> ); diff --git a/webapp/components/post_view/components/reaction.jsx b/webapp/components/post_view/components/reaction.jsx index 92ec675b6..ae658da1f 100644 --- a/webapp/components/post_view/components/reaction.jsx +++ b/webapp/components/post_view/components/reaction.jsx @@ -2,13 +2,12 @@ // See License.txt for license information. import React from 'react'; +import {OverlayTrigger, Tooltip} from 'react-bootstrap'; +import {FormattedMessage} from 'react-intl'; import EmojiStore from 'stores/emoji_store.jsx'; -import * as PostActions from 'actions/post_actions.jsx'; -import * as Utils from 'utils/utils.jsx'; -import {FormattedMessage} from 'react-intl'; -import {OverlayTrigger, Tooltip} from 'react-bootstrap'; +import * as Utils from 'utils/utils.jsx'; export default class Reaction extends React.Component { static propTypes = { @@ -16,7 +15,14 @@ export default class Reaction extends React.Component { currentUserId: React.PropTypes.string.isRequired, emojiName: React.PropTypes.string.isRequired, reactions: React.PropTypes.arrayOf(React.PropTypes.object), - emojis: React.PropTypes.object.isRequired + emojis: React.PropTypes.object.isRequired, + profiles: React.PropTypes.array.isRequired, + otherUsers: React.PropTypes.number.isRequired, + actions: React.PropTypes.shape({ + addReaction: React.PropTypes.func.isRequired, + getMissingProfiles: React.PropTypes.func.isRequired, + removeReaction: React.PropTypes.func.isRequired + }) } constructor(props) { @@ -28,12 +34,12 @@ export default class Reaction extends React.Component { addReaction(e) { e.preventDefault(); - PostActions.addReaction(this.props.post.channel_id, this.props.post.id, this.props.emojiName); + this.props.actions.addReaction(this.props.post.channel_id, this.props.post.id, this.props.emojiName); } removeReaction(e) { e.preventDefault(); - PostActions.removeReaction(this.props.post.channel_id, this.props.post.id, this.props.emojiName); + this.props.actions.removeReaction(this.props.post.channel_id, this.props.post.id, this.props.emojiName); } render() { @@ -43,23 +49,16 @@ export default class Reaction extends React.Component { let currentUserReacted = false; const users = []; - let otherUsers = 0; - for (const reaction of this.props.reactions) { - if (reaction.user_id === this.props.currentUserId) { + const otherUsers = this.props.otherUsers; + for (const user of this.props.profiles) { + if (user.id === this.props.currentUserId) { currentUserReacted = true; } else { - const displayName = Utils.displayUsername(reaction.user_id); - - if (displayName) { - users.push(displayName); - } else { - // Just count users that we don't have loaded - otherUsers += 1; - } + users.push(Utils.displayUsernameForUser(user)); } } - // sort users in alphabetical order with "you" being first if the current user reacted + // Sort users in alphabetical order with "you" being first if the current user reacted users.sort(); if (currentUserReacted) { users.unshift(Utils.localizeMessage('reaction.you', 'You')); @@ -184,6 +183,7 @@ export default class Reaction extends React.Component { {clickTooltip} </Tooltip> } + onEnter={this.props.actions.getMissingProfiles} > <div className={className} diff --git a/webapp/components/post_view/components/reaction_container.jsx b/webapp/components/post_view/components/reaction_container.jsx new file mode 100644 index 000000000..09e6ce5ea --- /dev/null +++ b/webapp/components/post_view/components/reaction_container.jsx @@ -0,0 +1,88 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React from 'react'; + +import {addReaction, removeReaction} from 'actions/post_actions.jsx'; +import * as UserActions from 'actions/user_actions.jsx'; + +import UserStore from 'stores/user_store.jsx'; + +import Reaction from './reaction.jsx'; + +export default class ReactionContainer extends React.Component { + static propTypes = { + post: React.PropTypes.object.isRequired, + emojiName: React.PropTypes.string.isRequired, + reactions: React.PropTypes.arrayOf(React.PropTypes.object), + emojis: React.PropTypes.object.isRequired + } + + constructor(props) { + super(props); + + this.handleUsersChanged = this.handleUsersChanged.bind(this); + + this.getStateFromStore = this.getStateFromStore.bind(this); + + this.getProfilesForReactions = this.getProfilesForReactions.bind(this); + this.getMissingProfiles = this.getMissingProfiles.bind(this); + + this.state = this.getStateFromStore(props); + } + + componentDidMount() { + UserStore.addChangeListener(this.handleUsersChanged); + } + + componentWillReceiveProps(nextProps) { + if (nextProps.reactions !== this.props.reactions) { + this.setState(this.getStateFromStore(nextProps)); + } + } + + componentWillUnmount() { + UserStore.removeChangeListener(this.handleUsersChanged); + } + + handleUsersChanged() { + this.setState(this.getStateFromStore()); + } + + getStateFromStore(props = this.props) { + const profiles = this.getProfilesForReactions(props.reactions); + const otherUsers = props.reactions.length - profiles.length; + + return { + profiles, + otherUsers, + currentUserId: UserStore.getCurrentId() + }; + } + + getProfilesForReactions(reactions) { + return reactions.map((reaction) => { + return UserStore.getProfile(reaction.user_id); + }).filter((profile) => Boolean(profile)); + } + + getMissingProfiles() { + const ids = this.props.reactions.map((reaction) => reaction.user_id); + + UserActions.getMissingProfiles(ids); + } + + render() { + return ( + <Reaction + {...this.props} + {...this.state} + actions={{ + addReaction, + getMissingProfiles: this.getMissingProfiles, + removeReaction + }} + /> + ); + } +} diff --git a/webapp/components/post_view/components/reaction_list_container.jsx b/webapp/components/post_view/components/reaction_list_container.jsx index 3ee8f73a3..906145eed 100644 --- a/webapp/components/post_view/components/reaction_list_container.jsx +++ b/webapp/components/post_view/components/reaction_list_container.jsx @@ -11,8 +11,7 @@ import ReactionListView from './reaction_list_view.jsx'; export default class ReactionListContainer extends React.Component { static propTypes = { - post: React.PropTypes.object.isRequired, - currentUserId: React.PropTypes.string.isRequired + post: React.PropTypes.object.isRequired } constructor(props) { @@ -86,7 +85,6 @@ export default class ReactionListContainer extends React.Component { return ( <ReactionListView post={this.props.post} - currentUserId={this.props.currentUserId} reactions={this.state.reactions} emojis={this.state.emojis} /> diff --git a/webapp/components/post_view/components/reaction_list_view.jsx b/webapp/components/post_view/components/reaction_list_view.jsx index aaa896c9a..c322ce727 100644 --- a/webapp/components/post_view/components/reaction_list_view.jsx +++ b/webapp/components/post_view/components/reaction_list_view.jsx @@ -3,12 +3,11 @@ import React from 'react'; -import Reaction from './reaction.jsx'; +import Reaction from './reaction_container.jsx'; export default class ReactionListView extends React.Component { static propTypes = { post: React.PropTypes.object.isRequired, - currentUserId: React.PropTypes.string.isRequired, reactions: React.PropTypes.arrayOf(React.PropTypes.object), emojis: React.PropTypes.object.isRequired } @@ -33,7 +32,6 @@ export default class ReactionListView extends React.Component { <Reaction key={emojiName} post={this.props.post} - currentUserId={this.props.currentUserId} emojiName={emojiName} reactions={reactionsByName.get(emojiName)} emojis={this.props.emojis} diff --git a/webapp/components/rhs_comment.jsx b/webapp/components/rhs_comment.jsx index 52e4d9851..278163bf7 100644 --- a/webapp/components/rhs_comment.jsx +++ b/webapp/components/rhs_comment.jsx @@ -592,10 +592,7 @@ export default class RhsComment extends React.Component { <PostMessageContainer post={post}/> </div> {fileAttachment} - <ReactionListContainer - post={post} - currentUserId={this.props.currentUser.id} - /> + <ReactionListContainer post={post}/> </div> </div> </div> diff --git a/webapp/components/rhs_root_post.jsx b/webapp/components/rhs_root_post.jsx index 231033fb1..f07826d63 100644 --- a/webapp/components/rhs_root_post.jsx +++ b/webapp/components/rhs_root_post.jsx @@ -559,10 +559,7 @@ export default class RhsRootPost extends React.Component { /> </div> {fileAttachment} - <ReactionListContainer - post={post} - currentUserId={this.props.currentUser.id} - /> + <ReactionListContainer post={post}/> </div> </div> </div> |