@ -1,17 +0,0 @@ | |||||
FROM neo4j:latest | |||||
ENV NEO4J_AUTH=none | |||||
RUN cd /var/lib/neo4j/plugins \ | |||||
&& wget http://products.graphaware.com/download/framework-server-community/graphaware-server-community-all-3.0.6.43.jar \ | |||||
&& wget http://products.graphaware.com/download/noderank/graphaware-noderank-3.0.6.43.3.jar | |||||
RUN echo "dbms.unmanaged_extension_classes=com.graphaware.server=/graphaware" >> /var/lib/neo4j/conf/neo4j.conf | |||||
RUN echo 'com.graphaware.runtime.enabled=true\n\ | |||||
com.graphaware.module.NR.1=com.graphaware.module.noderank.NodeRankModuleBootstrapper\n\ | |||||
com.graphaware.module.NR.maxTopRankNodes=10\n\ | |||||
com.graphaware.module.NR.dampingFactor=0.85\n\ | |||||
com.graphaware.module.NR.propertyKey=nodeRank\n'\ | |||||
>> /var/lib/neo4j/conf/neo4j.conf | |||||
RUN echo 'com.graphaware.runtime.stats.disabled=true\n\ | |||||
com.graphaware.server.stats.disabled=true\n'\ | |||||
>> /var/lib/neo4j/conf/neo4j.conf |
@ -1,37 +0,0 @@ | |||||
import api from '../api'; | |||||
export const SUGGESTIONS_FETCH_REQUEST = 'SUGGESTIONS_FETCH_REQUEST'; | |||||
export const SUGGESTIONS_FETCH_SUCCESS = 'SUGGESTIONS_FETCH_SUCCESS'; | |||||
export const SUGGESTIONS_FETCH_FAIL = 'SUGGESTIONS_FETCH_FAIL'; | |||||
export function fetchSuggestions() { | |||||
return (dispatch, getState) => { | |||||
dispatch(fetchSuggestionsRequest()); | |||||
api(getState).get('/api/v1/accounts/suggestions').then(response => { | |||||
dispatch(fetchSuggestionsSuccess(response.data)); | |||||
}).catch(error => { | |||||
dispatch(fetchSuggestionsFail(error)); | |||||
}); | |||||
}; | |||||
}; | |||||
export function fetchSuggestionsRequest() { | |||||
return { | |||||
type: SUGGESTIONS_FETCH_REQUEST | |||||
}; | |||||
}; | |||||
export function fetchSuggestionsSuccess(accounts) { | |||||
return { | |||||
type: SUGGESTIONS_FETCH_SUCCESS, | |||||
accounts: accounts | |||||
}; | |||||
}; | |||||
export function fetchSuggestionsFail(error) { | |||||
return { | |||||
type: SUGGESTIONS_FETCH_FAIL, | |||||
error: error | |||||
}; | |||||
}; |
@ -1,86 +0,0 @@ | |||||
import PureRenderMixin from 'react-addons-pure-render-mixin'; | |||||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||||
import AccountContainer from '../../../containers/account_container'; | |||||
import { FormattedMessage } from 'react-intl'; | |||||
const outerStyle = { | |||||
position: 'relative' | |||||
}; | |||||
const headerStyle = { | |||||
fontSize: '14px', | |||||
fontWeight: '500', | |||||
display: 'block', | |||||
padding: '10px', | |||||
color: '#9baec8', | |||||
background: '#454b5e', | |||||
overflow: 'hidden' | |||||
}; | |||||
const nextStyle = { | |||||
display: 'inline-block', | |||||
float: 'right', | |||||
fontWeight: '400', | |||||
color: '#2b90d9' | |||||
}; | |||||
const SuggestionsBox = React.createClass({ | |||||
propTypes: { | |||||
accountIds: ImmutablePropTypes.list, | |||||
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.accountIds.skip(this.props.perWindow * newIndex).size === 0) { | |||||
newIndex = 0; | |||||
} | |||||
this.setState({ index: newIndex }); | |||||
}, | |||||
render () { | |||||
const { accountIds, perWindow } = this.props; | |||||
if (!accountIds || accountIds.size === 0) { | |||||
return <div />; | |||||
} | |||||
let nextLink = ''; | |||||
if (accountIds.size > perWindow) { | |||||
nextLink = <a href='#' style={nextStyle} onClick={this.handleNextClick}><FormattedMessage id='suggestions_box.refresh' defaultMessage='Refresh' /></a>; | |||||
} | |||||
return ( | |||||
<div style={outerStyle}> | |||||
<strong style={headerStyle}> | |||||
<FormattedMessage id='suggestions_box.who_to_follow' defaultMessage='Who to follow' /> {nextLink} | |||||
</strong> | |||||
{accountIds.skip(perWindow * this.state.index).take(perWindow).map(accountId => <AccountContainer key={accountId} id={accountId} withNote={false} />)} | |||||
</div> | |||||
); | |||||
} | |||||
}); | |||||
export default SuggestionsBox; |
@ -1,8 +0,0 @@ | |||||
import { connect } from 'react-redux'; | |||||
import SuggestionsBox from '../components/suggestions_box'; | |||||
const mapStateToProps = (state) => ({ | |||||
accountIds: state.getIn(['user_lists', 'suggestions']) | |||||
}); | |||||
export default connect(mapStateToProps)(SuggestionsBox); |
@ -1,50 +0,0 @@ | |||||
# frozen_string_literal: true | |||||
class FollowSuggestion | |||||
class << self | |||||
def get(for_account_id, limit = 10) | |||||
neo = Neography::Rest.new | |||||
query = <<END | |||||
MATCH (a {account_id: {id}})-[:follows]->(b)-[:follows]->(c) | |||||
WHERE a <> c | |||||
AND NOT (a)-[:follows]->(c) | |||||
RETURN DISTINCT c.account_id, count(b), c.nodeRank | |||||
ORDER BY count(b) DESC, c.nodeRank DESC | |||||
LIMIT {limit} | |||||
END | |||||
results = neo.execute_query(query, id: for_account_id, limit: limit) | |||||
if results.empty? || results['data'].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 | |||||
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).with_counters.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 [] | |||||
end | |||||
private | |||||
def fallback(for_account_id, limit) | |||||
neo = Neography::Rest.new | |||||
query = <<END | |||||
MATCH (b) | |||||
RETURN b.account_id | |||||
ORDER BY b.nodeRank DESC | |||||
LIMIT {limit} | |||||
END | |||||
neo.execute_query(query, id: for_account_id, limit: limit) | |||||
end | |||||
end | |||||
end |
@ -1,5 +0,0 @@ | |||||
Neography.configure do |config| | |||||
config.protocol = "http" | |||||
config.server = ENV.fetch('NEO4J_HOST') { 'localhost' } | |||||
config.port = ENV.fetch('NEO4J_PORT') { 7474 } | |||||
end |