summaryrefslogtreecommitdiffstats
path: root/webapp/components/post_body.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/components/post_body.jsx')
-rw-r--r--webapp/components/post_body.jsx224
1 files changed, 224 insertions, 0 deletions
diff --git a/webapp/components/post_body.jsx b/webapp/components/post_body.jsx
new file mode 100644
index 000000000..cb682abba
--- /dev/null
+++ b/webapp/components/post_body.jsx
@@ -0,0 +1,224 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import ReactDOM from 'react-dom';
+import FileAttachmentList from './file_attachment_list.jsx';
+import UserStore from 'stores/user_store.jsx';
+import * as Utils from 'utils/utils.jsx';
+import * as Emoji from 'utils/emoticons.jsx';
+import Constants from 'utils/constants.jsx';
+import * as TextFormatting from 'utils/text_formatting.jsx';
+import twemoji from 'twemoji';
+import PostBodyAdditionalContent from './post_body_additional_content.jsx';
+
+import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl';
+
+import loadingGif from 'images/load.gif';
+
+const holders = defineMessages({
+ plusOne: {
+ id: 'post_body.plusOne',
+ defaultMessage: ' plus 1 other file'
+ },
+ plusMore: {
+ id: 'post_body.plusMore',
+ defaultMessage: ' plus {count} other files'
+ }
+});
+
+import React from 'react';
+
+class PostBody extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.parseEmojis = this.parseEmojis.bind(this);
+ }
+
+ getAllChildNodes(nodeIn) {
+ var textNodes = [];
+
+ function getTextNodes(node) {
+ textNodes.push(node);
+
+ for (var i = 0, len = node.childNodes.length; i < len; ++i) {
+ getTextNodes(node.childNodes[i]);
+ }
+ }
+
+ getTextNodes(nodeIn);
+ return textNodes;
+ }
+
+ parseEmojis() {
+ twemoji.parse(ReactDOM.findDOMNode(this), {
+ className: 'emoji twemoji',
+ base: '',
+ folder: Emoji.getImagePathForEmoticon()
+ });
+ }
+
+ componentDidMount() {
+ this.parseEmojis();
+ }
+
+ render() {
+ const {formatMessage} = this.props.intl;
+ const post = this.props.post;
+ const filenames = this.props.post.filenames;
+ const parentPost = this.props.parentPost;
+
+ let comment = '';
+ let postClass = '';
+
+ if (parentPost) {
+ const profile = UserStore.getProfile(parentPost.user_id);
+
+ let apostrophe = '';
+ let name = '...';
+ if (profile != null) {
+ let username = profile.username;
+ if (parentPost.props &&
+ parentPost.props.from_webhook &&
+ parentPost.props.override_username &&
+ global.window.mm_config.EnablePostUsernameOverride === 'true') {
+ username = parentPost.props.override_username;
+ }
+
+ if (username.slice(-1) === 's') {
+ apostrophe = '\'';
+ } else {
+ apostrophe = '\'s';
+ }
+ name = (
+ <a
+ className='theme'
+ onClick={Utils.searchForTerm.bind(null, username)}
+ >
+ {username}
+ </a>
+ );
+ }
+
+ let message = '';
+ if (parentPost.message) {
+ message = Utils.replaceHtmlEntities(parentPost.message);
+ } else if (parentPost.filenames.length) {
+ message = parentPost.filenames[0].split('/').pop();
+
+ if (parentPost.filenames.length === 2) {
+ message += formatMessage(holders.plusOne);
+ } else if (parentPost.filenames.length > 2) {
+ message += formatMessage(holders.plusMore, {count: (parentPost.filenames.length - 1)});
+ }
+ }
+
+ comment = (
+ <div className='post__link'>
+ <span>
+ <FormattedMessage
+ id='post_body.commentedOn'
+ defaultMessage='Commented on {name}{apostrophe} message: '
+ values={{
+ name: (name),
+ apostrophe: apostrophe
+ }}
+ />
+ <a
+ className='theme'
+ onClick={this.props.handleCommentClick}
+ >
+ {message}
+ </a>
+ </span>
+ </div>
+ );
+ }
+
+ let loading;
+ if (post.state === Constants.POST_FAILED) {
+ postClass += ' post--fail';
+ loading = (
+ <a
+ className='theme post-retry pull-right'
+ href='#'
+ onClick={this.props.retryPost}
+ >
+ <FormattedMessage
+ id='post_body.retry'
+ defaultMessage='Retry'
+ />
+ </a>
+ );
+ } else if (post.state === Constants.POST_LOADING) {
+ postClass += ' post-waiting';
+ loading = (
+ <img
+ className='post-loading-gif pull-right'
+ src={loadingGif}
+ />
+ );
+ }
+
+ let fileAttachmentHolder = '';
+ if (filenames && filenames.length > 0) {
+ fileAttachmentHolder = (
+ <FileAttachmentList
+ filenames={filenames}
+ channelId={post.channel_id}
+ userId={post.user_id}
+ />
+ );
+ }
+
+ let message;
+ let additionalContent = null;
+ if (this.props.post.state === Constants.POST_DELETED) {
+ message = (
+ <FormattedMessage
+ id='post_body.deleted'
+ defaultMessage='(message deleted)'
+ />
+ );
+ } else {
+ message = (
+ <span
+ onClick={TextFormatting.handleClick}
+ dangerouslySetInnerHTML={{__html: TextFormatting.formatText(this.props.post.message)}}
+ />
+ );
+
+ additionalContent = (
+ <PostBodyAdditionalContent post={this.props.post}/>
+ );
+ }
+
+ return (
+ <div>
+ {comment}
+ <div className='post__body'>
+ <div
+ key={`${post.id}_message`}
+ id={`${post.id}_message`}
+ className={postClass}
+ >
+ {loading}
+ {message}
+ </div>
+ {fileAttachmentHolder}
+ {additionalContent}
+ </div>
+ </div>
+ );
+ }
+}
+
+PostBody.propTypes = {
+ intl: intlShape.isRequired,
+ post: React.PropTypes.object.isRequired,
+ parentPost: React.PropTypes.object,
+ retryPost: React.PropTypes.func.isRequired,
+ handleCommentClick: React.PropTypes.func.isRequired
+};
+
+export default injectIntl(PostBody);