merge with master branch

This commit is contained in:
viktor 2018-03-21 09:35:41 +03:00
commit f6214dd79e
25 changed files with 2028 additions and 1388 deletions

1585
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,7 @@
"mobx-react-router": "^4.0.1",
"moment": "^2.20.1",
"node-sass-chokidar": "0.0.3",
"nodemon": "^1.14.12",
"npm-run-all": "^4.1.2",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
@ -65,8 +66,8 @@
"scripts": {
"predeploy": "npm run build",
"deploy": "gh-pages -d build -o origin",
"build-css": "node-sass-chokidar src/assets/App.scss -o src/assets",
"watch-css": "npm run build-css && node-sass-chokidar src/assets/App.scss -o src/assets/src/assets --watch",
"build-css": "node-sass-chokidar src/assets/App.scss -o src/assets --output-style=compressed",
"watch-css": "nodemon -e scss -x \"npm run build-css\"",
"start-js": "node scripts/start.js",
"start": "npm-run-all -p watch-css start-js",
"build-js": "node scripts/build.js",

File diff suppressed because one or more lines are too long

View File

@ -14,6 +14,7 @@
@import 'stylesheets/settings';
@import 'stylesheets/socials';
@import 'stylesheets/vote-scale';
@import 'stylesheets/ballot-types';
@import 'stylesheets/ballots/placeholders';
@import 'stylesheets/ballots/base';
@import 'stylesheets/ballots/about';
@ -23,4 +24,4 @@
@import 'stylesheets/select/menu';
@import 'stylesheets/select/mixins';
@import 'stylesheets/select/multi';
@import 'stylesheets/select/spinner';
@import 'stylesheets/select/spinner';

View File

@ -0,0 +1,30 @@
.ballot-types {
border-bottom: 1px solid #e5eef9;
padding: 0 30px 10px;
&-i {
cursor: pointer;
position: relative;
margin-bottom: 20px;
&:before {
content: '';
position: absolute;
left: -30px;
top: 50%;
opacity: 0;
height: 30px;
width: 3px;
transform: translateY(-50%);
background-color: #08b3f2;
}
&_active {
color: #08b3f2;
&:before {
opacity: 1;
}
}
}
}

View File

@ -6,7 +6,8 @@ label {
font-family: 'Open Sans', sans-serif;
}
input {
input,
textarea {
@extend %form-el;
&:focus {
@ -18,6 +19,14 @@ input {
}
}
textarea {
width: 100%;
padding-top: 10px;
padding-bottom: 10px;
height: 70px;
resize: none;
}
select {
@include image-2x('./images/select@2x.png', 8px, 4px);
@extend %form-el;

View File

@ -1,15 +1,54 @@
.info {
@include image-2x('./images/info@2x.png', 32px, 32px);
display: flex;
align-items: center;
padding-left: 44px;
min-height: 32px;
background-image: url(./images/info.png);
background-repeat: no-repeat;
background-position: left center;
color: #8197a2;
.ballots & {
margin-bottom: 20px;
@include image-2x('./images/info@2x.png', 32px, 32px);
display: flex;
align-items: center;
padding-left: 44px;
min-height: 32px;
background-image: url(./images/info.png);
background-repeat: no-repeat;
background-position: left center;
}
.new-form & {
padding: 30px;
}
&-title {
position: relative;
margin-bottom: 30px;
padding-left: 44px;
&:before {
@include image-2x('./images/info@2x.png', 32px, 32px);
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 32px;
height: 32px;
}
}
&-i {
position: relative;
margin-bottom: 10px;
padding-left: 12px;
line-height: 18px;
font-size: 12px;
&:before {
content: '';
position: absolute;
left: 0;
top: 7px;
width: 4px;
height: 4px;
border-radius: 50%;
background-color: #08b3f2;
}
}
}

View File

@ -1,15 +1,41 @@
.new {
&-form {
@extend %white-block;
display: flex;
overflow: hidden;
padding: 0;
&-footer {
display: flex;
align-items: center;
justify-content: space-between;
@media screen and (max-width: $tablet-width) {
display: block;
}
@media screen and (max-width: $mobile-width) {
flex-direction: column;
&-side {
padding-top: 30px;
padding-bottom: 30px;
box-sizing: border-box;
@media screen and (max-width: $tablet-width) {
width: 100% !important;
}
&_left {
width: 30%;
@media screen and (max-width: $tablet-width) {
padding-bottom: 0;
}
}
&_right {
width: 70%;
border-left: 1px solid #e5eef9;
padding-left: 30px;
padding-right: 30px;
@media screen and (max-width: $tablet-width) {
border: 0;
padding-top: 0;
}
}
}
}

View File

@ -29,6 +29,7 @@ export class BallotCard extends React.Component {
displayValue: zeroTimeTo,
title: "To close"
};
@observable creatorMiningKey;
@observable creator;
@observable progress;
@observable totalVoters;
@ -45,8 +46,15 @@ export class BallotCard extends React.Component {
return cls;
}
@computed get finalizeDescription () {
const _finalizeDescription = this.isFinalized ? '' : constants.CARD_FINALIZE_DESCRIPTION;
return _finalizeDescription;
}
@computed get votesForNumber() {
let votes = (this.totalVoters + this.progress) / 2;
if (isNaN(votes))
votes = 0;
return votes;
}
@ -56,11 +64,15 @@ export class BallotCard extends React.Component {
}
let votesPercents = Math.round(this.votesForNumber / this.totalVoters * 100);
if (isNaN(votesPercents))
votesPercents = 0;
return votesPercents;
}
@computed get votesAgainstNumber() {
let votes = (this.totalVoters - this.progress) / 2;
if (isNaN(votes))
votes = 0;
return votes;
}
@ -70,20 +82,32 @@ export class BallotCard extends React.Component {
}
let votesPercents = Math.round(this.votesAgainstNumber / this.totalVoters * 100);
if (isNaN(votesPercents))
votesPercents = 0;
return votesPercents;
}
@action("Get start time of keys ballot")
getStartTime = async () => {
const { contractsStore, id, votingType } = this.props;
let startTime = await this.getContract(contractsStore, votingType).getStartTime(id);
let startTime;
try {
startTime = await this.getContract(contractsStore, votingType).getStartTime(id);
} catch(e) {
console.log(e.message);
}
this.startTime = moment.utc(startTime * 1000).format(USDateTimeFormat);
}
@action("Get end time of keys ballot")
getEndTime = async () => {
const { contractsStore, id, votingType } = this.props;
let endTime = await this.getContract(contractsStore, votingType).getEndTime(id);
let endTime;
try {
endTime = await this.getContract(contractsStore, votingType).getEndTime(id);
} catch(e) {
console.log(e.message);
}
this.endTime = moment.utc(endTime * 1000).format(USDateTimeFormat);
}
@ -96,12 +120,13 @@ export class BallotCard extends React.Component {
let msFinish = finish.diff(_now);
if (msStart > 0) {
this.timeToStart.val = msStart;
this.timeToStart.val = msStart + 5000;
this.timeToStart.displayValue = this.formatMs(msStart, ":mm:ss");
return this.timeTo = this.timeToStart;
}
if (msFinish > 0) {
this.timeToStart.val = 0;
this.timeToFinish.val = msFinish;
this.timeToFinish.displayValue = this.formatMs(msFinish, ":mm:ss");
return this.timeTo = this.timeToFinish;
@ -131,55 +156,106 @@ export class BallotCard extends React.Component {
@action("Get creator")
getCreator = async () => {
const { contractsStore, id, votingType } = this.props;
let votingState = await this.getContract(contractsStore, votingType).votingState(id);
this.getValidatorFullname(votingState.creator);
let votingState;
try {
votingState = await this.getContract(contractsStore, votingType).votingState(id);
} catch(e) {
console.log(e.message);
}
if (votingState) {
this.getValidatorFullname(votingState.creator);
}
}
@action("Get progress")
getProgress = async () => {
const { contractsStore, id, votingType } = this.props;
let progress = await this.getContract(contractsStore, votingType).getProgress(id);
this.progress = Number(progress);
let progress;
try {
progress = await this.getContract(contractsStore, votingType).getProgress(id);
} catch(e) {
console.log(e.message);
}
if (progress) {
this.progress = Number(progress);
}
}
@action("Get total voters")
getTotalVoters = async () => {
const { contractsStore, id, votingType } = this.props;
let totalVoters = await this.getContract(contractsStore, votingType).getTotalVoters(id);
this.totalVoters = Number(totalVoters);
let totalVoters;
try {
totalVoters = await this.getContract(contractsStore, votingType).getTotalVoters(id);
} catch(e) {
console.log(e.message);
}
if (totalVoters) {
this.totalVoters = Number(totalVoters);
}
}
@action("Get isFinalized")
getIsFinalized = async() => {
const { contractsStore, id, votingType } = this.props;
this.isFinalized = await this.getContract(contractsStore, votingType).getIsFinalized(id);
let isFinalized;
try {
isFinalized = await this.getContract(contractsStore, votingType).getIsFinalized(id);
} catch(e) {
console.log(e.message);
}
this.isFinalized = isFinalized;
}
@action("Get validator full name")
getValidatorFullname = async (_miningKey) => {
const { contractsStore } = this.props;
let validator = await contractsStore.validatorMetadata.validators(_miningKey);
let firstName = toAscii(validator.firstName);
let lastName = toAscii(validator.lastName);
let fullName = `${firstName} ${lastName}`;
let validator;
try {
validator = await contractsStore.validatorMetadata.validators(_miningKey);
} catch(e) {
console.log(e.message);
}
let firstName, lastName, fullName
if (validator) {
firstName = toAscii(validator.firstName);
lastName = toAscii(validator.lastName);
fullName = `${firstName} ${lastName}`;
}
this.creatorMiningKey = _miningKey;
this.creator = fullName ? fullName : _miningKey;
}
isValidaVote = async () => {
isValidVote = async () => {
const { contractsStore, id, votingType } = this.props;
let isValidVote = await this.getContract(contractsStore, votingType).isValidVote(id, contractsStore.votingKey);
return isValidVote;
let _isValidVote;
try {
_isValidVote = await this.getContract(contractsStore, votingType).isValidVote(id, contractsStore.votingKey);
} catch(e) {
console.log(e.message);
}
return _isValidVote;
}
isActive = async () => {
const { contractsStore, id, votingType } = this.props;
let isActive = await this.getContract(contractsStore, votingType).isActive(id);
return isActive;
let _isActive;
try {
_isActive = await this.getContract(contractsStore, votingType).isActive(id);
} catch(e) {
console.log(e.message);
}
return _isActive;
}
getMemo = async () => {
const { contractsStore, id, votingType } = this.props;
let memo = await this.getContract(contractsStore, votingType).getMemo(id);
let memo;
try {
memo = await this.getContract(contractsStore, votingType).getMemo(id);
} catch(e) {
console.log(e.message);
}
this.memo = memo;
return memo;
}
@ -196,7 +272,7 @@ export class BallotCard extends React.Component {
return;
}
commonStore.showLoading();
let isValidVote = await this.isValidaVote();
let isValidVote = await this.isValidVote();
if (!isValidVote) {
commonStore.hideLoading();
swal("Warning!", messages.INVALID_VOTE_MSG, "warning");
@ -309,8 +385,20 @@ export class BallotCard extends React.Component {
let { commonStore } = this.props;
if (commonStore.searchTerm) {
if (commonStore.searchTerm.length > 0) {
const isCreatorPattern = String(this.creator).toLowerCase().includes(commonStore.searchTerm);
return isCreatorPattern;
const _isCreatorPattern = String(this.creator).toLowerCase().includes(commonStore.searchTerm);
const _isCreatorMiningKeyPattern = String(this.creatorMiningKey).toLowerCase().includes(commonStore.searchTerm);
return _isCreatorPattern || _isCreatorMiningKeyPattern;
}
}
return true;
}
isMemoPattern = () => {
let { commonStore } = this.props;
if (commonStore.searchTerm) {
if (commonStore.searchTerm.length > 0) {
const _isMemoPattern = String(this.memo).toLowerCase().includes(commonStore.searchTerm);
return _isMemoPattern;
}
}
return true;
@ -332,7 +420,7 @@ export class BallotCard extends React.Component {
render () {
let { contractsStore, votingType, children, isSearchPattern } = this.props;
console.log(votingType);
let ballotClass = (this.showCard() && (this.isCreatorPattern() || isSearchPattern)) ? "ballots-i" : "ballots-i display-none";
let ballotClass = (this.showCard() && (this.isCreatorPattern() || this.isMemoPattern() || isSearchPattern)) ? "ballots-i" : "ballots-i display-none";
const threshold = this.getThreshold(contractsStore, votingType);
return (
<div className={ballotClass}>
@ -349,7 +437,7 @@ export class BallotCard extends React.Component {
{children}
<div className="ballots-about-i ballots-about-i_time">
<div className="ballots-about-td">
<p className="ballots-about-i--title">Time</p>
<p className="ballots-about-i--title">Ballot Time</p>
</div>
<div className="ballots-about-td">
<p className="ballots-i--time">{this.timeTo.displayValue}</p>
@ -391,11 +479,11 @@ export class BallotCard extends React.Component {
<div className="ballots-footer">
<div className="ballots-footer-left">
<button type="button" onClick={(e) => this.finalize(e)} className={this.finalizeButtonClass}>{this.finalizeButtonDisplayName}</button>
<p>{constants.CARD_FINALIZE_DESCRIPTION}</p>
<p>{this.finalizeDescription}</p>
</div>
<div type="button" className="ballots-i--vote ballots-i--vote_no">{this.typeName(votingType)} Ballot ID: {this.props.id}</div>
</div>
</div>
);
}
}
}

View File

@ -54,7 +54,12 @@ export class BallotKeysCard extends React.Component {
@action("Get ballot type of keys ballot")
getBallotType = async () => {
const { contractsStore, id } = this.props;
let ballotType = await contractsStore.votingToChangeKeys.getBallotType(id);
let ballotType;
try {
ballotType = await contractsStore.votingToChangeKeys.getBallotType(id);
} catch(e) {
console.log(e.message);
}
this.ballotType = ballotType;
this.getBallotTypeDisplayName(ballotType);
}
@ -62,7 +67,12 @@ export class BallotKeysCard extends React.Component {
@action("Get affected key type of keys ballot")
getAffectedKeyType = async () => {
const { contractsStore, id } = this.props;
let affectedKeyType = await contractsStore.votingToChangeKeys.getAffectedKeyType(id);
let affectedKeyType;
try {
affectedKeyType = await contractsStore.votingToChangeKeys.getAffectedKeyType(id);
} catch(e) {
console.log(e.message);
}
this.affectedKeyType = affectedKeyType;
this.getAffectedKeyTypeDisplayName(affectedKeyType);
}
@ -71,15 +81,33 @@ export class BallotKeysCard extends React.Component {
@action("Get affected key of keys ballot")
getAffectedKey = async () => {
const { contractsStore, id } = this.props;
let affectedKey = await contractsStore.votingToChangeKeys.getAffectedKey(id);
let affectedKey;
try {
affectedKey = await contractsStore.votingToChangeKeys.getAffectedKey(id);
} catch (e) {
console.log(e.message);
}
this.affectedKey = affectedKey;
}
@action("Get mining key of keys ballot")
getMiningKey = async () => {
const { contractsStore, id } = this.props;
let miningKey = await contractsStore.votingToChangeKeys.getMiningKey(id);
const metadata = await contractsStore.getValidatorMetadata(miningKey)
this.miningKey = `${metadata.lastName} ${miningKey}`;
let miningKey, metadata;
try {
miningKey = await contractsStore.votingToChangeKeys.getMiningKey(id);
} catch(e) {
console.log(e.message);
}
try {
metadata = await contractsStore.getValidatorMetadata(miningKey);
} catch(e) {
console.log(e.message);
}
if (metadata) {
this.miningKey = `${metadata.lastName} ${miningKey}`;
} else {
this.miningKey = `${miningKey}`;
}
}
constructor(props) {
@ -93,10 +121,11 @@ export class BallotKeysCard extends React.Component {
isSearchPattern = () => {
let { commonStore } = this.props;
if (commonStore.searchTerm) {
const isMiningKeyPattern = String(this.miningKey).toLowerCase().includes(commonStore.searchTerm);
const isAffectedKeyPattern = String(this.affectedKey).toLowerCase().includes(commonStore.searchTerm);
const isAffectedKeyTypeDisplayNamePattern = String(this.affectedKeyTypeDisplayName).toLowerCase().includes(commonStore.searchTerm);
const isBallotTypeDisplayNamePattern = String(this.ballotTypeDisplayName).toLowerCase().includes(commonStore.searchTerm);
return (isAffectedKeyPattern || isAffectedKeyTypeDisplayNamePattern || isBallotTypeDisplayNamePattern);
return (isMiningKeyPattern || isAffectedKeyPattern || isAffectedKeyTypeDisplayNamePattern || isBallotTypeDisplayNamePattern);
}
return true;
}

View File

@ -26,10 +26,10 @@ export class BallotKeysMetadata extends React.Component {
</div>
<div className="right">
<div className="form-el">
<label htmlFor="key">Mining Key</label>
<label htmlFor="mining-key">Mining Key</label>
<Select.Creatable
name="form-field-name"
id="key"
id="mining-key"
value={ballotStore.ballotKeys.miningKey}
onChange={ballotStore.setMiningKey}
options={options}
@ -41,8 +41,8 @@ export class BallotKeysMetadata extends React.Component {
</div>
<div className="left">
<div className="form-el">
<label htmlFor="key">Ballot End</label>
<input type="datetime-local" id="key"
<label htmlFor="datetime-local">Ballot End</label>
<input type="datetime-local" id="datetime-local"
value={ballotStore.endTime}
min={ballotStore.endTime}
onChange={e => ballotStore.changeBallotMetadata(e, "endTime")}

View File

@ -11,7 +11,12 @@ export class BallotMinThresholdCard extends React.Component {
@action("Get proposed value of min threshold ballot")
getProposedValue = async () => {
const { contractsStore, id } = this.props;
let proposedValue = await contractsStore.votingToChangeMinThreshold.getProposedValue(id);
let proposedValue;
try {
proposedValue = await contractsStore.votingToChangeMinThreshold.getProposedValue(id);
} catch(e) {
console.log(e.message);
}
this.proposedValue = proposedValue;
}

View File

@ -23,8 +23,8 @@ export class BallotMinThresholdMetadata extends React.Component {
</div>
<div className="right">
<div className="form-el">
<label htmlFor="key">Ballot End</label>
<input type="datetime-local" id="key"
<label htmlFor="datetime-local">Ballot End</label>
<input type="datetime-local" id="datetime-local"
value={ballotStore.endTime}
onChange={e => ballotStore.changeBallotMetadata(e, "endTime")}
/>

View File

@ -12,14 +12,24 @@ export class BallotProxyCard extends React.Component {
@action("Get proposed address of proxy ballot")
getProposedAddress = async () => {
const { contractsStore, id } = this.props;
let proposedAddress = await contractsStore.votingToChangeProxy.getProposedValue(id);
let proposedAddress;
try {
proposedAddress = await contractsStore.votingToChangeProxy.getProposedValue(id);
} catch(e) {
console.log(e.message);
}
this.proposedAddress = proposedAddress;
}
@action("Get contract type of proxy ballot")
getContractType = async () => {
const { contractsStore, id } = this.props;
let contractType = await contractsStore.votingToChangeProxy.getContractType(id);
let contractType;
try {
contractType = await contractsStore.votingToChangeProxy.getContractType(id);
} catch(e) {
console.log(e.message);
}
this.contractType = contractType;
}

View File

@ -45,8 +45,8 @@ export class BallotProxyMetadata extends React.Component {
</div>
<div className="left">
<div className="form-el">
<label htmlFor="key">Ballot End</label>
<input type="datetime-local" id="key"
<label htmlFor="datetime-local">Ballot End</label>
<input type="datetime-local" id="datetime-local"
value={ballotStore.endTime}
onChange={e => ballotStore.changeBallotMetadata(e, "endTime")}
/>

View File

@ -48,6 +48,11 @@ export class NewBallot extends React.Component {
if (ballotStore.isBallotForKey) {
for (let ballotKeysProp in ballotStore.ballotKeys) {
if (!ballotStore.ballotKeys[ballotKeysProp]) {
swal("Warning!", `Ballot ${ballotKeysProp} is empty`, "warning");
commonStore.hideLoading();
return false;
}
if (ballotStore.ballotKeys[ballotKeysProp].length === 0) {
swal("Warning!", `Ballot ${ballotKeysProp} is empty`, "warning");
commonStore.hideLoading();
@ -99,6 +104,12 @@ export class NewBallot extends React.Component {
}
}
if (!ballotStore.isBallotForKey && !ballotStore.isBallotForMinThreshold && !ballotStore.isBallotForProxy) {
swal("Warning!", messages.BALLOT_TYPE_IS_EMPTY_MSG, "warning");
commonStore.hideLoading();
return false;
}
return true;
}
@ -107,8 +118,8 @@ export class NewBallot extends React.Component {
const inputToMethod = {
startTime: curDateInSeconds,
endTime: ballotStore.endTimeUnix,
affectedKey: ballotStore.ballotKeys.affectedKey,
affectedKeyType: ballotStore.ballotKeys.keyType,
affectedKey: ballotStore.ballotKeys.affectedKey,
affectedKeyType: ballotStore.ballotKeys.keyType,
miningKey: ballotStore.ballotKeys.miningKey.value,
ballotType: ballotStore.ballotKeys.keysBallotType,
sender: contractsStore.votingKey,
@ -123,7 +134,7 @@ export class NewBallot extends React.Component {
const inputToMethod = {
startTime: curDateInSeconds,
endTime: ballotStore.endTimeUnix,
proposedValue: ballotStore.ballotMinThreshold.proposedValue,
proposedValue: ballotStore.ballotMinThreshold.proposedValue,
sender: contractsStore.votingKey,
memo: ballotStore.memo
};
@ -136,7 +147,7 @@ export class NewBallot extends React.Component {
const inputToMethod = {
startTime: curDateInSeconds,
endTime: ballotStore.endTimeUnix,
proposedValue: ballotStore.ballotProxy.proposedAddress,
proposedValue: ballotStore.ballotProxy.proposedAddress,
contractType: ballotStore.ballotProxy.contractType,
sender: contractsStore.votingKey,
memo: ballotStore.memo
@ -159,8 +170,8 @@ export class NewBallot extends React.Component {
if (isFormValid) {
if (ballotStore.ballotType === ballotStore.BallotType.keys) {
const inputToAreBallotParamsValid = {
affectedKey: ballotStore.ballotKeys.affectedKey,
affectedKeyType: ballotStore.ballotKeys.keyType,
affectedKey: ballotStore.ballotKeys.affectedKey,
affectedKeyType: ballotStore.ballotKeys.keyType,
miningKey: ballotStore.ballotKeys.miningKey.value,
ballotType: ballotStore.ballotKeys.keysBallotType
};
@ -173,19 +184,19 @@ export class NewBallot extends React.Component {
let methodToCreateBallot;
switch (ballotStore.ballotType) {
case ballotStore.BallotType.keys:
case ballotStore.BallotType.keys:
methodToCreateBallot = this.createBallotForKeys;
break;
case ballotStore.BallotType.minThreshold:
case ballotStore.BallotType.minThreshold:
methodToCreateBallot = this.createBallotForMinThreshold;
break;
case ballotStore.BallotType.proxy:
case ballotStore.BallotType.proxy:
methodToCreateBallot = this.createBallotForProxy;
break;
default:
break;
}
let curDateInSeconds = moment.utc().add(5, 'minute').unix();
let curDateInSeconds = moment.utc().add(5, 'minutes').unix();
methodToCreateBallot(curDateInSeconds)
.on("receipt", (tx) => {
commonStore.hideLoading();
@ -205,6 +216,15 @@ export class NewBallot extends React.Component {
}
}
menuItemActive = (ballotType) => {
const { ballotStore } = this.props;
if (ballotType == ballotStore.ballotType) {
return 'ballot-types-i ballot-types-i_active';
} else {
return 'ballot-types-i';
}
}
render() {
const { contractsStore, ballotStore } = this.props;
let validator = ballotStore.isNewValidatorPersonalData ? <Validator />: "";
@ -212,15 +232,15 @@ export class NewBallot extends React.Component {
let metadata
let minThreshold = 0;
switch (ballotStore.ballotType) {
case ballotStore.BallotType.keys:
case ballotStore.BallotType.keys:
metadata = <BallotKeysMetadata />;
minThreshold = contractsStore.keysBallotThreshold;
break;
case ballotStore.BallotType.minThreshold:
case ballotStore.BallotType.minThreshold:
metadata = <BallotMinThresholdMetadata />;
minThreshold = contractsStore.minThresholdBallotThreshold;
break;
case ballotStore.BallotType.proxy:
case ballotStore.BallotType.proxy:
metadata = <BallotProxyMetadata />;
minThreshold = contractsStore.proxyBallotThreshold;
break;
@ -231,67 +251,99 @@ export class NewBallot extends React.Component {
<section className="container new">
<h1 className="title">New Ballot</h1>
<form action="" className="new-form">
<div className="hidden">
<div className="left">
<div className="radio-container">
<input type="radio" name="ballot-type" id="ballot-for-validators"
value={ballotStore.BallotType.keys}
checked={ballotStore.isBallotForKey}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.keys)}
/>
<label htmlFor="ballot-for-validators" className="radio">Validator Management Ballot</label>
<p className="hint">
Ballot to add, remove or swap any type of key for existing or new validators.
</p>
<div className="new-form-side new-form-side_left">
<div className="ballot-types">
<div
className={this.menuItemActive(ballotStore.BallotType.keys)}
onClick={(e) => ballotStore.changeBallotType(e, ballotStore.BallotType.keys)}
>
Validator Management Ballot
</div>
<div
className={this.menuItemActive(ballotStore.BallotType.minThreshold)}
onClick={(e) => ballotStore.changeBallotType(e, ballotStore.BallotType.minThreshold)}
>
Consenus Thershold Ballot
</div>
<div
className={this.menuItemActive(ballotStore.BallotType.proxy)}
onClick={(e) => ballotStore.changeBallotType(e, ballotStore.BallotType.proxy)}
>
Modify Proxy Contract Ballot
</div>
</div>
<div className="right">
<div className="radio-container">
<input type="radio" name="ballot-type" id="ballot-for-consensus"
value={ballotStore.BallotType.minThreshold}
checked={ballotStore.isBallotForMinThreshold}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.minThreshold)}
/>
<label htmlFor="ballot-for-consensus" className="radio">Consenus Threshold Ballot</label>
<p className="hint">
Ballot to change the minimum threshold for consensus to vote for keys.
</p>
</div>
</div>
<div className="left">
<div className="radio-container">
<input type="radio" name="ballot-type" id="ballot-for-proxy"
value={ballotStore.BallotType.proxy}
checked={ballotStore.isBallotForProxy}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.proxy)}
/>
<label htmlFor="ballot-for-proxy" className="radio">Modify Proxy Contract Ballot</label>
<p className="hint">
Ballot to change one of the proxy contracts.
</p>
</div>
</div>
</div>
<hr />
{validator}
{keysTypes}
{metadata}
<div className="form-el">
<label>Description of the ballot</label>
<div>
<textarea rows="4"
value={ballotStore.memo}
onChange={(e) => ballotStore.setMemo(e)}
></textarea>
</div>
</div>
<div className="new-form-footer">
<div className="info">
Minimum {minThreshold} from {contractsStore.validatorsLength} validators required to pass the proposal<br />
You can create {contractsStore.validatorLimits.keys} ballot for keys<br />
You can create {contractsStore.validatorLimits.minThreshold} ballot for consensus<br />
You can create {contractsStore.validatorLimits.proxy} ballot for proxy<br />
<p className="info-title">Information of the ballot</p>
<div className="info-i">
Minimum {minThreshold} from {contractsStore.validatorsLength} validators required to pass the proposal<br />
</div>
<div className="info-i">
You can create {contractsStore.validatorLimits.keys} ballot for keys<br />
</div>
<div className="info-i">
You can create {contractsStore.validatorLimits.minThreshold} ballot for consensus<br />
</div>
<div className="info-i">
You can create {contractsStore.validatorLimits.proxy} ballot for proxy<br />
</div>
</div>
</div>
<div className="new-form-side new-form-side_right">
<div className="form-el">
<label>Description of the ballot</label>
<div>
<textarea rows="4"
value={ballotStore.memo}
onChange={(e) => ballotStore.setMemo(e)}
></textarea>
</div>
</div>
<hr />
<div className="hidden">
<div className="left">
<div className="radio-container">
<input type="radio" name="ballot-type" id="ballot-for-validators"
value={ballotStore.BallotType.keys}
checked={ballotStore.isBallotForKey}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.keys)}
/>
<label htmlFor="ballot-for-validators" className="radio">Validator Management Ballot</label>
<p className="hint">
Ballot to add, remove or swap any type of key for existing or new validators.
</p>
</div>
</div>
<div className="right">
<div className="radio-container">
<input type="radio" name="ballot-type" id="ballot-for-consensus"
value={ballotStore.BallotType.minThreshold}
checked={ballotStore.isBallotForMinThreshold}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.minThreshold)}
/>
<label htmlFor="ballot-for-consensus" className="radio">Consenus Threshold Ballot</label>
<p className="hint">
Ballot to change the minimum threshold for consensus to vote for keys.
</p>
</div>
</div>
<div className="left">
<div className="radio-container">
<input type="radio" name="ballot-type" id="ballot-for-proxy"
value={ballotStore.BallotType.proxy}
checked={ballotStore.isBallotForProxy}
onChange={e => ballotStore.changeBallotType(e, ballotStore.BallotType.proxy)}
/>
<label htmlFor="ballot-for-proxy" className="radio">Modify Proxy Contract Ballot</label>
<p className="hint">
Ballot to change one of the proxy contracts.
</p>
</div>
</div>
</div>
<hr />
{validator}
{keysTypes}
{metadata}
<button type="button" className="add-ballot" onClick={e => this.onClick(e)}>Add ballot</button>
</div>
</form>

View File

@ -1,5 +1,5 @@
import Web3 from 'web3';
import networkAddresses from './addresses';
import { networkAddresses } from './addresses';
import helpers from "./helpers";
export default class BallotsStorage {

View File

@ -1,5 +1,5 @@
import Web3 from 'web3';
import networkAddresses from './addresses';
import { networkAddresses } from './addresses';
import helpers from "./helpers";
export default class POAConsensus {

View File

@ -1,6 +1,6 @@
import Web3 from 'web3';
import moment from 'moment';
import networkAddresses from './addresses';
import { networkAddresses } from './addresses';
import helpers from "./helpers";
var toAscii = function(hex) {

View File

@ -1,5 +1,5 @@
import Web3 from 'web3';
import networkAddresses from './addresses';
import { networkAddresses } from './addresses';
import helpers from "./helpers";
export default class VotingToChangeKeys {

View File

@ -1,5 +1,5 @@
import Web3 from 'web3';
import networkAddresses from './addresses';
import { networkAddresses } from './addresses';
import helpers from "./helpers";
export default class VotingToChangeMinThreshold {

View File

@ -1,5 +1,5 @@
import Web3 from 'web3';
import networkAddresses from './addresses';
import { networkAddresses } from './addresses';
import helpers from "./helpers";
export default class VotingToChangeProxy {

View File

@ -1,6 +1,4 @@
import { messages } from "../messages";
import { addressesURL, wrongRepoAlert } from "./helpers";
import swal from 'sweetalert2';
// const local = {
// VOTING_TO_CHANGE_KEYS_ADDRESS: '0xecdbe3937cf6ff27f70480855cfe03254f915b48',
// VOTING_TO_CHANGE_MIN_THRESHOLD_ADDRESS: '0x5ae30d4c8892292e0d8164f87a2e12dff9dc99e1',
@ -13,31 +11,31 @@ import swal from 'sweetalert2';
let SOKOL_ADDRESSES = {};
let CORE_ADDRESSES = {};
function getContractsAddresses(branch) {
async function getContractsAddresses(branch) {
let addr = addressesURL(branch);
fetch(addr).then(function(response) {
return response.json();
}).then(function(contracts) {
switch (branch) {
case 'core':
CORE_ADDRESSES = contracts;
break;
case 'sokol':
SOKOL_ADDRESSES = contracts;
break;
default:
CORE_ADDRESSES = contracts;
break;
}
}).catch(function(err) {
wrongRepoAlert(addr);
});
let response;
try {
response = await fetch(addr);
} catch(e) {
return wrongRepoAlert(addr);
}
let contracts = await response.json();
switch (branch) {
case 'core':
CORE_ADDRESSES = contracts;
break;
case 'sokol':
SOKOL_ADDRESSES = contracts;
break;
default:
CORE_ADDRESSES = contracts;
break;
}
}
getContractsAddresses('core');
getContractsAddresses('sokol');
module.exports = (netId) => {
function getAddresses(netId) {
switch (netId) {
case '77':
return SOKOL_ADDRESSES
@ -48,4 +46,7 @@ module.exports = (netId) => {
}
}
module.exports = {
getContractsAddresses: getContractsAddresses,
networkAddresses: getAddresses
}

View File

@ -10,6 +10,7 @@ import validatorStore from './stores/ValidatorStore';
import ballotStore from './stores/BallotStore';
import ballotsStore from './stores/BallotsStore';
import contractsStore from './stores/ContractsStore';
import { getContractsAddresses } from './contracts/addresses';
import swal from 'sweetalert2';
import getWeb3 from './getWeb3';
import "babel-polyfill";
@ -32,6 +33,9 @@ class AppMainRouter extends Component {
commonStore.showLoading();
getWeb3().then(async (web3Config) => {
await getContractsAddresses('sokol');
await getContractsAddresses('core');
await contractsStore.setWeb3Instance(web3Config);
await contractsStore.setPoaConsensus(web3Config);
await contractsStore.setBallotsStorage(web3Config);
@ -39,13 +43,15 @@ class AppMainRouter extends Component {
await contractsStore.setVotingToChangeMinThreshold(web3Config);
await contractsStore.setVotingToChangeProxy(web3Config);
await contractsStore.setValidatorMetadata(web3Config);
await contractsStore.getAllKeysBallots();
await contractsStore.getAllMinThresholdBallots();
await contractsStore.getAllProxyBallots();
contractsStore.getValidatorsLength();
contractsStore.getKeysBallotThreshold();
contractsStore.getMinThresholdBallotThreshold();
contractsStore.getProxyBallotThreshold();
contractsStore.getAllKeysBallots();
contractsStore.getAllMinThresholdBallots();
contractsStore.getAllProxyBallots();
contractsStore.setVotingKey(web3Config);
await contractsStore.setMiningKey(web3Config);
contractsStore.getValidatorActiveBallots();
@ -78,4 +84,4 @@ class AppMainRouter extends Component {
}
ReactDOM.render(<AppMainRouter />, document.getElementById('root'));
registerServiceWorker();
registerServiceWorker();

View File

@ -12,6 +12,7 @@ messages.AFFECTED_KEY_IS_NOT_ADDRESS_MSG = "Ballot affectedKey isn't address";
messages.MINING_KEY_IS_NOT_ADDRESS_MSG = "Ballot miningKey isn't address";
messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG = "Ballot proposedAddress isn't address";
messages.END_TIME_SHOULD_BE_GREATER_THAN_NOW_MSG = "Ballot end time should be greater than now";
messages.BALLOT_TYPE_IS_EMPTY_MSG = "Ballot type is empty";
messages.NO_METAMASK_MSG = `You haven't chosen any account in MetaMask.
Please, choose your voting key in MetaMask and reload the page.
Check POA Network <a href='https://github.com/poanetwork/wiki' target='blank'>wiki</a> for more info.`;