118 lines
2.7 KiB
JavaScript
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)
|