diff options
Diffstat (limited to 'web/react/components/rhs_thread.jsx')
-rw-r--r-- | web/react/components/rhs_thread.jsx | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/web/react/components/rhs_thread.jsx b/web/react/components/rhs_thread.jsx new file mode 100644 index 000000000..adddeccf0 --- /dev/null +++ b/web/react/components/rhs_thread.jsx @@ -0,0 +1,215 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +var PostStore = require('../stores/post_store.jsx'); +var UserStore = require('../stores/user_store.jsx'); +var utils = require('../utils/utils.jsx'); +var SearchBox = require('./search_bar.jsx'); +var CreateComment = require('./create_comment.jsx'); +var RhsHeaderPost = require('./rhs_header_post.jsx'); +var RootPost = require('./rhs_root_post.jsx'); +var Comment = require('./rhs_comment.jsx'); +var Constants = require('../utils/constants.jsx'); +var FileUploadOverlay = require('./file_upload_overlay.jsx'); + +export default class RhsThread extends React.Component { + constructor(props) { + super(props); + + this.onChange = this.onChange.bind(this); + this.onChangeAll = this.onChangeAll.bind(this); + this.onTimeChange = this.onTimeChange.bind(this); + + this.state = this.getStateFromStores(); + } + getStateFromStores() { + var postList = PostStore.getSelectedPost(); + if (!postList || postList.order.length < 1) { + return {postList: {}}; + } + + var channelId = postList.posts[postList.order[0]].channel_id; + var pendingPostList = PostStore.getPendingPosts(channelId); + + if (pendingPostList) { + for (var pid in pendingPostList.posts) { + postList.posts[pid] = pendingPostList.posts[pid]; + } + } + + return {postList: postList}; + } + componentDidMount() { + PostStore.addSelectedPostChangeListener(this.onChange); + PostStore.addChangeListener(this.onChangeAll); + UserStore.addStatusesChangeListener(this.onTimeChange); + this.resize(); + $(window).resize(function resize() { + this.resize(); + }.bind(this)); + } + componentDidUpdate() { + $('.post-right__scroll').scrollTop($('.post-right__scroll')[0].scrollHeight); + $('.post-right__scroll').perfectScrollbar('update'); + this.resize(); + } + componentWillUnmount() { + PostStore.removeSelectedPostChangeListener(this.onChange); + PostStore.removeChangeListener(this.onChangeAll); + UserStore.removeStatusesChangeListener(this.onTimeChange); + } + onChange() { + var newState = this.getStateFromStores(); + if (!utils.areStatesEqual(newState, this.state)) { + this.setState(newState); + } + } + onChangeAll() { + // if something was changed in the channel like adding a + // comment or post then lets refresh the sidebar list + var currentSelected = PostStore.getSelectedPost(); + if (!currentSelected || currentSelected.order.length === 0) { + return; + } + + var currentPosts = PostStore.getPosts(currentSelected.posts[currentSelected.order[0]].channel_id); + + if (!currentPosts || currentPosts.order.length === 0) { + return; + } + + if (currentPosts.posts[currentPosts.order[0]].channel_id === currentSelected.posts[currentSelected.order[0]].channel_id) { + currentSelected.posts = {}; + for (var postId in currentPosts.posts) { + currentSelected.posts[postId] = currentPosts.posts[postId]; + } + + PostStore.storeSelectedPost(currentSelected); + } + + var newState = this.getStateFromStores(); + if (!utils.areStatesEqual(newState, this.state)) { + this.setState(newState); + } + } + onTimeChange() { + for (var id in this.state.postList.posts) { + if (!this.refs[id]) { + continue; + } + this.refs[id].forceUpdate(); + } + } + resize() { + var height = $(window).height() - $('#error_bar').outerHeight() - 100; + $('.post-right__scroll').css('height', height + 'px'); + $('.post-right__scroll').scrollTop(100000); + $('.post-right__scroll').perfectScrollbar(); + $('.post-right__scroll').perfectScrollbar('update'); + } + render() { + var postList = this.state.postList; + + if (postList == null) { + return ( + <div></div> + ); + } + + var selectedPost = postList.posts[postList.order[0]]; + var rootPost = null; + + if (selectedPost.root_id === '') { + rootPost = selectedPost; + } else { + rootPost = postList.posts[selectedPost.root_id]; + } + + var postsArray = []; + + for (var postId in postList.posts) { + var cpost = postList.posts[postId]; + if (cpost.root_id === rootPost.id) { + postsArray.push(cpost); + } + } + + // sort failed posts to bottom, followed by pending, and then regular posts + postsArray.sort(function postSort(a, b) { + if ((a.state === Constants.POST_LOADING || a.state === Constants.POST_FAILED) && (b.state !== Constants.POST_LOADING && b.state !== Constants.POST_FAILED)) { + return 1; + } + if ((a.state !== Constants.POST_LOADING && a.state !== Constants.POST_FAILED) && (b.state === Constants.POST_LOADING || b.state === Constants.POST_FAILED)) { + return -1; + } + + if (a.state === Constants.POST_LOADING && b.state === Constants.POST_FAILED) { + return -1; + } + if (a.state === Constants.POST_FAILED && b.state === Constants.POST_LOADING) { + return 1; + } + + if (a.create_at < b.create_at) { + return -1; + } + if (a.create_at > b.create_at) { + return 1; + } + return 0; + }); + + var currentId = UserStore.getCurrentId(); + var searchForm; + if (currentId != null) { + searchForm = <SearchBox />; + } + + return ( + <div className='post-right__container'> + <FileUploadOverlay + overlayType='right' /> + <div className='search-bar__container sidebar--right__search-header'>{searchForm}</div> + <div className='sidebar-right__body'> + <RhsHeaderPost + fromSearch={this.props.fromSearch} + isMentionSearch={this.props.isMentionSearch} + /> + <div className='post-right__scroll'> + <RootPost + post={rootPost} + commentCount={postsArray.length} + /> + <div className='post-right-comments-container'> + {postsArray.map(function mapPosts(comPost) { + return ( + <Comment + ref={comPost.id} + key={comPost.id} + post={comPost} + selected={(comPost.id === selectedPost.id)} + /> + ); + })} + </div> + <div className='post-create__container'> + <CreateComment + channelId={rootPost.channel_id} + rootId={rootPost.id} + /> + </div> + </div> + </div> + </div> + ); + } +} + +RhsThread.defaultProps = { + fromSearch: '', + isMentionSearch: false +}; +RhsThread.propTypes = { + fromSearch: React.PropTypes.string, + isMentionSearch: React.PropTypes.bool +}; |