about summary refs log tree commit diff
path: root/app/assets/javascripts/components/features
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/components/features')
-rw-r--r--app/assets/javascripts/components/features/compose/components/search.jsx126
-rw-r--r--app/assets/javascripts/components/features/compose/containers/search_container.jsx35
-rw-r--r--app/assets/javascripts/components/features/compose/index.jsx3
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>
     );
   }