let requestTree = (query, baseComponent, dispatch) => {
dispatch(startFetching());
- return getTree(baseComponent.key, { q: query, s: 'qualifier,name' })
+
+ const params = { s: 'qualifier,name', qualifiers: 'BRC,FIL,UTS' };
+
+ if (query) {
+ params.q = query;
+ }
+
+ return getTree(baseComponent.key, params)
.then(r => dispatch(searchAction(r.components)))
.then(() => dispatch(stopFetching()));
};
export function search (query, baseComponent) {
return dispatch => {
dispatch(updateQueryAction(query));
- if (query) {
+ if (query != null) {
requestTree(query, baseComponent, dispatch);
} else {
dispatch(searchAction(null));
import Breadcrumbs from './Breadcrumbs';
import SourceViewer from './SourceViewer';
import Search from './Search';
-import { initComponent, browse } from '../actions';
+import { initComponent, browse, search } from '../actions';
import { translate } from '../../../helpers/l10n';
componentDidMount () {
const { dispatch, component, routing } = this.props;
const selectedKey = (routing.path && decodeURIComponent(routing.path.substr(1))) || component.key;
+
dispatch(initComponent(component.key, component.breadcrumbs))
.then(() => dispatch(browse(selectedKey)));
+
+ this.handleKeyDown = this.handleKeyDown.bind(this);
+ this.attachShortcuts();
}
componentWillReceiveProps (nextProps) {
}
}
+ componentWillUnmount () {
+ this.removeShortcuts();
+ }
+
+ attachShortcuts () {
+ window.addEventListener('keyup', this.handleKeyDown);
+ }
+
+ removeShortcuts () {
+ window.removeEventListener('keyup', this.handleKeyDown);
+ }
+
handleBrowse (component) {
const { dispatch } = this.props;
dispatch(browse(component.key));
}
+ handleKeyDown (e) {
+ const { dispatch, component, searchQuery } = this.props;
+
+ // "t" key
+ if (e.keyCode === 84 && searchQuery == null) {
+ dispatch(search('', component));
+ }
+ }
+
render () {
const {
fetching,
const shouldShowSearchResults = !!searchResults;
const shouldShowSourceViewer = !!sourceViewer;
const shouldShowComponents = !shouldShowSearchResults && !shouldShowSourceViewer && components;
- const shouldShowBreadcrumbs = !shouldShowSearchResults && Array.isArray(breadcrumbs) && breadcrumbs.length > 1;
+ const shouldShowBreadcrumbs = !shouldShowSearchResults && Array.isArray(breadcrumbs) && breadcrumbs.length > 1;
const componentsClassName = classNames('spacer-top', { 'new-loading': fetching });
<i className="spinner"/>
</div>
- <Search component={this.props.component}/>
+ <div className="page-actions">
+ <Search component={this.props.component}/>
+ </div>
</header>
{errorMessage && (
import { connect } from 'react-redux';
import { search } from '../actions';
+import { translate } from '../../../helpers/l10n';
class Search extends Component {
componentDidMount () {
- this.refs.input.focus();
+ this.focusSearchInput();
+ }
+
+ componentDidUpdate () {
+ this.focusSearchInput();
+ }
+
+ focusSearchInput () {
+ if (this.refs.input) {
+ this.refs.input.focus();
+ }
}
handleSearch (e) {
e.preventDefault();
const { dispatch, component } = this.props;
- const query = this.refs.input.value;
+ const query = this.refs.input ? this.refs.input.value : '';
dispatch(search(query, component));
}
+ handleStopSearch (e) {
+ e.preventDefault();
+ const { dispatch } = this.props;
+ dispatch(search(null));
+ }
+
+ handleKeyDown (e) {
+ const { dispatch } = this.props;
+
+ // "escape" key
+ if (e.keyCode === 27) {
+ dispatch(search(null));
+ }
+ }
+
render () {
const { query } = this.props;
+ const hasQuery = query != null;
return (
<form
onSubmit={this.handleSearch.bind(this)}
className="search-box code-search-box">
- <button className="search-box-submit button-clean">
- <i className="icon-search"></i>
- </button>
- <input
- ref="input"
- onChange={this.handleSearch.bind(this)}
- value={query}
- className="search-box-input"
- type="search"
- name="q"
- placeholder="Search"
- maxLength="100"
- autoComplete="off"/>
+ {hasQuery && (
+ <input
+ ref="input"
+ onChange={this.handleSearch.bind(this)}
+ onKeyDown={this.handleKeyDown.bind(this)}
+ value={query}
+ className="search-box-input"
+ type="search"
+ name="q"
+ placeholder="Search"
+ maxLength="100"
+ autoComplete="off"
+ style={{ visibility: hasQuery ? 'visible': 'hidden' }}/>
+ )}
+ {!hasQuery && (
+ <button className="search-box-submit">
+ {translate('search_verb')}
+ </button>
+ )}
+ {hasQuery && (
+ <button
+ className="search-box-submit"
+ onClick={this.handleStopSearch.bind(this)}>
+ {translate('cancel')}
+ </button>
+ )}
</form>
);
}
breadcrumbs: null,
sourceViewer: null,
searchResults: null,
- searchQuery: '',
+ searchQuery: null,
coverageMetric: null,
baseBreadcrumbs: [],
errorMessage: null
breadcrumbs,
sourceViewer,
searchResults: null,
- searchQuery: '',
+ searchQuery: null,
errorMessage: null
};
case SEARCH:
</ul>
</div>
- <h3 class="shortcuts-section-title">{{t 'shortcuts.section.rules'}}</h3>
+ <div class="spacer-bottom">
+ <h3 class="shortcuts-section-title">{{t 'shortcuts.section.rules'}}</h3>
+ <ul class="shortcuts-list">
+ <li><span class="shortcut-button">↑</span> <span
+ class="shortcut-button">↓</span> {{t 'shortcuts.section.rules.navigate_between_rules'}}</li>
+ <li><span class="shortcut-button">→</span> {{t 'shortcuts.section.rules.open_details'}}</li>
+ <li><span class="shortcut-button">←</span> {{t 'shortcuts.section.rules.return_to_list'}}</li>
+ <li><span class="shortcut-button">a</span> {{t 'shortcuts.section.rules.activate'}}</li>
+ <li><span class="shortcut-button">d</span> {{t 'shortcuts.section.rules.deactivate'}}</li>
+ </ul>
+ </div>
+
+ <h3 class="shortcuts-section-title">{{t 'shortcuts.section.code'}}</h3>
<ul class="shortcuts-list">
- <li><span class="shortcut-button">↑</span> <span
- class="shortcut-button">↓</span> {{t 'shortcuts.section.rules.navigate_between_rules'}}</li>
- <li><span class="shortcut-button">→</span> {{t 'shortcuts.section.rules.open_details'}}</li>
- <li><span class="shortcut-button">←</span> {{t 'shortcuts.section.rules.return_to_list'}}</li>
- <li><span class="shortcut-button">a</span> {{t 'shortcuts.section.rules.activate'}}</li>
- <li><span class="shortcut-button">d</span> {{t 'shortcuts.section.rules.deactivate'}}</li>
+ <li><span class="shortcut-button">t</span> {{t 'shortcuts.section.code.search'}}</li>
</ul>
</div>
it('should be reset', () => {
const stateBefore = Object.assign({}, initialState, { searchQuery: 'query' });
expect(current(stateBefore, browseAction(exampleComponent)).searchQuery)
- .to.equal('');
+ .to.be.null;
});
});
describe('errorMessage', () => {