diff options
Diffstat (limited to 'app/assets/javascripts/components/features')
3 files changed, 163 insertions, 1 deletions
diff --git a/app/assets/javascripts/components/features/compose/components/search.jsx b/app/assets/javascripts/components/features/compose/components/search.jsx new file mode 100644 index 000000000..e81771e6a --- /dev/null +++ b/app/assets/javascripts/components/features/compose/components/search.jsx @@ -0,0 +1,126 @@ +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'; + +const getSuggestionValue = suggestion => suggestion.value; + +const renderSuggestion = suggestion => { + if (suggestion.type === 'account') { + return <AutosuggestAccountContainer id={suggestion.id} />; + } else { + return <span>#{suggestion.id}</span> + } +}; + +const renderSectionTitle = section => ( + <strong>{section.title}</strong> +); + +const getSectionSuggestions = section => section.items; + +const outerStyle = { + padding: '10px', + lineHeight: '20px', + position: 'relative' +}; + +const inputStyle = { + boxSizing: 'border-box', + display: 'block', + width: '100%', + border: 'none', + padding: '10px', + paddingRight: '30px', + fontFamily: 'Roboto', + background: '#282c37', + color: '#9baec8', + fontSize: '14px', + margin: '0' +}; + +const iconStyle = { + position: 'absolute', + top: '18px', + right: '20px', + color: '#9baec8', + 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, + onClear: React.PropTypes.func.isRequired, + onFetch: React.PropTypes.func.isRequired, + onReset: React.PropTypes.func.isRequired + }, + + mixins: [PureRenderMixin], + + onChange (_, { newValue }) { + if (typeof newValue !== 'string') { + return; + } + + this.props.onChange(newValue); + }, + + onSuggestionsClearRequested () { + this.props.onClear(); + }, + + onSuggestionsFetchRequested ({ value }) { + value = value.replace('#', ''); + this.props.onFetch(value.trim()); + }, + + onSuggestionSelected (_, { suggestion }) { + if (suggestion.type === 'account') { + this.context.router.push(`/accounts/${suggestion.id}`); + } else { + this.context.router.push(`/statuses/tag/${suggestion.id}`); + } + }, + + render () { + const inputProps = { + placeholder: 'Search', + value: this.props.value, + onChange: this.onChange, + style: inputStyle + }; + + return ( + <div 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 style={iconStyle}><i className='fa fa-search' /></div> + </div> + ); + }, + +}); + +export default Search; diff --git a/app/assets/javascripts/components/features/compose/containers/search_container.jsx b/app/assets/javascripts/components/features/compose/containers/search_container.jsx new file mode 100644 index 000000000..17a68f2fc --- /dev/null +++ b/app/assets/javascripts/components/features/compose/containers/search_container.jsx @@ -0,0 +1,35 @@ +import { connect } from 'react-redux'; +import { + changeSearch, + clearSearchSuggestions, + fetchSearchSuggestions, + resetSearch +} from '../../../actions/search'; +import Search from '../components/search'; + +const mapStateToProps = state => ({ + suggestions: state.getIn(['search', 'suggestions']), + value: state.getIn(['search', 'value']) +}); + +const mapDispatchToProps = dispatch => ({ + + onChange (value) { + dispatch(changeSearch(value)); + }, + + onClear () { + dispatch(clearSearchSuggestions()); + }, + + onFetch (value) { + dispatch(fetchSearchSuggestions(value)); + }, + + onReset () { + dispatch(resetSearch()); + } + +}); + +export default connect(mapStateToProps, mapDispatchToProps)(Search); diff --git a/app/assets/javascripts/components/features/compose/index.jsx b/app/assets/javascripts/components/features/compose/index.jsx index d76afc437..260f67034 100644 --- a/app/assets/javascripts/components/features/compose/index.jsx +++ b/app/assets/javascripts/components/features/compose/index.jsx @@ -5,6 +5,7 @@ import UploadFormContainer from '../ui/containers/upload_form_container'; import NavigationContainer from '../ui/containers/navigation_container'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import SuggestionsContainer from './containers/suggestions_container'; +import SearchContainer from './containers/search_container'; import { fetchSuggestions } from '../../actions/suggestions'; import { connect } from 'react-redux'; @@ -24,13 +25,13 @@ const Compose = React.createClass({ return ( <Drawer> <div style={{ flex: '1 1 auto' }}> + <SearchContainer /> <NavigationContainer /> <ComposeFormContainer /> <UploadFormContainer /> </div> <SuggestionsContainer /> - <FollowFormContainer /> </Drawer> ); } |