From 0c449ba5c98b4200ac255e2e6b70b754452a861e Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 1 Dec 2015 10:54:53 -0500 Subject: Replaced CommandList with the new suggestion components --- web/react/components/command_list.jsx | 99 -------------------------- web/react/components/command_provider.jsx | 68 ++++++++++++++++++ web/react/components/textbox.jsx | 45 +----------- web/react/stores/suggestion_store.jsx | 10 +-- web/sass-files/sass/partials/_command-box.scss | 6 +- 5 files changed, 82 insertions(+), 146 deletions(-) delete mode 100644 web/react/components/command_list.jsx create mode 100644 web/react/components/command_provider.jsx diff --git a/web/react/components/command_list.jsx b/web/react/components/command_list.jsx deleted file mode 100644 index 7fc0f79cf..000000000 --- a/web/react/components/command_list.jsx +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import * as client from '../utils/client.jsx'; - -export default class CommandList extends React.Component { - constructor(props) { - super(props); - - this.handleClick = this.handleClick.bind(this); - this.addFirstCommand = this.addFirstCommand.bind(this); - this.isEmpty = this.isEmpty.bind(this); - this.getSuggestedCommands = this.getSuggestedCommands.bind(this); - - this.state = { - suggestions: [], - cmd: '' - }; - } - - handleClick(i) { - this.props.addCommand(this.state.suggestions[i].suggestion); - this.setState({suggestions: [], cmd: ''}); - } - - addFirstCommand() { - if (this.state.suggestions.length === 0) { - return; - } - this.handleClick(0); - } - - isEmpty() { - return this.state.suggestions.length === 0; - } - - getSuggestedCommands(cmd) { - if (!cmd || cmd.charAt(0) !== '/') { - this.setState({suggestions: [], cmd: ''}); - return; - } - - client.executeCommand( - this.props.channelId, - cmd, - true, - function success(data) { - if (data.suggestions.length === 1 && data.suggestions[0].suggestion === cmd) { - data.suggestions = []; - } - this.setState({suggestions: data.suggestions, cmd: cmd}); - }.bind(this), - function fail() { - } - ); - } - - render() { - if (this.state.suggestions.length === 0) { - return (
); - } - - var suggestions = []; - - for (var i = 0; i < this.state.suggestions.length; i++) { - if (this.state.suggestions[i].suggestion !== this.state.cmd) { - suggestions.push( -
-
{this.state.suggestions[i].suggestion}
-
{this.state.suggestions[i].description}
-
- ); - } - } - - return ( -
- {suggestions} -
- ); - } -} - -CommandList.defaultProps = { - channelId: null -}; - -CommandList.propTypes = { - addCommand: React.PropTypes.func, - channelId: React.PropTypes.string -}; diff --git a/web/react/components/command_provider.jsx b/web/react/components/command_provider.jsx new file mode 100644 index 000000000..0526e09b1 --- /dev/null +++ b/web/react/components/command_provider.jsx @@ -0,0 +1,68 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; +import * as Client from '../utils/client.jsx'; +import Constants from '../utils/constants.jsx'; +import SuggestionStore from '../stores/suggestion_store.jsx'; + +class CommandSuggestion extends React.Component { + render() { + const {item, isSelection, onClick} = this.props; + + let className = 'command-name'; + if (isSelection) { + className += ' command--selected'; + } + + return ( +
+
+ {item.suggestion} +
+
+ {item.description} +
+
+ ); + } +} + +CommandSuggestion.propTypes = { + item: React.PropTypes.object.isRequired, + isSelection: React.PropTypes.bool, + onClick: React.PropTypes.func +}; + +export default class CommandProvider { + handlePretextChanged(suggestionId, pretext) { + if (pretext.startsWith('/')) { + SuggestionStore.setMatchedPretext(suggestionId, pretext); + + Client.executeCommand( + '', + pretext, + true, + (data) => { + this.handleCommandsReceived(suggestionId, pretext, data.suggestions); + } + ); + } + } + + handleCommandsReceived(suggestionId, matchedPretext, commandSuggestions) { + const terms = commandSuggestions.map(({suggestion}) => suggestion); + + AppDispatcher.handleServerAction({ + type: Constants.ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS, + id: suggestionId, + matchedPretext, + terms, + items: commandSuggestions, + component: CommandSuggestion + }); + } +} diff --git a/web/react/components/textbox.jsx b/web/react/components/textbox.jsx index fde8f64d3..b50575fc1 100644 --- a/web/react/components/textbox.jsx +++ b/web/react/components/textbox.jsx @@ -1,8 +1,8 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import CommandList from './command_list.jsx'; import AtMentionProvider from './at_mention_provider.jsx'; +import CommandProvider from './command_provider.jsx'; import SuggestionList from './suggestion_list.jsx'; import SuggestionBox from './suggestion_box.jsx'; import ErrorStore from '../stores/error_store.jsx'; @@ -10,7 +10,6 @@ import ErrorStore from '../stores/error_store.jsx'; import * as TextFormatting from '../utils/text_formatting.jsx'; import * as Utils from '../utils/utils.jsx'; import Constants from '../utils/constants.jsx'; -const KeyCodes = Constants.KeyCodes; const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES; export default class Textbox extends React.Component { @@ -21,8 +20,6 @@ export default class Textbox extends React.Component { this.onRecievedError = this.onRecievedError.bind(this); this.handleKeyPress = this.handleKeyPress.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); - this.handleBackspace = this.handleBackspace.bind(this); - this.addCommand = this.addCommand.bind(this); this.resize = this.resize.bind(this); this.handleFocus = this.handleFocus.bind(this); this.handleBlur = this.handleBlur.bind(this); @@ -32,9 +29,7 @@ export default class Textbox extends React.Component { connection: '' }; - this.caret = -1; - - this.suggestionProviders = [new AtMentionProvider()]; + this.suggestionProviders = [new AtMentionProvider(), new CommandProvider()]; } getStateFromStores() { @@ -68,48 +63,19 @@ export default class Textbox extends React.Component { } componentDidUpdate() { - if (this.caret >= 0) { - Utils.setCaretPosition(this.refs.message.getTextbox(), this.caret); - this.caret = -1; - } this.resize(); } - componentWillReceiveProps(nextProps) { - this.refs.commands.getSuggestedCommands(nextProps.messageText); - } - handleKeyPress(e) { - const text = this.refs.message.getTextbox().value; - - if (!this.refs.commands.isEmpty() && text.indexOf('/') === 0 && e.which === KeyCodes.ENTER) { - this.refs.commands.addFirstCommand(); - e.preventDefault(); - return; - } - this.props.onKeyPress(e); } handleKeyDown(e) { - if (e.keyCode === KeyCodes.BACKSPACE) { - this.handleBackspace(e); - } else if (this.props.onKeyDown) { + if (this.props.onKeyDown) { this.props.onKeyDown(e); } } - handleBackspace() { - const text = this.refs.message.getTextbox().value; - if (text.indexOf('/') === 0) { - this.refs.commands.getSuggestedCommands(text.substring(0, text.length - 1)); - } - } - - addCommand(cmd) { - this.props.onUserInput(cmd); - } - resize() { const e = this.refs.message.getTextbox(); const w = ReactDOM.findDOMNode(this.refs.wrapper); @@ -193,11 +159,6 @@ export default class Textbox extends React.Component { ref='wrapper' className='textarea-wrapper' > -