From 0a1b0d051a1a7d83ad01502f8073d35ee5da95cc Mon Sep 17 00:00:00 2001 From: Nick Frazier Date: Mon, 26 Dec 2016 09:25:50 -0500 Subject: Add error to RHS reply box for messages > 4000 chars, consistent with create post and edit post errors (#4871) * functionality * CSS updates * cleanup * moved message length checks to Textbox component * cleanup --- webapp/components/create_comment.jsx | 33 +++++++++++++++------------------ webapp/components/create_post.jsx | 30 +++++++----------------------- webapp/components/edit_post_modal.jsx | 23 ++++++++--------------- webapp/components/textbox.jsx | 34 ++++++++++++++++++++++++++++++++-- webapp/sass/layout/_sidebar-right.scss | 18 ++++++++++++++++++ webapp/sass/responsive/_mobile.scss | 5 +++++ webapp/sass/responsive/_tablet.scss | 4 ++++ 7 files changed, 89 insertions(+), 58 deletions(-) diff --git a/webapp/components/create_comment.jsx b/webapp/components/create_comment.jsx index 8ecda6777..09ec32b6b 100644 --- a/webapp/components/create_comment.jsx +++ b/webapp/components/create_comment.jsx @@ -55,6 +55,7 @@ export default class CreateComment extends React.Component { this.focusTextbox = this.focusTextbox.bind(this); this.showPostDeletedModal = this.showPostDeletedModal.bind(this); this.hidePostDeletedModal = this.hidePostDeletedModal.bind(this); + this.handlePostError = this.handlePostError.bind(this); PostStore.clearCommentDraftUploads(); MessageHistoryStore.resetHistoryIndex('comment'); @@ -96,6 +97,10 @@ export default class CreateComment extends React.Component { } } + handlePostError(postError) { + this.setState({postError}); + } + handleSubmit(e) { e.preventDefault(); @@ -109,16 +114,11 @@ export default class CreateComment extends React.Component { const message = this.state.message; - if (message.length > Constants.CHARACTER_LIMIT) { - this.setState({ - postError: ( - - ) - }); + if (this.state.postError) { + this.setState({errorClass: 'animation--highlight'}); + setTimeout(() => { + this.setState({errorClass: null}); + }, Constants.ANIMATION_TIMEOUT); return; } @@ -420,7 +420,8 @@ export default class CreateComment extends React.Component { let postError = null; if (this.state.postError) { - postError = ; + const postErrorClass = 'post-error' + (this.state.errorClass ? (' ' + this.state.errorClass) : ''); + postError = ; } let preview = null; @@ -434,11 +435,6 @@ export default class CreateComment extends React.Component { ); } - let postFooterClassName = 'post-create-footer'; - if (postError) { - postFooterClassName += ' has-error'; - } - let uploadsInProgressText = null; if (this.state.uploadsInProgress.length > 0) { uploadsInProgressText = ( @@ -470,6 +466,7 @@ export default class CreateComment extends React.Component { onChange={this.handleChange} onKeyPress={this.commentMsgKeyPress} onKeyDown={this.handleKeyDown} + handlePostError={this.handlePostError} value={this.state.message} onBlur={this.handleBlur} createMessage={Utils.localizeMessage('create_comment.addComment', 'Add a comment...')} @@ -494,7 +491,7 @@ export default class CreateComment extends React.Component { channelId={this.props.channelId} parentId={this.props.rootId} /> -
+
{uploadsInProgressText} - {preview} {postError} + {preview} {serverError}
diff --git a/webapp/components/create_post.jsx b/webapp/components/create_post.jsx index 5346d05ad..8e75b6070 100644 --- a/webapp/components/create_post.jsx +++ b/webapp/components/create_post.jsx @@ -25,7 +25,7 @@ import PreferenceStore from 'stores/preference_store.jsx'; import Constants from 'utils/constants.jsx'; -import {FormattedHTMLMessage, FormattedMessage} from 'react-intl'; +import {FormattedHTMLMessage} from 'react-intl'; import {browserHistory} from 'react-router/es6'; const Preferences = Constants.Preferences; @@ -61,7 +61,7 @@ export default class CreatePost extends React.Component { this.showPostDeletedModal = this.showPostDeletedModal.bind(this); this.hidePostDeletedModal = this.hidePostDeletedModal.bind(this); this.showShortcuts = this.showShortcuts.bind(this); - this.checkMessageLength = this.checkMessageLength.bind(this); + this.handlePostError = this.handlePostError.bind(this); PostStore.clearDraftUploads(); @@ -81,6 +81,10 @@ export default class CreatePost extends React.Component { }; } + handlePostError(postError) { + this.setState({postError}); + } + handleSubmit(e) { e.preventDefault(); @@ -218,25 +222,6 @@ export default class CreatePost extends React.Component { const draft = PostStore.getCurrentDraft(); draft.message = message; PostStore.storeCurrentDraft(draft); - - this.checkMessageLength(message); - } - - checkMessageLength(message) { - if (message.length > Constants.CHARACTER_LIMIT) { - const errorMessage = ( - ); - this.setState({postError: errorMessage}); - } else { - this.setState({postError: null}); - } } handleUploadClick() { @@ -335,8 +320,6 @@ export default class CreatePost extends React.Component { fullWidthTextBox: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.CHANNEL_DISPLAY_MODE, Preferences.CHANNEL_DISPLAY_MODE_DEFAULT) === Preferences.CHANNEL_DISPLAY_MODE_FULL_SCREEN, showTutorialTip: tutorialStep === TutorialSteps.POST_POPOVER }); - - this.checkMessageLength(this.state.message); } componentDidMount() { @@ -543,6 +526,7 @@ export default class CreatePost extends React.Component { onChange={this.handleChange} onKeyPress={this.postMsgKeyPress} onKeyDown={this.handleKeyDown} + handlePostError={this.handlePostError} value={this.state.message} onBlur={this.handleBlur} createMessage={Utils.localizeMessage('create_post.write', 'Write a message...')} diff --git a/webapp/components/edit_post_modal.jsx b/webapp/components/edit_post_modal.jsx index 1617d9f65..5f312170f 100644 --- a/webapp/components/edit_post_modal.jsx +++ b/webapp/components/edit_post_modal.jsx @@ -38,6 +38,7 @@ export default class EditPostModal extends React.Component { this.onModalShown = this.onModalShown.bind(this); this.onModalHide = this.onModalHide.bind(this); this.onModalKeyDown = this.onModalKeyDown.bind(this); + this.handlePostError = this.handlePostError.bind(this); this.state = { editText: '', @@ -52,6 +53,12 @@ export default class EditPostModal extends React.Component { }; } + handlePostError(postError) { + if (this.state.postError !== postError) { + this.setState({postError}); + } + } + handleEdit() { const updatedPost = { message: this.state.editText, @@ -103,21 +110,6 @@ export default class EditPostModal extends React.Component { this.setState({ editText: message }); - - if (message.length > Constants.CHARACTER_LIMIT) { - const errorMessage = ( - ); - this.setState({postError: errorMessage}); - } else { - this.setState({postError: ''}); - } } handleEditKeyPress(e) { @@ -262,6 +254,7 @@ export default class EditPostModal extends React.Component { onChange={this.handleChange} onKeyPress={this.handleEditKeyPress} onKeyDown={this.handleKeyDown} + handlePostError={this.handlePostError} value={this.state.editText} channelId={this.state.channel_id} createMessage={Utils.localizeMessage('edit_post.editPost', 'Edit the post...')} diff --git a/webapp/components/textbox.jsx b/webapp/components/textbox.jsx index b9b000282..1189a51d8 100644 --- a/webapp/components/textbox.jsx +++ b/webapp/components/textbox.jsx @@ -32,6 +32,7 @@ export default class Textbox extends React.Component { this.handleBlur = this.handleBlur.bind(this); this.handleHeightChange = this.handleHeightChange.bind(this); this.showPreview = this.showPreview.bind(this); + this.handleChange = this.handleChange.bind(this); this.state = { connection: '' @@ -51,6 +52,10 @@ export default class Textbox extends React.Component { ErrorStore.addChangeListener(this.onRecievedError); } + componentWillMount() { + this.checkMessageLength(this.props.value); + } + componentWillUnmount() { ErrorStore.removeChangeListener(this.onRecievedError); } @@ -65,6 +70,30 @@ export default class Textbox extends React.Component { } } + handleChange(e) { + this.checkMessageLength(e.target.value); + this.props.onChange(e); + } + + checkMessageLength(message) { + if (this.props.handlePostError) { + if (message.length > Constants.CHARACTER_LIMIT) { + const errorMessage = ( + ); + this.props.handlePostError(errorMessage); + } else { + this.props.handlePostError(null); + } + } + } + handleKeyPress(e) { this.props.onKeyPress(e); } @@ -206,7 +235,7 @@ export default class Textbox extends React.Component { type='textarea' spellCheck='true' placeholder={this.props.createMessage} - onChange={this.props.onChange} + onChange={this.handleChange} onKeyPress={this.handleKeyPress} onKeyDown={this.handleKeyDown} onBlur={this.handleBlur} @@ -257,5 +286,6 @@ Textbox.propTypes = { createMessage: React.PropTypes.string.isRequired, onKeyDown: React.PropTypes.func, onBlur: React.PropTypes.func, - supportsCommands: React.PropTypes.bool.isRequired + supportsCommands: React.PropTypes.bool.isRequired, + handlePostError: React.PropTypes.func }; diff --git a/webapp/sass/layout/_sidebar-right.scss b/webapp/sass/layout/_sidebar-right.scss index 915bb2d09..8d5a1d044 100644 --- a/webapp/sass/layout/_sidebar-right.scss +++ b/webapp/sass/layout/_sidebar-right.scss @@ -59,6 +59,24 @@ form { padding: .5em 15px 0; } + + .post-create-footer { + @include clearfix; + font-size: 13px; + overflow: visible; + position: relative; + clear: both; + + .post-error { + font-weight: normal; + margin-bottom: 0; + display: inline-block; + font-size: .85em; + @include opacity(.55); + position: absolute; + top: -25px; + } + } } .help__format-text { diff --git a/webapp/sass/responsive/_mobile.scss b/webapp/sass/responsive/_mobile.scss index 1dcaacc60..16f0d3851 100644 --- a/webapp/sass/responsive/_mobile.scss +++ b/webapp/sass/responsive/_mobile.scss @@ -1073,6 +1073,11 @@ margin: .5em 0; top: 0; } + + .post-error { + top: 0; + left: 0; + } } } diff --git a/webapp/sass/responsive/_tablet.scss b/webapp/sass/responsive/_tablet.scss index 4de187846..64b8ab6dd 100644 --- a/webapp/sass/responsive/_tablet.scss +++ b/webapp/sass/responsive/_tablet.scss @@ -42,6 +42,10 @@ top: 0; left: 32px; position: relative; + + .sidebar--right & { + left: 0; + } } } -- cgit v1.2.3-1-g7c22