Replaced CommandList with the new suggestion components
Этот коммит содержится в:
@@ -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 (<div/>);
|
||||
}
|
||||
|
||||
var suggestions = [];
|
||||
|
||||
for (var i = 0; i < this.state.suggestions.length; i++) {
|
||||
if (this.state.suggestions[i].suggestion !== this.state.cmd) {
|
||||
suggestions.push(
|
||||
<div
|
||||
key={i}
|
||||
className='command-name'
|
||||
onClick={this.handleClick.bind(this, i)}
|
||||
>
|
||||
<div className='command__title'><strong>{this.state.suggestions[i].suggestion}</strong></div>
|
||||
<div className='command__desc'>{this.state.suggestions[i].description}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref='mentionlist'
|
||||
className='command-box'
|
||||
style={{height: (suggestions.length * 56) + 2}}
|
||||
>
|
||||
{suggestions}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CommandList.defaultProps = {
|
||||
channelId: null
|
||||
};
|
||||
|
||||
CommandList.propTypes = {
|
||||
addCommand: React.PropTypes.func,
|
||||
channelId: React.PropTypes.string
|
||||
};
|
||||
68
web/react/components/command_provider.jsx
Обычный файл
68
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 (
|
||||
<div
|
||||
className={className}
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className='command__title'>
|
||||
<string>{item.suggestion}</string>
|
||||
</div>
|
||||
<div className='command__desc'>
|
||||
{item.description}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
>
|
||||
<CommandList
|
||||
ref='commands'
|
||||
addCommand={this.addCommand}
|
||||
channelId={this.props.channelId}
|
||||
/>
|
||||
<SuggestionBox
|
||||
id={this.props.id}
|
||||
ref='message'
|
||||
|
||||
@@ -223,11 +223,13 @@ class SuggestionStore extends EventEmitter {
|
||||
this.emitSuggestionsChanged(id);
|
||||
break;
|
||||
case ActionTypes.SUGGESTION_RECEIVED_SUGGESTIONS:
|
||||
this.setMatchedPretext(id, other.matchedPretext);
|
||||
this.addSuggestions(id, other.terms, other.items, other.componentType);
|
||||
if (other.matchedPretext === this.getMatchedPretext(id)) {
|
||||
// ensure the matched pretext hasn't changed so that we don't receive suggestions for outdated pretext
|
||||
this.addSuggestions(id, other.terms, other.items, other.component);
|
||||
|
||||
this.ensureSelectionExists(id);
|
||||
this.emitSuggestionsChanged(id);
|
||||
this.ensureSelectionExists(id);
|
||||
this.emitSuggestionsChanged(id);
|
||||
}
|
||||
break;
|
||||
case ActionTypes.SUGGESTION_SELECT_NEXT:
|
||||
this.selectNext(id);
|
||||
|
||||
@@ -32,4 +32,8 @@
|
||||
|
||||
.command-desc {
|
||||
color: #a7a8ab;
|
||||
}
|
||||
}
|
||||
|
||||
.command--selected {
|
||||
background-color: #e8eaed;
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user