mon-entreprise/source/components/SearchBar.js

118 lines
2.7 KiB
JavaScript

import { encodeRuleName } from 'Engine/rules.js'
import Fuse from 'fuse.js'
import { sortBy, pick } from 'ramda'
import React from 'react'
import Highlighter from 'react-highlight-words'
import { withNamespaces } from 'react-i18next'
import { Link, Redirect } from 'react-router-dom'
import Select from 'react-select'
import 'react-select/dist/react-select.css'
import { capitalise0 } from '../utils'
class SearchBar extends React.Component {
componentDidMount() {
this.inputElement.focus()
}
UNSAFE_componentWillMount() {
let { rules } = this.props
var options = {
keys: [
{
name: 'name',
weight: 0.3
},
{
name: 'title',
weight: 0.3
},
{
name: 'espace',
weight: 0.2
},
{
name: 'description',
weight: 0.2
}
]
}
this.fuse = new Fuse(
rules.map(pick(['title', 'espace', 'description', 'name', 'dottedName'])),
options
)
}
state = {
selectedOption: null,
inputValue: null
}
handleChange = selectedOption => {
this.setState({ selectedOption })
}
renderOption = ({ title, dottedName }) => (
<span>
<Highlighter
searchWords={[this.state.inputValue]}
textToHighlight={title}
/>
<span style={{ opacity: 0.6, fontSize: '75%', marginLeft: '.6em' }}>
<Highlighter
searchWords={[this.state.inputValue]}
textToHighlight={dottedName}
/>
</span>
</span>
)
filterOptions = (options, filter) => this.fuse.search(filter)
render() {
let { i18n, rules } = this.props,
{ selectedOption } = this.state
if (selectedOption != null) {
this.props.finally && this.props.finally()
return (
<Redirect
to={'../règle/' + encodeRuleName(selectedOption.dottedName)}
/>
)
}
return (
<>
<Select
value={selectedOption && selectedOption.dottedName}
onChange={this.handleChange}
onInputChange={inputValue => this.setState({ inputValue })}
valueKey="dottedName"
labelKey="title"
options={rules}
filterOptions={this.filterOptions}
optionRenderer={this.renderOption}
placeholder={i18n.t('Entrez des mots clefs ici')}
noResultsText={i18n.t('noresults', {
defaultValue: "Nous n'avons rien trouvé…"
})}
ref={el => {
this.inputElement = el
}}
/>
{this.props.showDefaultList && !this.state.inputValue && (
<ul>
{sortBy(rule => rule.title, rules).map(rule => (
<li key={rule.dottedName}>
<Link
to={
this.props.rulePagesBasePath +
'/' +
encodeRuleName(rule.name)
}>
{rule.title || capitalise0(rule.name)}
</Link>
</li>
))}
</ul>
)}
</>
)
}
}
export default withNamespaces()(SearchBar)