Commit c429d1cb authored by Jaden DIEFENBAUGH's avatar Jaden DIEFENBAUGH

fix webworkers with webpack4, add fuzzy search bar for objs, closes #67

parent d82e0d8c
......@@ -24,6 +24,7 @@ import { pluralize } from '@helpers/beat.js';
import EntityListContainer from './EntityList.jsx';
import NewEntityModal from './NewEntityModal.jsx';
import EntityDetailContainer from './EntityDetail.jsx';
import SearchBar from './SearchBar.jsx';
type Props = {
entity: BeatEntity,
......@@ -54,6 +55,9 @@ class EntityHome extends React.Component<Props, State> {
<Col>
<div className='d-flex'>
<h3>{ pluralize(this.props.entity) }</h3>
<SearchBar
entity={this.props.entity}
/>
<div className='ml-auto'>
<Button outline color='success' onClick={this.toggleNew}>New</Button>
<NewEntityModal
......
// @flow
import * as React from 'react';
import {
Container,
Row,
Col,
Badge,
Dropdown, DropdownMenu, DropdownItem, DropdownToggle,
Input,
Button,
} from 'reactstrap';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import * as Selectors from '@store/selectors.js';
import { pluralize } from '@helpers/beat';
import type { BeatEntity, BeatObject } from '@helpers/beat';
import SearchWorker from '@helpers/search.worker.js';
type Props = {
entity: BeatEntity,
data: BeatObject[],
};
type State = {
searchResults: BeatObject[],
resultsOpen: boolean,
};
class SearchBar extends React.PureComponent<Props, State> {
constructor(props: Props){
super(props);
}
state = {
searchResults: [],
resultsOpen: false,
}
searchWorker = null;
componentDidMount = () => {
this.searchWorker = new SearchWorker();
this.searchWorker.onmessage = (m) => {
this.setState(prevState => ({
searchResults: m.data.slice(0, 5),
resultsOpen: m.data.length > 0,
}));
};
this.updateFuseInstance();
}
componentWillReceiveProps = (nextProps: Props) => {
this.updateFuseInstance(nextProps.data);
}
updateFuseInstance = (data: BeatObject[] = this.props.data) => {
if(!this.searchWorker)
throw new Error(`searchWorker is not instantiated!`);
this.searchWorker.postMessage(
{
type: 'dataChanged',
payload: {
data,
options: {
shouldSort: true,
tokenize: true,
threshold: 0.6,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: ['name', 'contents.description', 'contents.#description'],
}
}
}
);
}
search = (str: string) => {
if(!this.searchWorker)
throw new Error(`searchWorker is not instantiated!`);
this.searchWorker.postMessage(
{
type: 'search',
payload: str
}
);
}
toggleResults = (val: boolean = !this.state.resultsOpen) => {
this.setState({ resultsOpen: val });
};
render = () => {
return (
<Dropdown
isOpen={this.state.resultsOpen}
toggle={e => this.toggleResults(false)}
style={{flex: 1}}
className='ml-2 mr-2'
>
<DropdownToggle
tag='span'
>
<Input
onChange={e => {
this.search(e.target.value);
}}
placeholder={`Search ${ pluralize(this.props.entity) }...`}
/>
</DropdownToggle>
<DropdownMenu>
{
this.state.searchResults.map((r, i) =>
<DropdownItem
tag={Link}
to={`/${ this.props.entity }/${ r.name }`}
key={i}
>
{ r.name }
{' '}
<small className='text-muted'>
{ r.contents.description || r.contents['#description'] || '' }
</small>
</DropdownItem>
)
}
</DropdownMenu>
</Dropdown>
);
}
}
const mapStateToProps = (state, ownProps) => ({
data: Selectors[`${ ownProps.entity }Get`](state),
});
export default connect(mapStateToProps)(SearchBar);
......@@ -24,7 +24,8 @@ module.exports = {
filename: '[name].js',
// output in './dist/'
path: dist,
publicPath: '/'
publicPath: '/',
globalObject: 'this',
},
module: {
rules: [
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment