Files
mostlymatter/webapp/components/rhs_root_post.jsx
George Goldberg a857cf18f4 PLT-4860 Make ProfilePopover into it's own component and use it consistently everywhere (#4701)
* PLT-4860 - Use same User Popover everywhere.

Refactor out the ProfilePopover into it's own component and give it the
union of all the features of the previous two implementations, and make
sure all the necessary data for it to work consistently everywhere is
provided through the props wherever it is used.

* Don't show popover for webhook posts in main view.

* No popover on RHS when it's a webhook post.

* Fix style.

* Don't send in user when it's a system message.

* Fix some duplication of code.
2016-12-22 14:19:19 -03:00

467 строки
15 KiB
JavaScript

// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserProfile from './user_profile.jsx';
import PostBodyAdditionalContent from 'components/post_view/components/post_body_additional_content.jsx';
import PostMessageContainer from 'components/post_view/components/post_message_container.jsx';
import FileAttachmentListContainer from './file_attachment_list_container.jsx';
import ProfilePicture from 'components/profile_picture.jsx';
import ReactionListContainer from 'components/post_view/components/reaction_list_container.jsx';
import RhsDropdown from 'components/rhs_dropdown.jsx';
import ChannelStore from 'stores/channel_store.jsx';
import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
import {flagPost, unflagPost} from 'actions/post_actions.jsx';
import * as Utils from 'utils/utils.jsx';
import * as PostUtils from 'utils/post_utils.jsx';
import Constants from 'utils/constants.jsx';
import {Tooltip, OverlayTrigger} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import React from 'react';
export default class RhsRootPost extends React.Component {
constructor(props) {
super(props);
this.handlePermalink = this.handlePermalink.bind(this);
this.flagPost = this.flagPost.bind(this);
this.unflagPost = this.unflagPost.bind(this);
this.state = {};
}
handlePermalink(e) {
e.preventDefault();
GlobalActions.showGetPostLinkModal(this.props.post);
}
shouldComponentUpdate(nextProps) {
if (nextProps.status !== this.props.status) {
return true;
}
if (nextProps.isBusy !== this.props.isBusy) {
return true;
}
if (nextProps.compactDisplay !== this.props.compactDisplay) {
return true;
}
if (nextProps.useMilitaryTime !== this.props.useMilitaryTime) {
return true;
}
if (nextProps.isFlagged !== this.props.isFlagged) {
return true;
}
if (nextProps.previewCollapsed !== this.props.previewCollapsed) {
return true;
}
if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) {
return true;
}
if (!Utils.areObjectsEqual(nextProps.user, this.props.user)) {
return true;
}
if (!Utils.areObjectsEqual(nextProps.currentUser, this.props.currentUser)) {
return true;
}
return false;
}
flagPost(e) {
e.preventDefault();
flagPost(this.props.post.id);
}
unflagPost(e) {
e.preventDefault();
unflagPost(this.props.post.id);
}
render() {
const post = this.props.post;
const user = this.props.user;
const mattermostLogo = Constants.MATTERMOST_ICON_SVG;
var isOwner = this.props.currentUser.id === post.user_id;
var isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
const isSystemMessage = post.type && post.type.startsWith(Constants.SYSTEM_MESSAGE_PREFIX);
var timestamp = user ? user.update_at : 0;
var channel = ChannelStore.get(post.channel_id);
const flagIcon = Constants.FLAG_ICON_SVG;
var type = 'Post';
if (post.root_id.length > 0) {
type = 'Comment';
}
var userCss = '';
if (UserStore.getCurrentId() === post.user_id) {
userCss = 'current--user';
}
var systemMessageClass = '';
if (PostUtils.isSystemMessage(post)) {
systemMessageClass = 'post--system';
}
var channelName;
if (channel) {
if (channel.type === 'D') {
channelName = (
<FormattedMessage
id='rhs_root.direct'
defaultMessage='Direct Message'
/>
);
} else {
channelName = channel.display_name;
}
}
var dropdownContents = [];
if (Utils.isMobile()) {
if (this.props.isFlagged) {
dropdownContents.push(
<li
key='mobileFlag'
role='presentation'
>
<a
href='#'
onClick={this.unflagPost}
>
<FormattedMessage
id='rhs_root.mobile.unflag'
defaultMessage='Unflag'
/>
</a>
</li>
);
} else {
dropdownContents.push(
<li
key='mobileFlag'
role='presentation'
>
<a
href='#'
onClick={this.flagPost}
>
<FormattedMessage
id='rhs_root.mobile.flag'
defaultMessage='Flag'
/>
</a>
</li>
);
}
}
dropdownContents.push(
<li
key='rhs-root-permalink'
role='presentation'
>
<a
href='#'
onClick={this.handlePermalink}
>
<FormattedMessage
id='rhs_root.permalink'
defaultMessage='Permalink'
/>
</a>
</li>
);
if (isOwner || isAdmin) {
dropdownContents.push(
<li
key='rhs-root-delete'
role='presentation'
>
<a
href='#'
role='menuitem'
onClick={() => GlobalActions.showDeletePostModal(post, this.props.commentCount)}
>
<FormattedMessage
id='rhs_root.del'
defaultMessage='Delete'
/>
</a>
</li>
);
}
if (isOwner && !isSystemMessage) {
dropdownContents.push(
<li
key='rhs-root-edit'
role='presentation'
>
<a
href='#'
role='menuitem'
data-toggle='modal'
data-target='#edit_post'
data-refocusid='#reply_textbox'
data-title={type}
data-message={post.message}
data-postid={post.id}
data-channelid={post.channel_id}
>
<FormattedMessage
id='rhs_root.edit'
defaultMessage='Edit'
/>
</a>
</li>
);
}
var rootOptions = '';
if (dropdownContents.length > 0) {
rootOptions = (
<RhsDropdown dropdownContents={dropdownContents}/>
);
}
let fileAttachment = null;
if (post.file_ids && post.file_ids.length > 0) {
fileAttachment = (
<FileAttachmentListContainer
post={post}
compactDisplay={this.props.compactDisplay}
/>
);
}
let userProfile = (
<UserProfile
user={user}
status={this.props.status}
isBusy={this.props.isBusy}
/>
);
let botIndicator;
if (post.props && post.props.from_webhook) {
if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') {
userProfile = (
<UserProfile
user={user}
overwriteName={post.props.override_username}
disablePopover={true}
/>
);
} else {
userProfile = (
<UserProfile
user={user}
disablePopover={true}
/>
);
}
botIndicator = <li className='col col__name bot-indicator'>{'BOT'}</li>;
} else if (PostUtils.isSystemMessage(post)) {
userProfile = (
<UserProfile
user={{}}
overwriteName={Constants.SYSTEM_MESSAGE_PROFILE_NAME}
overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE}
disablePopover={true}
/>
);
}
let status = this.props.status;
if (post.props && post.props.from_webhook === 'true') {
status = null;
}
let profilePic = (
<ProfilePicture
src={PostUtils.getProfilePicSrcForPost(post, timestamp)}
status={status}
width='36'
height='36'
user={this.props.user}
isBusy={this.props.isBusy}
/>
);
if (post.props && post.props.from_webhook) {
profilePic = (
<ProfilePicture
src={PostUtils.getProfilePicSrcForPost(post, timestamp)}
width='36'
height='36'
/>
);
}
if (PostUtils.isSystemMessage(post)) {
profilePic = (
<span
className='icon'
dangerouslySetInnerHTML={{__html: mattermostLogo}}
/>
);
}
let compactClass = '';
if (this.props.compactDisplay) {
compactClass = 'post--compact';
if (post.props && post.props.from_webhook) {
profilePic = (
<ProfilePicture
src=''
/>
);
} else {
profilePic = (
<ProfilePicture
src=''
status={status}
user={this.props.user}
isBusy={this.props.isBusy}
/>
);
}
}
const profilePicContainer = (<div className='post__img'>{profilePic}</div>);
const messageWrapper = <PostMessageContainer post={post}/>;
let flag;
let flagFunc;
let flagVisible = '';
let flagTooltip = (
<Tooltip id='flagTooltip'>
<FormattedMessage
id='flag_post.flag'
defaultMessage='Flag for follow up'
/>
</Tooltip>
);
if (this.props.isFlagged) {
flagVisible = 'visible';
flag = (
<span
className='icon'
dangerouslySetInnerHTML={{__html: flagIcon}}
/>
);
flagFunc = this.unflagPost;
flagTooltip = (
<Tooltip id='flagTooltip'>
<FormattedMessage
id='flag_post.unflag'
defaultMessage='Unflag'
/>
</Tooltip>
);
} else {
flag = (
<span
className='icon'
dangerouslySetInnerHTML={{__html: flagIcon}}
/>
);
flagFunc = this.flagPost;
}
const timeOptions = {
day: 'numeric',
month: 'short',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
hour12: !this.props.useMilitaryTime
};
return (
<div className={'post post--root post--thread ' + userCss + ' ' + systemMessageClass + ' ' + compactClass}>
<div className='post-right-channel__name'>{channelName}</div>
<div className='post__content'>
{profilePicContainer}
<div>
<ul className='post__header'>
<li className='col__name'>{userProfile}</li>
{botIndicator}
<li className='col'>
<time className='post__time'>
{Utils.getDateForUnixTicks(post.create_at).toLocaleString('en', timeOptions)}
</time>
<OverlayTrigger
key={'rootpostflagtooltipkey' + flagVisible}
delayShow={Constants.OVERLAY_TIME_DELAY}
placement='top'
overlay={flagTooltip}
>
<a
href='#'
className={'flag-icon__container ' + flagVisible}
onClick={flagFunc}
>
{flag}
</a>
</OverlayTrigger>
</li>
<li className='col col__reply'>
{rootOptions}
</li>
</ul>
<div className='post__body'>
<PostBodyAdditionalContent
post={post}
message={messageWrapper}
previewCollapsed={this.props.previewCollapsed}
/>
{fileAttachment}
<ReactionListContainer
post={post}
currentUserId={this.props.currentUser.id}
/>
</div>
</div>
</div>
</div>
);
}
}
RhsRootPost.defaultProps = {
commentCount: 0
};
RhsRootPost.propTypes = {
post: React.PropTypes.object.isRequired,
user: React.PropTypes.object.isRequired,
currentUser: React.PropTypes.object.isRequired,
commentCount: React.PropTypes.number,
compactDisplay: React.PropTypes.bool,
useMilitaryTime: React.PropTypes.bool.isRequired,
isFlagged: React.PropTypes.bool,
status: React.PropTypes.string,
previewCollapsed: React.PropTypes.string,
isBusy: React.PropTypes.bool
};