Rework search
This commit is contained in:
		
							parent
							
								
									553e6dd07c
								
							
						
					
					
						commit
						b4046c5957
					
				
					 13 changed files with 352 additions and 265 deletions
				
			
		|  | @ -1,123 +1,67 @@ | |||
| import PureRenderMixin from 'react-addons-pure-render-mixin'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| import Autosuggest from 'react-autosuggest'; | ||||
| import AutosuggestAccountContainer from '../containers/autosuggest_account_container'; | ||||
| import AutosuggestStatusContainer from '../containers/autosuggest_status_container'; | ||||
| import { debounce } from 'react-decoration'; | ||||
| import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; | ||||
| 
 | ||||
| const messages = defineMessages({ | ||||
|   placeholder: { id: 'search.placeholder', defaultMessage: 'Search' } | ||||
| }); | ||||
| 
 | ||||
| const getSuggestionValue = suggestion => suggestion.value; | ||||
| 
 | ||||
| const renderSuggestion = suggestion => { | ||||
|   if (suggestion.type === 'account') { | ||||
|     return <AutosuggestAccountContainer id={suggestion.id} />; | ||||
|   } else if (suggestion.type === 'hashtag') { | ||||
|     return <span>#{suggestion.id}</span>; | ||||
|   } else { | ||||
|     return <AutosuggestStatusContainer id={suggestion.id} />; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| const renderSectionTitle = section => ( | ||||
|   <strong><FormattedMessage id={`search.${section.title}`} defaultMessage={section.title} /></strong> | ||||
| ); | ||||
| 
 | ||||
| const getSectionSuggestions = section => section.items; | ||||
| 
 | ||||
| const outerStyle = { | ||||
|   padding: '10px', | ||||
|   lineHeight: '20px', | ||||
|   position: 'relative' | ||||
| }; | ||||
| 
 | ||||
| const iconStyle = { | ||||
|   position: 'absolute', | ||||
|   top: '18px', | ||||
|   right: '20px', | ||||
|   fontSize: '18px', | ||||
|   pointerEvents: 'none' | ||||
| }; | ||||
| 
 | ||||
| const Search = React.createClass({ | ||||
| 
 | ||||
|   contextTypes: { | ||||
|     router: React.PropTypes.object | ||||
|   }, | ||||
| 
 | ||||
|   propTypes: { | ||||
|     suggestions: React.PropTypes.array.isRequired, | ||||
|     value: React.PropTypes.string.isRequired, | ||||
|     onChange: React.PropTypes.func.isRequired, | ||||
|     onSubmit: React.PropTypes.func.isRequired, | ||||
|     onClear: React.PropTypes.func.isRequired, | ||||
|     onFetch: React.PropTypes.func.isRequired, | ||||
|     onReset: React.PropTypes.func.isRequired, | ||||
|     onShow: React.PropTypes.func.isRequired, | ||||
|     intl: React.PropTypes.object.isRequired | ||||
|   }, | ||||
| 
 | ||||
|   mixins: [PureRenderMixin], | ||||
| 
 | ||||
|   onChange (_, { newValue }) { | ||||
|     if (typeof newValue !== 'string') { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     this.props.onChange(newValue); | ||||
|   handleChange (e) { | ||||
|     this.props.onChange(e.target.value); | ||||
|   }, | ||||
| 
 | ||||
|   onSuggestionsClearRequested () { | ||||
|   handleClear (e) { | ||||
|     e.preventDefault(); | ||||
|     this.props.onClear(); | ||||
|   }, | ||||
| 
 | ||||
|   @debounce(500) | ||||
|   onSuggestionsFetchRequested ({ value }) { | ||||
|     value = value.replace('#', ''); | ||||
|     this.props.onFetch(value.trim()); | ||||
|   }, | ||||
| 
 | ||||
|   onSuggestionSelected (_, { suggestion }) { | ||||
|     if (suggestion.type === 'account') { | ||||
|       this.context.router.push(`/accounts/${suggestion.id}`); | ||||
|     } else if(suggestion.type === 'hashtag') { | ||||
|       this.context.router.push(`/timelines/tag/${suggestion.id}`); | ||||
|     } else { | ||||
|       this.context.router.push(`/statuses/${suggestion.id}`); | ||||
|   handleKeyDown (e) { | ||||
|     if (e.key === 'Enter') { | ||||
|       e.preventDefault(); | ||||
|       this.props.onSubmit(); | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   handleFocus () { | ||||
|     this.props.onShow(); | ||||
|   }, | ||||
| 
 | ||||
|   render () { | ||||
|     const inputProps = { | ||||
|       placeholder: this.props.intl.formatMessage(messages.placeholder), | ||||
|       value: this.props.value, | ||||
|       onChange: this.onChange, | ||||
|       className: 'search__input' | ||||
|     }; | ||||
|     const { intl, value } = this.props; | ||||
|     const hasValue = value.length > 0; | ||||
| 
 | ||||
|     return ( | ||||
|       <div className='search' style={outerStyle}> | ||||
|         <Autosuggest | ||||
|           multiSection={true} | ||||
|           suggestions={this.props.suggestions} | ||||
|           focusFirstSuggestion={true} | ||||
|           focusInputOnSuggestionClick={false} | ||||
|           alwaysRenderSuggestions={false} | ||||
|           onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} | ||||
|           onSuggestionsClearRequested={this.onSuggestionsClearRequested} | ||||
|           onSuggestionSelected={this.onSuggestionSelected} | ||||
|           getSuggestionValue={getSuggestionValue} | ||||
|           renderSuggestion={renderSuggestion} | ||||
|           renderSectionTitle={renderSectionTitle} | ||||
|           getSectionSuggestions={getSectionSuggestions} | ||||
|           inputProps={inputProps} | ||||
|       <div className='search'> | ||||
|         <input | ||||
|           className='search__input' | ||||
|           type='text' | ||||
|           placeholder={intl.formatMessage(messages.placeholder)} | ||||
|           value={value} | ||||
|           onChange={this.handleChange} | ||||
|           onKeyUp={this.handleKeyDown} | ||||
|           onFocus={this.handleFocus} | ||||
|         /> | ||||
| 
 | ||||
|         <div style={iconStyle}><i className='fa fa-search' /></div> | ||||
|         <div className='search__icon'> | ||||
|           <i className={`fa fa-search ${hasValue ? '' : 'active'}`} /> | ||||
|           <i className={`fa fa-times-circle ${hasValue ? 'active' : ''}`} onClick={this.handleClear} /> | ||||
|         </div> | ||||
|       </div> | ||||
|     ); | ||||
|   }, | ||||
|   } | ||||
| 
 | ||||
| }); | ||||
| 
 | ||||
|  |  | |||
		Reference in a new issue