Merge pull request #99 from poanetwork/update-new-ballot

Update new ballot
This commit is contained in:
Victor Baranov 2018-03-20 22:29:41 +03:00 committed by GitHub
commit 244f6ee173
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1808 additions and 1291 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", "mobx-react-router": "^4.0.1",
"moment": "^2.20.1", "moment": "^2.20.1",
"node-sass-chokidar": "0.0.3", "node-sass-chokidar": "0.0.3",
"nodemon": "^1.14.12",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"object-assign": "4.1.1", "object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0", "postcss-flexbugs-fixes": "3.2.0",
@ -65,8 +66,8 @@
"scripts": { "scripts": {
"predeploy": "npm run build", "predeploy": "npm run build",
"deploy": "gh-pages -d build -o origin", "deploy": "gh-pages -d build -o origin",
"build-css": "node-sass-chokidar src/assets/App.scss -o src/assets", "build-css": "node-sass-chokidar src/assets/App.scss -o src/assets --output-style=compressed",
"watch-css": "npm run build-css && node-sass-chokidar src/assets/App.scss -o src/assets/src/assets --watch", "watch-css": "nodemon -e scss -x \"npm run build-css\"",
"start-js": "node scripts/start.js", "start-js": "node scripts/start.js",
"start": "npm-run-all -p watch-css start-js", "start": "npm-run-all -p watch-css start-js",
"build-js": "node scripts/build.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/settings';
@import 'stylesheets/socials'; @import 'stylesheets/socials';
@import 'stylesheets/vote-scale'; @import 'stylesheets/vote-scale';
@import 'stylesheets/ballot-types';
@import 'stylesheets/ballots/placeholders'; @import 'stylesheets/ballots/placeholders';
@import 'stylesheets/ballots/base'; @import 'stylesheets/ballots/base';
@import 'stylesheets/ballots/about'; @import 'stylesheets/ballots/about';

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

View File

@ -1,4 +1,7 @@
.info { .info {
color: #8197a2;
.ballots & {
@include image-2x('./images/info@2x.png', 32px, 32px); @include image-2x('./images/info@2x.png', 32px, 32px);
display: flex; display: flex;
align-items: center; align-items: center;
@ -7,9 +10,45 @@
background-image: url(./images/info.png); background-image: url(./images/info.png);
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: left center; background-position: left center;
color: #8197a2; }
.ballots & { .new-form & {
margin-bottom: 20px; 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 { .new {
&-form { &-form {
@extend %white-block; @extend %white-block;
overflow: hidden;
&-footer {
display: flex; display: flex;
align-items: center; overflow: hidden;
justify-content: space-between; padding: 0;
@media screen and (max-width: $mobile-width) { @media screen and (max-width: $tablet-width) {
flex-direction: column; display: block;
}
&-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

@ -48,6 +48,11 @@ export class NewBallot extends React.Component {
if (ballotStore.isBallotForKey) { if (ballotStore.isBallotForKey) {
for (let ballotKeysProp in ballotStore.ballotKeys) { 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) { if (ballotStore.ballotKeys[ballotKeysProp].length === 0) {
swal("Warning!", `Ballot ${ballotKeysProp} is empty`, "warning"); swal("Warning!", `Ballot ${ballotKeysProp} is empty`, "warning");
commonStore.hideLoading(); 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; return true;
} }
@ -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() { render() {
const { contractsStore, ballotStore } = this.props; const { contractsStore, ballotStore } = this.props;
let validator = ballotStore.isNewValidatorPersonalData ? <Validator />: ""; let validator = ballotStore.isNewValidatorPersonalData ? <Validator />: "";
@ -231,6 +251,54 @@ export class NewBallot extends React.Component {
<section className="container new"> <section className="container new">
<h1 className="title">New Ballot</h1> <h1 className="title">New Ballot</h1>
<form action="" className="new-form"> <form action="" className="new-form">
<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="info">
<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="hidden">
<div className="left"> <div className="left">
<div className="radio-container"> <div className="radio-container">
@ -276,22 +344,6 @@ export class NewBallot extends React.Component {
{validator} {validator}
{keysTypes} {keysTypes}
{metadata} {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 />
</div>
<button type="button" className="add-ballot" onClick={e => this.onClick(e)}>Add ballot</button> <button type="button" className="add-ballot" onClick={e => this.onClick(e)}>Add ballot</button>
</div> </div>
</form> </form>

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.MINING_KEY_IS_NOT_ADDRESS_MSG = "Ballot miningKey isn't address";
messages.PROPOSED_ADDRESS_IS_NOT_ADDRESS_MSG = "Ballot proposedAddress 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.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. messages.NO_METAMASK_MSG = `You haven't chosen any account in MetaMask.
Please, choose your voting key in MetaMask and reload the page. 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.`; Check POA Network <a href='https://github.com/poanetwork/wiki' target='blank'>wiki</a> for more info.`;