added client predictive commenting

Этот коммит содержится в:
JoramWilander
2015-07-23 12:45:08 -04:00
родитель 32f7b50bb5
Коммит 5596a6b37c
4 изменённых файлов: 97 добавлений и 17 удалений

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

@@ -2,15 +2,16 @@
// See License.txt for license information.
var client = require('../utils/client.jsx');
var AsyncClient =require('../utils/async_client.jsx');
var AsyncClient = require('../utils/async_client.jsx');
var SocketStore = require('../stores/socket_store.jsx');
var ChannelStore = require('../stores/channel_store.jsx');
var UserStore = require('../stores/user_store.jsx');
var PostStore = require('../stores/post_store.jsx');
var Textbox = require('./textbox.jsx');
var MsgTyping = require('./msg_typing.jsx');
var FileUpload = require('./file_upload.jsx');
var FilePreview = require('./file_preview.jsx');
var utils = require('../utils/utils.jsx');
var Constants = require('../utils/constants.jsx');
module.exports = React.createClass({
@@ -39,10 +40,16 @@ module.exports = React.createClass({
return;
}
var user_id = UserStore.getCurrentId();
post.channel_id = this.props.channelId;
post.root_id = this.props.rootId;
post.parent_id = this.props.parentId;
post.parent_id = this.props.rootId;
post.filenames = this.state.previews;
var time = utils.getTimestamp();
post.pending_post_id = user_id + ":"+ time;
post.user_id = user_id;
post.create_at = time;
this.setState({submitting: true, serverError: null});
@@ -69,10 +76,19 @@ module.exports = React.createClass({
$('#post_deleted').modal('show');
}
} else {
this.setState(state);
post.did_fail = true;
PostStore.updatePendingPost(post);
}
state.submitting = false;
this.setState(state);
}.bind(this)
);
post.is_loading = true;
PostStore.storePendingPost(post);
PostStore.storeCommentDraft(this.props.rootId, null);
this.setState({ messageText: '', submitting: false, post_error: null, previews: [], server_error: null, limit_error: null });
},
commentMsgKeyPress: function(e) {
if (e.which === 13 && !e.shiftKey && !e.altKey) {

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

@@ -214,20 +214,34 @@ module.exports = React.createClass({
var channelId = ChannelStore.getCurrentId();
if (this.state.channelId !== channelId) {
var draft = PostStore.getCurrentDraft();
this.setState({
channelId: channelId, messageText: draft['message'], initialText: draft['message'], submitting: false,
serverError: null, postError: null, previews: draft['previews'], uploadsInProgress: draft['uploadsInProgress']
});
var previews = [];
var messageText = '';
var uploadsInProgress = 0;
if (draft && draft['previews'] && draft['message']) {
previews = draft['previews'];
messageText = draft['message'];
uploadsInProgress = draft['uploadsInProgress'];
}
this.setState({channelId: channelId, messageText: messageText, initialText: messageText, submitting: false, serverError: null, postError: null, previews: previews, uploadsInProgress: uploadsInProgress});
}
},
getInitialState: function() {
PostStore.clearDraftUploads();
PostStore.clearPendingPosts(ChannelStore.getCurrentId());
var draft = PostStore.getCurrentDraft();
return {
channelId: ChannelStore.getCurrentId(), messageText: draft['message'], uploadsInProgress: draft['uploadsInProgress'],
previews: draft['previews'], submitting: false, initialText: draft['message']
};
var previews = [];
var messageText = '';
var uploadsInProgress = 0;
if (draft && draft["previews"] && draft["message"]) {
previews = draft['previews'];
messageText = draft['message'];
uploadsInProgress = draft['uploadsInProgress'];
}
return { channelId: ChannelStore.getCurrentId(), messageText: messageText, uploadsInProgress: uploadsInProgress, previews: previews, submitting: false, initialText: messageText};
},
getFileCount: function(channelId) {
if (channelId === this.state.channelId) {

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

@@ -22,16 +22,19 @@ module.exports = React.createClass({
var comments = "";
var lastCommentClass = this.props.isLastComment ? " comment-icon__container__show" : " comment-icon__container__hide";
if (this.props.commentCount >= 1) {
if (this.props.commentCount >= 1 && !post.did_fail && !post.is_loading) {
comments = <a href="#" className={"comment-icon__container theme" + lastCommentClass} onClick={this.props.handleCommentClick}><span className="comment-icon" dangerouslySetInnerHTML={{__html: Constants.COMMENT_ICON }} />{this.props.commentCount}</a>;
}
var show_dropdown = isOwner || (this.props.allowReply === "true" && type != "Comment");
if (post.did_fail || post.is_loading) show_dropdown = false;
return (
<ul className="post-header post-info">
<li className="post-header-col"><time className="post-profile-time">{ utils.displayDateTime(post.create_at) }</time></li>
<li className="post-header-col post-header__reply">
<div className="dropdown">
{ isOwner || (this.props.allowReply === "true" && type != "Comment") ?
{ show_dropdown ?
<div>
<a href="#" className="dropdown-toggle theme" type="button" data-toggle="dropdown" aria-expanded="false" />
<ul className="dropdown-menu" role="menu">

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

@@ -12,6 +12,7 @@ var CreateComment = require( './create_comment.jsx' );
var Constants = require('../utils/constants.jsx');
var FileAttachmentList = require('./file_attachment_list.jsx');
var FileUploadOverlay = require('./file_upload_overlay.jsx');
var client = require('../utils/client.jsx');
var ActionTypes = Constants.ActionTypes;
RhsHeaderPost = React.createClass({
@@ -119,10 +120,36 @@ RootPost = React.createClass({
});
CommentPost = React.createClass({
retryComment: function(e) {
e.preventDefault();
var post = this.props.post;
client.createPost(post, post.channel_id,
function(data) {
AsyncClient.getPosts(true);
var member = ChannelStore.getMember(post.channel_id);
member.msg_count = channel.total_msg_count;
member.last_viewed_at = (new Date).getTime();
ChannelStore.setChannelMember(member);
}.bind(this),
function(err) {
post.did_fail = true;
PostStore.updatePendingPost(post);
this.forceUpdate();
}.bind(this)
);
post.did_fail = false;
post.is_loading = true;
PostStore.updatePendingPost(post);
this.forceUpdate();
},
render: function() {
var post = this.props.post;
var commentClass = "post";
var post = this.props.post;
var currentUserCss = "";
if (UserStore.getCurrentId() === post.user_id) {
@@ -139,6 +166,16 @@ CommentPost = React.createClass({
var message = utils.textToJsx(post.message);
var timestamp = UserStore.getCurrentUser().update_at;
var loading;
var postClass = "";
if (post.did_fail) {
postClass += " post-fail";
loading = <a className="post-retry pull-right" href="#" onClick={this.retryComment}>Retry</a>;
} else if (post.is_loading) {
postClass += " post-waiting";
loading = <img className="post-loading-gif pull-right" src="/static/images/load.gif"/>;
}
return (
<div className={commentClass + " " + currentUserCss}>
<div className="post-profile-img__container">
@@ -149,7 +186,7 @@ CommentPost = React.createClass({
<li className="post-header-col"><strong><UserProfile userId={post.user_id} /></strong></li>
<li className="post-header-col"><time className="post-right-comment-time">{ utils.displayDateTime(post.create_at) }</time></li>
<li className="post-header-col post-header__reply">
{ isOwner ?
{ isOwner && !post.did_fail && !post.is_loading ?
<div className="dropdown" onClick={function(e){$('.post-list-holder-by-time').scrollTop($(".post-list-holder-by-time").scrollTop() + 50);}}>
<a href="#" className="dropdown-toggle theme" type="button" data-toggle="dropdown" aria-expanded="false" />
<ul className="dropdown-menu" role="menu">
@@ -161,7 +198,7 @@ CommentPost = React.createClass({
</li>
</ul>
<div className="post-body">
<p>{message}</p>
<p className={postClass}>{loading}{message}</p>
{ post.filenames && post.filenames.length > 0 ?
<FileAttachmentList
filenames={post.filenames}
@@ -177,7 +214,17 @@ CommentPost = React.createClass({
});
function getStateFromStores() {
return { post_list: PostStore.getSelectedPost() };
var post_list = PostStore.getSelectedPost();
if (!post_list || post_list.order.length < 1) return { post_list: {} };
var channel_id = post_list.posts[post_list.order[0]].channel_id;
var pending_post_list = PostStore.getPendingPosts(channel_id);
if (pending_post_list) {
for (var pid in pending_post_list.posts) { post_list.posts[pid] = pending_post_list.posts[pid] };
}
return { post_list: post_list };
}
module.exports = React.createClass({