diff --git a/app/assets/javascripts/components/features/compose/components/suggestions_box.jsx b/app/assets/javascripts/components/features/compose/components/suggestions_box.jsx index 50229eb69..d7eeee729 100644 --- a/app/assets/javascripts/components/features/compose/components/suggestions_box.jsx +++ b/app/assets/javascripts/components/features/compose/components/suggestions_box.jsx @@ -6,7 +6,8 @@ import { Link } from 'react-router'; const outerStyle = { marginBottom: '10px', - borderTop: '1px solid #616b86' + borderTop: '1px solid #616b86', + position: 'relative' }; const headerStyle = { @@ -41,26 +42,64 @@ const acctStyle = { textOverflow: 'ellipsis' }; +const nextStyle = { + fontWeight: '400', + color: '#2b90d9' +}; + const SuggestionsBox = React.createClass({ propTypes: { - accounts: ImmutablePropTypes.list.isRequired + accounts: ImmutablePropTypes.list.isRequired, + perWindow: React.PropTypes.number + }, + + getInitialState () { + return { + index: 0 + }; + }, + + getDefaultProps () { + return { + perWindow: 2 + }; }, mixins: [PureRenderMixin], + handleNextClick (e) { + e.preventDefault(); + + let newIndex = this.state.index + 1; + + if (this.props.accounts.skip(this.props.perWindow * newIndex).size === 0) { + newIndex = 0; + } + + this.setState({ index: newIndex }); + }, + render () { - const accounts = this.props.accounts.take(3); + const { accounts, perWindow } = this.props; if (accounts.size === 0) { return
; } + let nextLink = ''; + + if (accounts.size > perWindow) { + nextLink = Next; + } + return (
- Who to follow + + Who to follow {nextLink} + - {accounts.map(account => { + {accounts.skip(perWindow * this.state.index).take(perWindow).map(account => { let displayName = account.get('display_name'); if (displayName.length === 0) { diff --git a/app/models/follow_suggestion.rb b/app/models/follow_suggestion.rb index 719270318..25d28f5ac 100644 --- a/app/models/follow_suggestion.rb +++ b/app/models/follow_suggestion.rb @@ -14,9 +14,17 @@ END results = neo.execute_query(query, id: for_account_id, limit: limit) - return fallback(for_account_id, limit) if results.empty? || results['data'].empty? + if results.empty? + results = fallback(for_account_id, limit) + elsif results['data'].size < limit + results['data'] = (results['data'] + fallback(for_account_id, limit - results['data'].size)['data']).uniq + end - map_to_accounts(for_account_id, results) + account_ids = results['data'].map(&:first) + blocked_ids = Block.where(account_id: for_account_id).pluck(:target_account_id) + accounts_map = Account.where(id: account_ids - blocked_ids).map { |a| [a.id, a] }.to_h + + account_ids.map { |id| accounts_map[id] }.compact rescue Neography::NeographyError, Excon::Error::Socket => e Rails.logger.error e return [] @@ -25,23 +33,18 @@ END private def self.fallback(for_account_id, limit) - neo = Neography::Rest.new - query = 'MATCH (a) WHERE a.account_id <> {id} RETURN a.account_id ORDER BY a.nodeRank DESC LIMIT {limit}' - results = neo.execute_query(query, id: for_account_id, limit: limit) - - map_to_accounts(for_account_id, results) - rescue Neography::NeographyError, Excon::Error::Socket => e - Rails.logger.error e - return [] - end - - def self.map_to_accounts(for_account_id, results) - return [] if results.empty? || results['data'].empty? + neo = Neography::Rest.new - account_ids = results['data'].map(&:first) - blocked_ids = Block.where(account_id: for_account_id).pluck(:target_account_id) - accounts_map = Account.where(id: account_ids - blocked_ids).map { |a| [a.id, a] }.to_h + query = < b +AND NOT (a)-[:follows]->(b) +RETURN b.account_id +ORDER BY b.nodeRank DESC +LIMIT {limit} +END - account_ids.map { |id| accounts_map[id] }.compact + neo.execute_query(query, id: for_account_id, limit: limit) end end