Commit 19a765c5 authored by Dan Notestein's avatar Dan Notestein
Browse files

Merge branch 'more-witnesses' into 'develop'

Display more witnesses

See merge request !81
parents 0fcadee0 fdd49eff
......@@ -13,8 +13,7 @@ find node_modules/eslint-config-airbnb -name '*.js'|xargs sed -i "s/': 2/': 1/"
"es6": true
},
"rules": {
"max-len": 0,
/*[1, 160, 4],*/
"max-len": ["error", { "code": 120 }],
"comma-dangle": 0,
"semi": [
0
......
......@@ -20,22 +20,34 @@ import _ from 'lodash';
const Long = ByteBuffer.Long;
const { string, func, object } = PropTypes;
const witnessFilterLastBlockAgeThresholdInDays = 30;
const DISABLED_SIGNING_KEY = 'STM1111111111111111111111111111111114T1Anm';
function _blockGap(head_block, last_block) {
if (!last_block || last_block < 1) return 'forever';
function _blockGap(head_block, last_block, format = 'auto') {
const secs = (head_block - last_block) * 3;
if (secs < 60) return 'just now';
if (secs < 120) return 'recently';
const mins = Math.floor(secs / 60);
if (mins < 120) return mins + ' mins ago';
const hrs = Math.floor(mins / 60);
if (hrs < 48) return hrs + ' hrs ago';
const days = Math.floor(hrs / 24);
if (days < 14) return days + ' days ago';
const weeks = Math.floor(days / 7);
if (weeks < 104) return weeks + ' weeks ago';
const months = Math.floor(days / 30);
const years = Math.floor(days / 365);
switch (format) {
case 'days':
return days;
case 'auto':
default:
if (!last_block || last_block < 1) return 'forever';
if (secs < 60) return 'just now';
if (secs < 120) return 'recently';
if (mins < 120) return mins + ' mins ago';
if (hrs < 48) return hrs + ' hrs ago';
if (days < 14) return days + ' days ago';
if (weeks < 4) return weeks + ' weeks ago';
if (months < 24) return months + ' months ago';
return years + ' years ago';
}
}
class Witnesses extends React.Component {
......@@ -104,17 +116,32 @@ class Witnesses extends React.Component {
}
async loadWitnessAccounts() {
const witnessAccounts = this.state.witnessAccounts;
const { head_block } = this.props;
const { witnessAccounts } = this.state;
const { witnesses } = this.props;
const witnessOwners = [[]];
let chunksCount = 0;
witnesses.map((item) => {
if (witnessOwners[chunksCount].length >= 20) {
chunksCount += 1;
witnessOwners[chunksCount] = [];
const lastBlock = item.get('last_confirmed_block_num');
const witnessLastBlockAgeInDays = _blockGap(
head_block,
lastBlock,
'days'
);
// Lets not fetch extra account details for witnesses who have not produced blocks in a while
if (
witnessLastBlockAgeInDays <=
witnessFilterLastBlockAgeThresholdInDays
) {
if (witnessOwners[chunksCount].length >= 20) {
chunksCount += 1;
witnessOwners[chunksCount] = [];
}
witnessOwners[chunksCount].push(item.get('owner'));
}
witnessOwners[chunksCount].push(item.get('owner'));
return true;
});
......@@ -196,7 +223,7 @@ class Witnesses extends React.Component {
onWitnessChange,
updateWitnessToHighlight,
} = this;
const sorted_witnesses = this.props.witnesses.sort((a, b) =>
const sortedWitnesses = this.props.witnesses.sort((a, b) =>
Long.fromString(String(b.get('votes'))).subtract(
Long.fromString(String(a.get('votes'))).toString()
)
......@@ -207,7 +234,7 @@ class Witnesses extends React.Component {
let previousTotalVoteHpf = 0;
const now = Moment();
const witnesses = sorted_witnesses.map((item) => {
const witnesses = sortedWitnesses.map((item) => {
const witnessName = item.get('owner');
if (witnessName === witnessToHighlight) {
foundWitnessToHighlight = true;
......@@ -230,6 +257,9 @@ class Witnesses extends React.Component {
.replace(/ /g, '')
.split(',');
}
witnessOwnerNames = witnessOwnerNames.filter((ownerName) => {
return ownerName !== item.get('owner');
});
}
const totalVotesVests = item.get('votes');
......@@ -333,6 +363,40 @@ class Witnesses extends React.Component {
? { textDecoration: 'line-through', color: '#AAA' }
: {};
const witnessLastBlockAgeInDays = _blockGap(
head_block,
lastBlock,
'days'
);
const witnessSocialLink = (witnessName) => {
return (
<Link
to={`${$STM_Config.social_url}/@${witnessName}`}
style={ownerStyle}
title={tt('witnesses_jsx.navigate_to_witness_profile')}
target="_blank"
rel="noreferrer noopener"
>
{witnessName}
</Link>
);
};
// Don't display the witness
if (
// If rank over 100
rank > 100 &&
// And no blocked produced for over 30 days
witnessLastBlockAgeInDays >
witnessFilterLastBlockAgeThresholdInDays &&
// And not voted by current user
!myVote
) {
rank += 1;
return null;
}
return (
<tr
key={witnessName}
......@@ -385,70 +449,43 @@ class Witnesses extends React.Component {
</Link>
<div className="Witnesses__info">
<div>
<Link
to={`${$STM_Config.social_url}/@${witnessName}`}
style={ownerStyle}
title={tt(
'witnesses_jsx.navigate_to_witness_profile'
)}
target="_blank"
rel="noreferrer noopener"
>
{witnessName}
</Link>
{witnessOwnerNames && (
<span>
{' '}
by{' '}
{witnessOwnerNames.map(
(ownerName, index) => {
if (
witnessOwnerNames.length >
1 &&
index ===
witnessOwnerNames.length -
1
) {
{witnessSocialLink(witnessName)}
{witnessOwnerNames &&
witnessOwnerNames.length > 0 && (
<span>
{' '}
{tt('witnesses_jsx.by')}{' '}
{witnessOwnerNames.map(
(ownerName, index) => {
if (
witnessOwnerNames.length >
1 &&
index ===
witnessOwnerNames.length -
1
) {
return (
<span>
{' '}
&{' '}
{witnessSocialLink(
ownerName
)}
</span>
);
}
return (
<span>
{' '}
&{' '}
<Link
to={`${$STM_Config.social_url}/@${ownerName}`}
style={
ownerStyle
}
title={tt(
'witnesses_jsx.navigate_to_witness_profile'
)}
target="_blank"
rel="noreferrer noopener"
>
{ownerName}
</Link>
{index > 0 && ', '}
{witnessSocialLink(
ownerName
)}
</span>
);
}
return (
<span>
{index > 0 && ', '}
<Link
to={`${$STM_Config.social_url}/@${ownerName}`}
style={ownerStyle}
title={tt(
'witnesses_jsx.navigate_to_witness_profile'
)}
target="_blank"
rel="noreferrer noopener"
>
{ownerName}
</Link>
</span>
);
}
)}
</span>
)}
)}
</span>
)}
<Link
to={`/~witnesses?highlight=${witnessName}`}
onClick={(event) => {
......@@ -544,13 +581,17 @@ class Witnesses extends React.Component {
);
});
let addl_witnesses = false;
let additionalWitnesses = false;
const sortedWitnessNames = sortedWitnesses.map((witness) => {
return witness.get('owner');
});
if (witness_votes) {
witness_vote_count -= witness_votes.size;
addl_witnesses = witness_votes
additionalWitnesses = witness_votes
.union(witnessVotesInProgress)
.filter((item) => {
return !sorted_witnesses.has(item);
return sortedWitnessNames.indexOf(item) === -1;
})
.map((item) => {
const votingActive = witnessVotesInProgress.has(item);
......@@ -617,6 +658,7 @@ class Witnesses extends React.Component {
)}
.
</p>
<p>{tt('witnesses_jsx.witness_list_notes')}</p>
</div>
)}
</div>
......@@ -693,7 +735,7 @@ class Witnesses extends React.Component {
</div>
</form>
<br />
{addl_witnesses}
{additionalWitnesses}
<br />
<br />
</div>
......
......@@ -423,15 +423,17 @@
"external_site": "Open external site",
"disabled": "Disabled",
"top_witnesses": "Witness Voting",
"by": "by",
"you_have_votes_remaining": {
"zero": "You have no votes remaining",
"one": "You have 1 vote remaining",
"other": "You have %(count)s votes remaining"
},
"you_can_vote_for_maximum_of_witnesses": "You can vote for a maximum of 30 witnesses",
"witness_list_notes": "Notes: in the list below, the first 100 witnesses are unfiltered, this includes active and inactive witnesses. Past the rank of 100, witnesses will be filtered out of the list if they have not produced any block for the last 30 days.",
"witness": "Witness",
"information": "More Information",
"if_you_want_to_vote_outside_of_top_enter_account_name": "If you would like to vote for a witness outside of the top 100, enter the account name below to cast a vote",
"if_you_want_to_vote_outside_of_top_enter_account_name": "If you would like to vote for a witness outside of the top 200, enter the account name below to cast a vote",
"set_witness_proxy": "You can also choose a proxy that will vote for witnesses for you. This will reset your current witness selection.",
"witness_set": "You have set a voting proxy. If you would like to re-enable manual voting, please clear your proxy.",
"witness_proxy_current": "Your current proxy is",
......
......@@ -35,7 +35,7 @@ async function getStateForTrending() {
async function getStateForWitnesses() {
let schedule = await api.getWitnessScheduleAsync();
let witnesses = await api.getWitnessesByVoteAsync('', 100);
let witnesses = await api.getWitnessesByVoteAsync('', 200);
let global_properties = await api.getDynamicGlobalPropertiesAsync();
let result = {};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment