Search command is now built into findbar
This commit is contained in:
parent
3b316f1034
commit
26a51807f6
@ -47,9 +47,21 @@
|
|||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.command .faded {
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: lighter;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
.highlightedCommand {
|
.highlightedCommand {
|
||||||
color: white;
|
color: white;
|
||||||
background: hsl(200, 50%, 50%);
|
background: hsl(200, 50%, 50%);
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.highlightedCommand .faded {
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: lighter;
|
||||||
|
color: #ddd;
|
||||||
|
}
|
||||||
|
@ -3,12 +3,16 @@ import fuzzy from 'fuzzy';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { runCommand } from '../actions/findbar';
|
import { runCommand } from '../actions/findbar';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { Icon } from '../components/UI';
|
||||||
import styles from './FindBar.css';
|
import styles from './FindBar.css';
|
||||||
|
|
||||||
|
const SEARCH = 'SEARCH';
|
||||||
|
|
||||||
class FindBar extends Component {
|
class FindBar extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this._compiledCommands = {};
|
this._compiledCommands = [];
|
||||||
|
this._searchCommand = { search: true, regexp:`(?:${SEARCH})?(.*)`, param:{ name:'searchTerm', display:'' } };
|
||||||
this.state = {
|
this.state = {
|
||||||
value: '',
|
value: '',
|
||||||
placeholder: '',
|
placeholder: '',
|
||||||
@ -66,12 +70,6 @@ class FindBar extends Component {
|
|||||||
param = { name:match[1], display:match[2] || this._camelCaseToSpace(match[1]) };
|
param = { name:match[1], display:match[2] || this._camelCaseToSpace(match[1]) };
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(Object.assign({}, command, {
|
|
||||||
regexp,
|
|
||||||
token,
|
|
||||||
param
|
|
||||||
}));
|
|
||||||
|
|
||||||
return Object.assign({}, command, {
|
return Object.assign({}, command, {
|
||||||
regexp,
|
regexp,
|
||||||
token,
|
token,
|
||||||
@ -84,17 +82,25 @@ class FindBar extends Component {
|
|||||||
matchCommand() {
|
matchCommand() {
|
||||||
const string = this.state.activeScope ? this.state.activeScope + this.state.value : this.state.value;
|
const string = this.state.activeScope ? this.state.activeScope + this.state.value : this.state.value;
|
||||||
let match;
|
let match;
|
||||||
const command = this._compiledCommands.find(command => {
|
let command = this._compiledCommands.find(command => {
|
||||||
match = string.match(RegExp(`^${command.regexp}`, 'i'));
|
match = string.match(RegExp(`^${command.regexp}`, 'i'));
|
||||||
return match;
|
return match;
|
||||||
});
|
});
|
||||||
|
|
||||||
const paramName = command.param ? command.param.name : null;
|
// If no command was found, trigger a search command
|
||||||
const enteredParamValue = command.param && match[1] ? match[1].trim() : null;
|
|
||||||
|
|
||||||
if (!command) {
|
if (!command) {
|
||||||
// No matched command
|
command = this._searchCommand;
|
||||||
return null;
|
match = string.match(RegExp(`^${this._searchCommand.regexp}`, 'i'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const paramName = command && command.param ? command.param.name : null;
|
||||||
|
const enteredParamValue = command && command.param && match[1] ? match[1].trim() : null;
|
||||||
|
|
||||||
|
if (command.search) {
|
||||||
|
this.setState({
|
||||||
|
activeScope: SEARCH
|
||||||
|
});
|
||||||
|
this.props.dispatch(runCommand('search', { searchTerm: enteredParamValue }));
|
||||||
} else if (command.param && !enteredParamValue) {
|
} else if (command.param && !enteredParamValue) {
|
||||||
// Partial Match
|
// Partial Match
|
||||||
// Command was partially matched: It requires a param, but param wasn't entered
|
// Command was partially matched: It requires a param, but param wasn't entered
|
||||||
@ -128,12 +134,23 @@ class FindBar extends Component {
|
|||||||
// Memoized version
|
// Memoized version
|
||||||
_getSuggestions(value, scope, commands) {
|
_getSuggestions(value, scope, commands) {
|
||||||
if (scope) return []; // No autocomplete for scoped input
|
if (scope) return []; // No autocomplete for scoped input
|
||||||
|
|
||||||
const results = fuzzy.filter(value, commands, {
|
const results = fuzzy.filter(value, commands, {
|
||||||
//pre: '<strong>',
|
pre: '<strong>',
|
||||||
//post: '</strong>',
|
post: '</strong>',
|
||||||
extract: el => el.token
|
extract: el => el.token
|
||||||
});
|
});
|
||||||
return results.slice(0, 5).map(result => result.original);
|
|
||||||
|
let returnResults;
|
||||||
|
if (value.length > 0) {
|
||||||
|
returnResults = results.slice(0, 4).map(result => Object.assign({}, result.original, { string:result.string }));
|
||||||
|
returnResults.push(this._searchCommand);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
returnResults = results.slice(0, 5).map(result => Object.assign({}, result.original, { string:result.string }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown(event) {
|
handleKeyDown(event) {
|
||||||
@ -172,7 +189,7 @@ class FindBar extends Component {
|
|||||||
isOpen: false,
|
isOpen: false,
|
||||||
highlightedIndex: 0
|
highlightedIndex: 0
|
||||||
};
|
};
|
||||||
if (command) {
|
if (command && !command.search) {
|
||||||
newState.value = command.token;
|
newState.value = command.token;
|
||||||
}
|
}
|
||||||
this.setState(newState, () => {
|
this.setState(newState, () => {
|
||||||
@ -228,11 +245,14 @@ class FindBar extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectCommandFromMouse(command) {
|
selectCommandFromMouse(command) {
|
||||||
this.setState({
|
const newState = {
|
||||||
value: command.token,
|
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
highlightedIndex: 0
|
highlightedIndex: 0
|
||||||
}, () => {
|
};
|
||||||
|
if (command && !command.search) {
|
||||||
|
newState.value = command.token;
|
||||||
|
}
|
||||||
|
this.setState(newState, () => {
|
||||||
this.matchCommand();
|
this.matchCommand();
|
||||||
this._input.focus();
|
this._input.focus();
|
||||||
this.setIgnoreBlur(false);
|
this.setIgnoreBlur(false);
|
||||||
@ -245,6 +265,7 @@ class FindBar extends Component {
|
|||||||
|
|
||||||
renderMenu() {
|
renderMenu() {
|
||||||
const commands = this.getSuggestions().map((command, index) => {
|
const commands = this.getSuggestions().map((command, index) => {
|
||||||
|
if (!command.search) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={this.state.highlightedIndex === index ? styles.highlightedCommand : styles.command}
|
className={this.state.highlightedIndex === index ? styles.highlightedCommand : styles.command}
|
||||||
@ -252,17 +273,36 @@ class FindBar extends Component {
|
|||||||
onMouseDown={() => this.setIgnoreBlur(true)}
|
onMouseDown={() => this.setIgnoreBlur(true)}
|
||||||
onMouseEnter={() => this.highlightCommandFromMouse(index)}
|
onMouseEnter={() => this.highlightCommandFromMouse(index)}
|
||||||
onClick={() => this.selectCommandFromMouse(command)}
|
onClick={() => this.selectCommandFromMouse(command)}
|
||||||
ref={`command-${index}`}
|
>
|
||||||
>{command.token}</div>
|
<Icon type="right-open-mini"/>
|
||||||
|
<span dangerouslySetInnerHTML={{__html: command.string}} />
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={this.state.highlightedIndex === index ? styles.highlightedCommand : styles.command}
|
||||||
|
key='builtin-search'
|
||||||
|
onMouseDown={() => this.setIgnoreBlur(true)}
|
||||||
|
onMouseEnter={() => this.highlightCommandFromMouse(index)}
|
||||||
|
onClick={() => this.selectCommandFromMouse(command)}
|
||||||
|
>
|
||||||
|
<span className={styles.faded}><Icon type="search"/> Search for: </span>{this.state.value}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return commands.length > 0 ? <div className={styles.menu} children={commands} /> : null;
|
return commands.length > 0 ? <div className={styles.menu} children={commands} /> : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderActiveScope() {
|
renderActiveScope() {
|
||||||
|
if (this.state.activeScope === SEARCH) {
|
||||||
|
return <div className={styles.inputScope}><Icon type="search"/> </div>;
|
||||||
|
} else {
|
||||||
return <div className={styles.inputScope}>{this.state.activeScope}</div>;
|
return <div className={styles.inputScope}>{this.state.activeScope}</div>;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const menu = this.state.isOpen && this.renderMenu();
|
const menu = this.state.isOpen && this.renderMenu();
|
||||||
|
@ -10,10 +10,7 @@ const commands = [
|
|||||||
{ pattern: 'Create new FAQ item(:faqName as FAQ item name)' },
|
{ pattern: 'Create new FAQ item(:faqName as FAQ item name)' },
|
||||||
{ pattern: 'Add news item(:headline)' },
|
{ pattern: 'Add news item(:headline)' },
|
||||||
{ pattern: 'Add new User(:userName as User name)' },
|
{ pattern: 'Add new User(:userName as User name)' },
|
||||||
{ pattern: 'Search(:searchTerm as what?)' },
|
|
||||||
{ pattern: 'Go to Settings' },
|
{ pattern: 'Go to Settings' },
|
||||||
{ pattern: 'Find(:seachTerm as what?)' },
|
|
||||||
{ pattern: '(:searchTerm as Find...)', token:'Find' }
|
|
||||||
];
|
];
|
||||||
|
|
||||||
storiesOf('FindBar', module)
|
storiesOf('FindBar', module)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user