parent
fca183968e
commit
8efa081f21
@ -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 |
|
Loading…
Reference in new issue