summaryrefslogtreecommitdiffstats
path: root/webapp/components/post_view/post/post.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/components/post_view/post/post.jsx')
-rw-r--r--webapp/components/post_view/post/post.jsx306
1 files changed, 306 insertions, 0 deletions
diff --git a/webapp/components/post_view/post/post.jsx b/webapp/components/post_view/post/post.jsx
new file mode 100644
index 000000000..eda4405bb
--- /dev/null
+++ b/webapp/components/post_view/post/post.jsx
@@ -0,0 +1,306 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import PostHeader from 'components/post_view/post_header';
+import PostBody from 'components/post_view/post_body';
+import ProfilePicture from 'components/profile_picture.jsx';
+
+import Constants from 'utils/constants.jsx';
+const ActionTypes = Constants.ActionTypes;
+import {Posts} from 'mattermost-redux/constants';
+
+import * as Utils from 'utils/utils.jsx';
+import * as PostUtils from 'utils/post_utils.jsx';
+import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
+
+import React from 'react';
+import PropTypes from 'prop-types';
+
+export default class Post extends React.PureComponent {
+ static propTypes = {
+
+ /**
+ * The post to render
+ */
+ post: PropTypes.object.isRequired,
+
+ /**
+ * The user who created the post
+ */
+ user: PropTypes.object,
+
+ /**
+ * The status of the poster
+ */
+ status: PropTypes.string,
+
+ /**
+ * The logged in user
+ */
+ currentUser: PropTypes.object.isRequired,
+
+ /**
+ * Set to center the post
+ */
+ center: PropTypes.bool,
+
+ /**
+ * Set to render post compactly
+ */
+ compactDisplay: PropTypes.bool,
+
+ /**
+ * Set to render a preview of the parent post above this reply
+ */
+ isFirstReply: PropTypes.bool,
+
+ /**
+ * Set to highlight the background of the post
+ */
+ highlight: PropTypes.bool,
+
+ /**
+ * Set to render this post as if it was attached to the previous post
+ */
+ consecutivePostByUser: PropTypes.bool,
+
+ /**
+ * Set if the previous post is a comment
+ */
+ previousPostIsComment: PropTypes.bool,
+
+ /**
+ * Set to render this comment as a mention
+ */
+ isCommentMention: PropTypes.bool,
+
+ /**
+ * The number of replies in the same thread as this post
+ */
+ replyCount: PropTypes.number,
+
+ /**
+ * Set to mark the poster as in a webrtc call
+ */
+ isBusy: PropTypes.bool,
+
+ /**
+ * The post count used for selenium tests
+ */
+ lastPostCount: PropTypes.number,
+
+ /**
+ * Function to get the post list HTML element
+ */
+ getPostList: PropTypes.func.isRequired
+ }
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ dropdownOpened: false
+ };
+ }
+
+ handleCommentClick = (e) => {
+ e.preventDefault();
+
+ AppDispatcher.handleServerAction({
+ type: ActionTypes.RECEIVED_POST_SELECTED,
+ postId: Utils.getRootId(this.props.post)
+ });
+
+ AppDispatcher.handleServerAction({
+ type: ActionTypes.RECEIVED_SEARCH,
+ results: null
+ });
+ }
+
+ handleDropdownOpened = (opened) => {
+ this.setState({
+ dropdownOpened: opened
+ });
+ }
+
+ forceUpdateInfo = () => {
+ this.refs.info.forceUpdate();
+ this.refs.header.forceUpdate();
+ }
+
+ getClassName = (post, isSystemMessage, fromWebhook) => {
+ let className = 'post';
+
+ if (post.failed || post.state === Posts.POST_DELETED) {
+ className += ' post--hide-controls';
+ }
+
+ if (this.props.highlight) {
+ className += ' post--highlight';
+ }
+
+ let rootUser = '';
+ if (this.props.isFirstReply) {
+ rootUser = 'other--root';
+ } else if (!post.root_id && !this.props.previousPostIsComment && this.props.consecutivePostByUser) {
+ rootUser = 'same--root';
+ } else if (post.root_id) {
+ rootUser = 'same--root';
+ } else {
+ rootUser = 'other--root';
+ }
+
+ let currentUserCss = '';
+ if (this.props.currentUser.id === post.user_id && !fromWebhook && !isSystemMessage) {
+ currentUserCss = 'current--user';
+ }
+
+ let sameUserClass = '';
+ if (this.props.consecutivePostByUser) {
+ sameUserClass = 'same--user';
+ }
+
+ let postType = '';
+ if (post.root_id && post.root_id.length > 0) {
+ postType = 'post--comment';
+ } else if (this.props.replyCount > 0) {
+ postType = 'post--root';
+ sameUserClass = '';
+ rootUser = '';
+ }
+
+ if (isSystemMessage) {
+ className += ' post--system';
+ sameUserClass = '';
+ currentUserCss = '';
+ postType = '';
+ rootUser = '';
+ }
+
+ if (this.props.compactDisplay) {
+ className += ' post--compact';
+ }
+
+ if (this.state.dropdownOpened) {
+ className += ' post--hovered';
+ }
+
+ if (post.is_pinned) {
+ className += ' post--pinned';
+ }
+
+ return className + ' ' + sameUserClass + ' ' + rootUser + ' ' + postType + ' ' + currentUserCss;
+ }
+
+ render() {
+ const post = this.props.post;
+ const mattermostLogo = Constants.MATTERMOST_ICON_SVG;
+
+ const isSystemMessage = PostUtils.isSystemMessage(post);
+ const fromWebhook = post.props && post.props.from_webhook === 'true';
+
+ let timestamp = 0;
+ if (!this.props.user || this.props.user.last_picture_update == null) {
+ timestamp = this.props.currentUser.last_picture_update;
+ } else {
+ timestamp = this.props.user.last_picture_update;
+ }
+
+ let status = this.props.status;
+ if (fromWebhook) {
+ status = null;
+ }
+
+ let profilePic = (
+ <ProfilePicture
+ src={PostUtils.getProfilePicSrcForPost(post, timestamp)}
+ status={status}
+ user={this.props.user}
+ isBusy={this.props.isBusy}
+ />
+ );
+
+ if (fromWebhook) {
+ profilePic = (
+ <ProfilePicture
+ src={PostUtils.getProfilePicSrcForPost(post, timestamp)}
+ />
+ );
+ } else if (PostUtils.isSystemMessage(post)) {
+ profilePic = (
+ <span
+ className='icon'
+ dangerouslySetInnerHTML={{__html: mattermostLogo}}
+ />
+ );
+ }
+
+ let centerClass = '';
+ if (this.props.center) {
+ centerClass = 'center';
+ }
+
+ if (this.props.compactDisplay) {
+ if (fromWebhook) {
+ profilePic = (
+ <ProfilePicture
+ src=''
+ status={status}
+ isBusy={this.props.isBusy}
+ user={this.props.user}
+ />
+ );
+ } else {
+ profilePic = (
+ <ProfilePicture
+ src=''
+ status={status}
+ />
+ );
+ }
+ }
+
+ const profilePicContainer = (<div className='post__img'>{profilePic}</div>);
+
+ return (
+ <div
+ ref={(div) => {
+ this.domNode = div;
+ }}
+ >
+ <div
+ id={'post_' + post.id}
+ className={this.getClassName(this.props.post, isSystemMessage, fromWebhook)}
+ >
+ <div className={'post__content ' + centerClass}>
+ {profilePicContainer}
+ <div>
+ <PostHeader
+ ref='header'
+ post={post}
+ handleCommentClick={this.handleCommentClick}
+ handleDropdownOpened={this.handleDropdownOpened}
+ user={this.props.user}
+ currentUser={this.props.currentUser}
+ compactDisplay={this.props.compactDisplay}
+ status={this.props.status}
+ isBusy={this.props.isBusy}
+ lastPostCount={this.props.lastPostCount}
+ replyCount={this.props.replyCount}
+ consecutivePostByUser={this.props.consecutivePostByUser}
+ getPostList={this.props.getPostList}
+ />
+ <PostBody
+ post={post}
+ handleCommentClick={this.handleCommentClick}
+ compactDisplay={this.props.compactDisplay}
+ lastPostCount={this.props.lastPostCount}
+ isCommentMention={this.props.isCommentMention}
+ />
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+}