diff options
Diffstat (limited to 'web/react')
-rw-r--r-- | web/react/components/create_post.jsx | 26 | ||||
-rw-r--r-- | web/react/components/edit_post_modal.jsx | 36 | ||||
-rw-r--r-- | web/react/components/textbox.jsx | 8 | ||||
-rw-r--r-- | web/react/stores/post_store.jsx | 37 | ||||
-rw-r--r-- | web/react/utils/constants.jsx | 10 |
5 files changed, 111 insertions, 6 deletions
diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index 6203e567a..2581bdcca 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -16,6 +16,7 @@ const Utils = require('../utils/utils.jsx'); const Constants = require('../utils/constants.jsx'); const ActionTypes = Constants.ActionTypes; +const KeyCodes = Constants.KeyCodes; export default class CreatePost extends React.Component { constructor(props) { @@ -35,6 +36,7 @@ export default class CreatePost extends React.Component { this.removePreview = this.removePreview.bind(this); this.onChange = this.onChange.bind(this); this.getFileCount = this.getFileCount.bind(this); + this.handleArrowUp = this.handleArrowUp.bind(this); PostStore.clearDraftUploads(); @@ -172,7 +174,7 @@ export default class CreatePost extends React.Component { } } postMsgKeyPress(e) { - if (e.which === 13 && !e.shiftKey && !e.altKey) { + if (e.which === KeyCodes.ENTER && !e.shiftKey && !e.altKey) { e.preventDefault(); ReactDOM.findDOMNode(this.refs.textbox).blur(); this.handleSubmit(e); @@ -292,6 +294,27 @@ export default class CreatePost extends React.Component { const draft = PostStore.getDraft(channelId); return draft.previews.length + draft.uploadsInProgress.length; } + handleArrowUp(e) { + if (e.keyCode === KeyCodes.UP && this.state.messageText === '') { + e.preventDefault(); + + const channelId = ChannelStore.getCurrentId(); + const lastPost = PostStore.getCurrentUsersLatestPost(channelId); + if (!lastPost) { + return; + } + var type = (lastPost.root_id && lastPost.root_id.length > 0) ? 'Comment' : 'Post'; + + AppDispatcher.handleViewAction({ + type: ActionTypes.RECIEVED_EDIT_POST, + refocusId: '#post_textbox', + title: type, + message: lastPost.message, + postId: lastPost.id, + channelId: lastPost.channel_id + }); + } + } render() { let serverError = null; if (this.state.serverError) { @@ -336,6 +359,7 @@ export default class CreatePost extends React.Component { <Textbox onUserInput={this.handleUserInput} onKeyPress={this.postMsgKeyPress} + onKeyDown={this.handleArrowUp} onHeightChange={this.resizePostHolder} messageText={this.state.messageText} createMessage='Write a message...' diff --git a/web/react/components/edit_post_modal.jsx b/web/react/components/edit_post_modal.jsx index 3dbff18cb..90d9696e7 100644 --- a/web/react/components/edit_post_modal.jsx +++ b/web/react/components/edit_post_modal.jsx @@ -5,6 +5,7 @@ var Client = require('../utils/client.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var Textbox = require('./textbox.jsx'); var BrowserStore = require('../stores/browser_store.jsx'); +var PostStore = require('../stores/post_store.jsx'); export default class EditPostModal extends React.Component { constructor() { @@ -14,6 +15,7 @@ export default class EditPostModal extends React.Component { this.handleEditInput = this.handleEditInput.bind(this); this.handleEditKeyPress = this.handleEditKeyPress.bind(this); this.handleUserInput = this.handleUserInput.bind(this); + this.handleEditPostEvent = this.handleEditPostEvent.bind(this); this.state = {editText: '', title: '', post_id: '', channel_id: '', comments: 0, refocusId: ''}; } @@ -35,16 +37,15 @@ export default class EditPostModal extends React.Component { Client.updatePost(updatedPost, function success() { - AsyncClient.getPosts(this.state.channel_id); + AsyncClient.getPosts(updatedPost.channel_id); window.scrollTo(0, 0); - }.bind(this), + }, function error(err) { AsyncClient.dispatchError(err, 'updatePost'); } ); $('#edit_post').modal('hide'); - $(this.state.refocusId).focus(); } handleEditInput(editMessage) { this.setState({editText: editMessage}); @@ -59,6 +60,18 @@ export default class EditPostModal extends React.Component { handleUserInput(e) { this.setState({editText: e.target.value}); } + handleEditPostEvent(options) { + this.setState({ + editText: options.message || '', + title: options.title || '', + post_id: options.postId || '', + channel_id: options.channelId || '', + comments: options.comments || 0, + refocusId: options.refocusId || '' + }); + + $(React.findDOMNode(this.refs.modal)).modal('show'); + } componentDidMount() { var self = this; @@ -68,12 +81,29 @@ export default class EditPostModal extends React.Component { $(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', function onShow(e) { var button = e.relatedTarget; + if (!button) { + return; + } self.setState({editText: $(button).attr('data-message'), title: $(button).attr('data-title'), channel_id: $(button).attr('data-channelid'), post_id: $(button).attr('data-postid'), comments: $(button).attr('data-comments'), refocusId: $(button).attr('data-refoucsid')}); }); $(ReactDOM.findDOMNode(this.refs.modal)).on('shown.bs.modal', function onShown() { self.refs.editbox.resize(); + $('#edit_textbox').get(0).focus(); }); + + $(React.findDOMNode(this.refs.modal)).on('hide.bs.modal', function onShown() { + if (self.state.refocusId !== '') { + setTimeout(() => { + $(self.state.refocusId).get(0).focus(); + }); + } + }); + + PostStore.addEditPostListener(this.handleEditPostEvent); + } + componentWillUnmount() { + PostStore.removeEditPostListener(this.handleEditPostEvent); } render() { var error = (<div className='form-group'><br /></div>); diff --git a/web/react/components/textbox.jsx b/web/react/components/textbox.jsx index d51fb9523..86bb42f62 100644 --- a/web/react/components/textbox.jsx +++ b/web/react/components/textbox.jsx @@ -9,6 +9,7 @@ const ErrorStore = require('../stores/error_store.jsx'); const Utils = require('../utils/utils.jsx'); const Constants = require('../utils/constants.jsx'); const ActionTypes = Constants.ActionTypes; +const KeyCodes = Constants.KeyCodes; export default class Textbox extends React.Component { constructor(props) { @@ -148,8 +149,10 @@ export default class Textbox extends React.Component { this.doProcessMentions = true; } - if (e.keyCode === 8) { + if (e.keyCode === KeyCodes.BACKSPACE) { this.handleBackspace(e); + } else if (this.props.onKeyDown) { + this.props.onKeyDown(e); } } @@ -318,5 +321,6 @@ Textbox.propTypes = { onUserInput: React.PropTypes.func.isRequired, onKeyPress: React.PropTypes.func.isRequired, onHeightChange: React.PropTypes.func, - createMessage: React.PropTypes.string.isRequired + createMessage: React.PropTypes.string.isRequired, + onKeyDown: React.PropTypes.func }; diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx index d8da48000..8609d8bbf 100644 --- a/web/react/stores/post_store.jsx +++ b/web/react/stores/post_store.jsx @@ -6,6 +6,7 @@ var EventEmitter = require('events').EventEmitter; var ChannelStore = require('../stores/channel_store.jsx'); var BrowserStore = require('../stores/browser_store.jsx'); +var UserStore = require('../stores/user_store.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; @@ -16,6 +17,7 @@ var SEARCH_TERM_CHANGE_EVENT = 'search_term_change'; var SELECTED_POST_CHANGE_EVENT = 'selected_post_change'; var MENTION_DATA_CHANGE_EVENT = 'mention_data_change'; var ADD_MENTION_EVENT = 'add_mention'; +var EDIT_POST_EVENT = 'edit_post'; class PostStoreClass extends EventEmitter { constructor() { @@ -75,6 +77,10 @@ class PostStoreClass extends EventEmitter { this.clearCommentDraftUploads = this.clearCommentDraftUploads.bind(this); this.storeLatestUpdate = this.storeLatestUpdate.bind(this); this.getLatestUpdate = this.getLatestUpdate.bind(this); + this.emitEditPost = this.emitEditPost.bind(this); + this.addEditPostListener = this.addEditPostListener.bind(this); + this.removeEditPostListener = this.removeEditPostListener.bind(this); + this.getCurrentUsersLatestPost = this.getCurrentUsersLatestPost.bind(this); } emitChange() { this.emit(CHANGE_EVENT); @@ -148,6 +154,18 @@ class PostStoreClass extends EventEmitter { this.removeListener(ADD_MENTION_EVENT, callback); } + emitEditPost(post) { + this.emit(EDIT_POST_EVENT, post); + } + + addEditPostListener(callback) { + this.on(EDIT_POST_EVENT, callback); + } + + removeEditPostListener(callback) { + this.removeListener(EDIT_POST_EVENT, callback); + } + getCurrentPosts() { var currentId = ChannelStore.getCurrentId(); @@ -212,6 +230,22 @@ class PostStoreClass extends EventEmitter { getPosts(channelId) { return BrowserStore.getItem('posts_' + channelId); } + getCurrentUsersLatestPost(channelId) { + const userId = UserStore.getCurrentId(); + var postList = makePostListNonNull(this.getPosts(channelId)); + var i = 0; + var len = postList.order.length; + var lastPost = null; + + for (i; i < len; i++) { + if (postList.posts[postList.order[i]].user_id === userId) { + lastPost = postList.posts[postList.order[i]]; + break; + } + } + + return lastPost; + } storePost(post) { this.pStorePost(post); this.emitChange(); @@ -446,6 +480,9 @@ PostStore.dispatchToken = AppDispatcher.register(function registry(payload) { case ActionTypes.RECIEVED_ADD_MENTION: PostStore.emitAddMention(action.id, action.username); break; + case ActionTypes.RECIEVED_EDIT_POST: + PostStore.emitEditPost(action); + break; default: } }); diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index cee2ec114..b8200db54 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -17,6 +17,7 @@ module.exports = { RECIEVED_POSTS: null, RECIEVED_POST: null, + RECIEVED_EDIT_POST: null, RECIEVED_SEARCH: null, RECIEVED_POST_SELECTED: null, RECIEVED_MENTION_DATA: null, @@ -289,5 +290,14 @@ module.exports = { ], Preferences: { CATEGORY_DIRECT_CHANNEL_SHOW: 'direct_channel_show' + }, + KeyCodes: { + UP: 38, + DOWN: 40, + LEFT: 37, + RIGHT: 39, + BACKSPACE: 8, + ENTER: 13, + ESCAPE: 27 } }; |