PLT-5035 Added loading of missing profiles when hovering over reactions (#5887)

Этот коммит содержится в:
Harrison Healey
2017-03-30 09:49:22 -04:00
коммит произвёл GitHub
родитель c06a23ea0b
Коммит ee3b983a63
8 изменённых файлов: 122 добавлений и 37 удалений

Просмотреть файл

@@ -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);
}

Просмотреть файл

@@ -196,10 +196,7 @@ export default class PostBody extends React.Component {
<div className={'post__body ' + mentionHighlightClass}> <div className={'post__body ' + mentionHighlightClass}>
{messageWithAdditionalContent} {messageWithAdditionalContent}
{fileAttachmentHolder} {fileAttachmentHolder}
<ReactionListContainer <ReactionListContainer post={post}/>
post={post}
currentUserId={this.props.currentUser.id}
/>
</div> </div>
</div> </div>
); );

Просмотреть файл

@@ -2,13 +2,12 @@
// See License.txt for license information. // See License.txt for license information.
import React from 'react'; import React from 'react';
import {OverlayTrigger, Tooltip} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import EmojiStore from 'stores/emoji_store.jsx'; 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 * as Utils from 'utils/utils.jsx';
import {OverlayTrigger, Tooltip} from 'react-bootstrap';
export default class Reaction extends React.Component { export default class Reaction extends React.Component {
static propTypes = { static propTypes = {
@@ -16,7 +15,14 @@ export default class Reaction extends React.Component {
currentUserId: React.PropTypes.string.isRequired, currentUserId: React.PropTypes.string.isRequired,
emojiName: React.PropTypes.string.isRequired, emojiName: React.PropTypes.string.isRequired,
reactions: React.PropTypes.arrayOf(React.PropTypes.object), 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) { constructor(props) {
@@ -28,12 +34,12 @@ export default class Reaction extends React.Component {
addReaction(e) { addReaction(e) {
e.preventDefault(); 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) { removeReaction(e) {
e.preventDefault(); 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() { render() {
@@ -43,23 +49,16 @@ export default class Reaction extends React.Component {
let currentUserReacted = false; let currentUserReacted = false;
const users = []; const users = [];
let otherUsers = 0; const otherUsers = this.props.otherUsers;
for (const reaction of this.props.reactions) { for (const user of this.props.profiles) {
if (reaction.user_id === this.props.currentUserId) { if (user.id === this.props.currentUserId) {
currentUserReacted = true; currentUserReacted = true;
} else { } else {
const displayName = Utils.displayUsername(reaction.user_id); users.push(Utils.displayUsernameForUser(user));
if (displayName) {
users.push(displayName);
} else {
// Just count users that we don't have loaded
otherUsers += 1;
}
} }
} }
// 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(); users.sort();
if (currentUserReacted) { if (currentUserReacted) {
users.unshift(Utils.localizeMessage('reaction.you', 'You')); users.unshift(Utils.localizeMessage('reaction.you', 'You'));
@@ -184,6 +183,7 @@ export default class Reaction extends React.Component {
{clickTooltip} {clickTooltip}
</Tooltip> </Tooltip>
} }
onEnter={this.props.actions.getMissingProfiles}
> >
<div <div
className={className} className={className}

Просмотреть файл

@@ -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
}}
/>
);
}
}

Просмотреть файл

@@ -11,8 +11,7 @@ import ReactionListView from './reaction_list_view.jsx';
export default class ReactionListContainer extends React.Component { export default class ReactionListContainer extends React.Component {
static propTypes = { static propTypes = {
post: React.PropTypes.object.isRequired, post: React.PropTypes.object.isRequired
currentUserId: React.PropTypes.string.isRequired
} }
constructor(props) { constructor(props) {
@@ -86,7 +85,6 @@ export default class ReactionListContainer extends React.Component {
return ( return (
<ReactionListView <ReactionListView
post={this.props.post} post={this.props.post}
currentUserId={this.props.currentUserId}
reactions={this.state.reactions} reactions={this.state.reactions}
emojis={this.state.emojis} emojis={this.state.emojis}
/> />

Просмотреть файл

@@ -3,12 +3,11 @@
import React from 'react'; import React from 'react';
import Reaction from './reaction.jsx'; import Reaction from './reaction_container.jsx';
export default class ReactionListView extends React.Component { export default class ReactionListView extends React.Component {
static propTypes = { static propTypes = {
post: React.PropTypes.object.isRequired, post: React.PropTypes.object.isRequired,
currentUserId: React.PropTypes.string.isRequired,
reactions: React.PropTypes.arrayOf(React.PropTypes.object), reactions: React.PropTypes.arrayOf(React.PropTypes.object),
emojis: React.PropTypes.object.isRequired emojis: React.PropTypes.object.isRequired
} }
@@ -33,7 +32,6 @@ export default class ReactionListView extends React.Component {
<Reaction <Reaction
key={emojiName} key={emojiName}
post={this.props.post} post={this.props.post}
currentUserId={this.props.currentUserId}
emojiName={emojiName} emojiName={emojiName}
reactions={reactionsByName.get(emojiName)} reactions={reactionsByName.get(emojiName)}
emojis={this.props.emojis} emojis={this.props.emojis}

Просмотреть файл

@@ -592,10 +592,7 @@ export default class RhsComment extends React.Component {
<PostMessageContainer post={post}/> <PostMessageContainer post={post}/>
</div> </div>
{fileAttachment} {fileAttachment}
<ReactionListContainer <ReactionListContainer post={post}/>
post={post}
currentUserId={this.props.currentUser.id}
/>
</div> </div>
</div> </div>
</div> </div>

Просмотреть файл

@@ -559,10 +559,7 @@ export default class RhsRootPost extends React.Component {
/> />
</div> </div>
{fileAttachment} {fileAttachment}
<ReactionListContainer <ReactionListContainer post={post}/>
post={post}
currentUserId={this.props.currentUser.id}
/>
</div> </div>
</div> </div>
</div> </div>