Skip to content

Commit

Permalink
PLT-5035 Added loading of missing profiles when hovering over reactions
Browse files Browse the repository at this point in the history
  • Loading branch information
hmhealey committed Mar 28, 2017
1 parent 060b9f9 commit c4c51a5
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 37 deletions.
10 changes: 10 additions & 0 deletions webapp/actions/user_actions.jsx
Expand Up @@ -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);
}
5 changes: 1 addition & 4 deletions webapp/components/post_view/components/post_body.jsx
Expand Up @@ -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>
);
Expand Down
38 changes: 19 additions & 19 deletions webapp/components/post_view/components/reaction.jsx
Expand Up @@ -2,21 +2,27 @@
// 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 = {
post: React.PropTypes.object.isRequired,
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) {
Expand All @@ -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() {
Expand All @@ -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'));
Expand Down Expand Up @@ -184,6 +183,7 @@ export default class Reaction extends React.Component {
{clickTooltip}
</Tooltip>
}
onEnter={this.props.actions.getMissingProfiles}
>
<div
className={className}
Expand Down
88 changes: 88 additions & 0 deletions 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
}}
/>
);
}
}
Expand Up @@ -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) {
Expand Down Expand Up @@ -89,7 +88,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}
/>
Expand Down
Expand Up @@ -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
}
Expand All @@ -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}
Expand Down
5 changes: 1 addition & 4 deletions webapp/components/rhs_comment.jsx
Expand Up @@ -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>
Expand Down
5 changes: 1 addition & 4 deletions webapp/components/rhs_root_post.jsx
Expand Up @@ -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>
Expand Down

0 comments on commit c4c51a5

Please sign in to comment.