Search improves (#67)
* ESC should go back from search using direct onKeyDown here as react-keydown does not trigger within an input * Addressable search urls
This commit is contained in:
@ -79,6 +79,7 @@ render(
|
|||||||
<Route exact path="/d/:id/new" component={DocumentNewChild} />
|
<Route exact path="/d/:id/new" component={DocumentNewChild} />
|
||||||
|
|
||||||
<Route exact path="/search" component={Search} />
|
<Route exact path="/search" component={Search} />
|
||||||
|
<Route exact path="/search/:query" component={Search} />
|
||||||
<Route exact path="/settings" component={Settings} />
|
<Route exact path="/settings" component={Settings} />
|
||||||
|
|
||||||
<Route exact path="/auth/slack" component={SlackAuth} />
|
<Route exact path="/auth/slack" component={SlackAuth} />
|
||||||
|
@ -3,6 +3,8 @@ import React from 'react';
|
|||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { Flex } from 'reflexbox';
|
import { Flex } from 'reflexbox';
|
||||||
|
import { withRouter } from 'react-router';
|
||||||
|
import { searchUrl } from 'utils/routeHelpers';
|
||||||
|
|
||||||
import SearchField from './components/SearchField';
|
import SearchField from './components/SearchField';
|
||||||
import styles from './Search.scss';
|
import styles from './Search.scss';
|
||||||
@ -13,6 +15,8 @@ import CenteredContent from 'components/CenteredContent';
|
|||||||
import DocumentPreview from 'components/DocumentPreview';
|
import DocumentPreview from 'components/DocumentPreview';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
history: Object,
|
||||||
|
match: Object,
|
||||||
notFound: ?boolean,
|
notFound: ?boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,12 +27,31 @@ type Props = {
|
|||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.store = new SearchStore();
|
this.store = new SearchStore();
|
||||||
|
this.updateSearchResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (prevProps.match.params.query !== this.props.match.params.query) {
|
||||||
|
this.updateSearchResults();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleKeyDown = ev => {
|
||||||
|
if (ev.which === 27) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.props.history.goBack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateSearchResults = _.debounce(() => {
|
||||||
|
this.store.search(this.props.match.params.query);
|
||||||
|
}, 250);
|
||||||
|
|
||||||
|
updateQuery = query => {
|
||||||
|
this.props.history.replace(searchUrl(query));
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const search = _.debounce(searchTerm => {
|
|
||||||
this.store.search(searchTerm);
|
|
||||||
}, 250);
|
|
||||||
const title = <Title content="Search" />;
|
const title = <Title content="Search" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -55,15 +78,13 @@ type Props = {
|
|||||||
/>
|
/>
|
||||||
<SearchField
|
<SearchField
|
||||||
searchTerm={this.store.searchTerm}
|
searchTerm={this.store.searchTerm}
|
||||||
onChange={search}
|
onKeyDown={this.handleKeyDown}
|
||||||
|
onChange={this.updateQuery}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
{this.store.documents &&
|
{this.store.documents.map(document => (
|
||||||
this.store.documents.map(document => {
|
<DocumentPreview key={document.id} document={document} />
|
||||||
return (
|
))}
|
||||||
<DocumentPreview key={document.id} document={document} />
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</CenteredContent>
|
</CenteredContent>
|
||||||
</Layout>
|
</Layout>
|
||||||
@ -71,4 +92,4 @@ type Props = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Search;
|
export default withRouter(Search);
|
||||||
|
@ -5,7 +5,7 @@ import { client } from 'utils/ApiClient';
|
|||||||
import type { Document } from 'types';
|
import type { Document } from 'types';
|
||||||
|
|
||||||
class SearchStore {
|
class SearchStore {
|
||||||
@observable documents: ?(Document[]);
|
@observable documents: Array<Document> = [];
|
||||||
@observable searchTerm: ?string = null;
|
@observable searchTerm: ?string = null;
|
||||||
|
|
||||||
@observable isFetching = false;
|
@observable isFetching = false;
|
||||||
@ -28,7 +28,7 @@ class SearchStore {
|
|||||||
console.error('Something went wrong');
|
console.error('Something went wrong');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.documents = null;
|
this.documents = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isFetching = false;
|
this.isFetching = false;
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React, { PropTypes } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { observer } from 'mobx-react';
|
|
||||||
|
|
||||||
import styles from './SearchField.scss';
|
import styles from './SearchField.scss';
|
||||||
|
|
||||||
@observer class SearchField extends React.Component {
|
class SearchField extends Component {
|
||||||
static propTypes = {
|
props: {
|
||||||
onChange: PropTypes.func,
|
onChange: Function,
|
||||||
};
|
};
|
||||||
|
|
||||||
onChange = (event: SyntheticEvent) => {
|
handleChange = (event: SyntheticEvent) => {
|
||||||
event.currentTarget.value && this.props.onChange(event.currentTarget.value);
|
event.currentTarget.value && this.props.onChange(event.currentTarget.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17,7 +15,8 @@ import styles from './SearchField.scss';
|
|||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<input
|
<input
|
||||||
onChange={this.onChange}
|
{...this.props}
|
||||||
|
onChange={this.handleChange}
|
||||||
className={styles.field}
|
className={styles.field}
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
autoFocus
|
autoFocus
|
||||||
|
13
frontend/utils/routeHelpers.js
Normal file
13
frontend/utils/routeHelpers.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
export function homeUrl() {
|
||||||
|
return '/dashboard';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function newCollectionUrl() {
|
||||||
|
return '/collections/new';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function searchUrl(query: string) {
|
||||||
|
return `/search/${query}`;
|
||||||
|
}
|
Reference in New Issue
Block a user