You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
3.2 KiB

  1. import PureRenderMixin from 'react-addons-pure-render-mixin';
  2. import ImmutablePropTypes from 'react-immutable-proptypes';
  3. import Autosuggest from 'react-autosuggest';
  4. import AutosuggestAccountContainer from '../containers/autosuggest_account_container';
  5. import { debounce } from 'react-decoration';
  6. import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
  7. const messages = defineMessages({
  8. placeholder: { id: 'search.placeholder', defaultMessage: 'Search' }
  9. });
  10. const getSuggestionValue = suggestion => suggestion.value;
  11. const renderSuggestion = suggestion => {
  12. if (suggestion.type === 'account') {
  13. return <AutosuggestAccountContainer id={suggestion.id} />;
  14. } else {
  15. return <span>#{suggestion.id}</span>
  16. }
  17. };
  18. const renderSectionTitle = section => (
  19. <strong><FormattedMessage id={`search.${section.title}`} defaultMessage={section.title} /></strong>
  20. );
  21. const getSectionSuggestions = section => section.items;
  22. const outerStyle = {
  23. padding: '10px',
  24. lineHeight: '20px',
  25. position: 'relative'
  26. };
  27. const iconStyle = {
  28. position: 'absolute',
  29. top: '18px',
  30. right: '20px',
  31. fontSize: '18px',
  32. pointerEvents: 'none'
  33. };
  34. const Search = React.createClass({
  35. contextTypes: {
  36. router: React.PropTypes.object
  37. },
  38. propTypes: {
  39. suggestions: React.PropTypes.array.isRequired,
  40. value: React.PropTypes.string.isRequired,
  41. onChange: React.PropTypes.func.isRequired,
  42. onClear: React.PropTypes.func.isRequired,
  43. onFetch: React.PropTypes.func.isRequired,
  44. onReset: React.PropTypes.func.isRequired,
  45. intl: React.PropTypes.object.isRequired
  46. },
  47. mixins: [PureRenderMixin],
  48. onChange (_, { newValue }) {
  49. if (typeof newValue !== 'string') {
  50. return;
  51. }
  52. this.props.onChange(newValue);
  53. },
  54. onSuggestionsClearRequested () {
  55. this.props.onClear();
  56. },
  57. @debounce(500)
  58. onSuggestionsFetchRequested ({ value }) {
  59. value = value.replace('#', '');
  60. this.props.onFetch(value.trim());
  61. },
  62. onSuggestionSelected (_, { suggestion }) {
  63. if (suggestion.type === 'account') {
  64. this.context.router.push(`/accounts/${suggestion.id}`);
  65. } else {
  66. this.context.router.push(`/timelines/tag/${suggestion.id}`);
  67. }
  68. },
  69. render () {
  70. const inputProps = {
  71. placeholder: this.props.intl.formatMessage(messages.placeholder),
  72. value: this.props.value,
  73. onChange: this.onChange,
  74. className: 'search__input'
  75. };
  76. return (
  77. <div className='search' style={outerStyle}>
  78. <Autosuggest
  79. multiSection={true}
  80. suggestions={this.props.suggestions}
  81. focusFirstSuggestion={true}
  82. focusInputOnSuggestionClick={false}
  83. alwaysRenderSuggestions={false}
  84. onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
  85. onSuggestionsClearRequested={this.onSuggestionsClearRequested}
  86. onSuggestionSelected={this.onSuggestionSelected}
  87. getSuggestionValue={getSuggestionValue}
  88. renderSuggestion={renderSuggestion}
  89. renderSectionTitle={renderSectionTitle}
  90. getSectionSuggestions={getSectionSuggestions}
  91. inputProps={inputProps}
  92. />
  93. <div style={iconStyle}><i className='fa fa-search' /></div>
  94. </div>
  95. );
  96. },
  97. });
  98. export default injectIntl(Search);