New ballot validation for all types; loading screen

This commit is contained in:
viktor 2017-12-20 16:13:28 +03:00
parent 660c1ac094
commit c7ebedd1a8
19 changed files with 723 additions and 257 deletions

5
package-lock.json generated
View File

@ -6844,6 +6844,11 @@
"resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.4.2.tgz",
"integrity": "sha512-dF+yxZSojSiI8AXGoxj5qdFWpucndc54Ug+TwlpHFaV7j22MGG+OML2+FVa6xAZtjb/OFFQhOC37Jegx2GbEwA=="
},
"moment": {
"version": "2.20.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
"integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
},
"mout": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz",

View File

@ -34,6 +34,7 @@
"mobx": "^3.4.1",
"mobx-react": "^4.3.5",
"mobx-react-devtools": "^4.2.15",
"moment": "^2.20.1",
"node-sass-chokidar": "0.0.3",
"npm-run-all": "^4.1.2",
"object-assign": "4.1.1",

View File

@ -3,11 +3,19 @@ import { Route } from 'react-router-dom';
import { Header, Ballots, NewBallot, Settings, Footer } from './components';
import './assets/App.css';
import DevTools from 'mobx-react-devtools'
import Loading from './Loading';
import { inject, observer } from 'mobx-react';
@inject("commonStore")
@observer
class App extends Component {
render() {
const { commonStore } = this.props;
console.log(commonStore.loading)
const loading = commonStore.loading ? <Loading /> : ''
return (
<div>
{loading}
<Header />
<Route exact path="/" component={Ballots}/>
<Route path="/new" component={NewBallot}/>

View File

@ -359,14 +359,29 @@ button {
opacity: .2;
transform: scale(0.3); } }
.loader {
.loading {
display: flex;
justify-content: space-between;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%); }
.loader-container {
width: 146px;
margin: -30px 0 0 -81.5px;
padding-top: 50px; }
.loading:before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 146px;
height: 35px;
background-image: url("./images/loading.png");
background-position: 0 0; }
@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) {
.loading:before {
background-image: url("./images/loading.png");
background-size: 100% 100%; } }
.loading-container {
position: fixed;
z-index: 1000000;
left: 0;
@ -374,7 +389,7 @@ button {
top: 0;
bottom: 0;
background-color: rgba(35, 29, 115, 0.8); }
.loader-i {
.loading-i {
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
@ -383,18 +398,17 @@ button {
opacity: .2;
width: 9px;
height: 9px;
margin: 0 8px;
border-radius: 50%;
background-color: #fff; }
.loader-i:nth-child(2) {
.loading-i:nth-child(2) {
animation-delay: .1s; }
.loader-i:nth-child(3) {
.loading-i:nth-child(3) {
animation-delay: .2s; }
.loader-i:nth-child(4) {
.loading-i:nth-child(4) {
animation-delay: .3s; }
.loader-i:nth-child(5) {
.loading-i:nth-child(5) {
animation-delay: .4s; }
.loader-i:nth-child(6) {
.loading-i:nth-child(6) {
animation-delay: .5s; }
.new-form {

View File

@ -7,7 +7,7 @@
@import 'stylesheets/footer';
@import 'stylesheets/header';
@import 'stylesheets/info';
@import 'stylesheets/loader';
@import 'stylesheets/loading';
@import 'stylesheets/new';
@import 'stylesheets/settings';
@import 'stylesheets/socials';

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -359,14 +359,29 @@ button {
opacity: .2;
transform: scale(0.3); } }
.loader {
.loading {
display: flex;
justify-content: space-between;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%); }
.loader-container {
width: 146px;
margin: -30px 0 0 -81.5px;
padding-top: 50px; }
.loading:before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 146px;
height: 35px;
background-image: url("./images/loading.png");
background-position: 0 0; }
@media (min--moz-device-pixel-ratio: 1.3), (-o-min-device-pixel-ratio: 2.6 / 2), (-webkit-min-device-pixel-ratio: 1.3), (min-device-pixel-ratio: 1.3), (min-resolution: 1.3dppx) {
.loading:before {
background-image: url("./images/loading.png");
background-size: 100% 100%; } }
.loading-container {
position: fixed;
z-index: 1000000;
left: 0;
@ -374,7 +389,7 @@ button {
top: 0;
bottom: 0;
background-color: rgba(35, 29, 115, 0.8); }
.loader-i {
.loading-i {
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
@ -383,18 +398,17 @@ button {
opacity: .2;
width: 9px;
height: 9px;
margin: 0 8px;
border-radius: 50%;
background-color: #fff; }
.loader-i:nth-child(2) {
.loading-i:nth-child(2) {
animation-delay: .1s; }
.loader-i:nth-child(3) {
.loading-i:nth-child(3) {
animation-delay: .2s; }
.loader-i:nth-child(4) {
.loading-i:nth-child(4) {
animation-delay: .3s; }
.loader-i:nth-child(5) {
.loading-i:nth-child(5) {
animation-delay: .4s; }
.loader-i:nth-child(6) {
.loading-i:nth-child(6) {
animation-delay: .5s; }
.new-form {

View File

@ -0,0 +1,47 @@
@keyframes fadeOut {
0% {
opacity: .2; }
20% {
opacity: 1;
transform: scale(1); }
100% {
opacity: .2;
transform: scale(0.3); } }
.loader {
display: flex;
justify-content: space-between;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%); }
.loader-container {
position: fixed;
z-index: 1000000;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(35, 29, 115, 0.8); }
.loader-i {
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: fadeOut;
animation-timing-function: linear;
opacity: .2;
width: 9px;
height: 9px;
margin: 0 8px;
border-radius: 50%;
background-color: #fff; }
.loader-i:nth-child(2) {
animation-delay: .1s; }
.loader-i:nth-child(3) {
animation-delay: .2s; }
.loader-i:nth-child(4) {
animation-delay: .3s; }
.loader-i:nth-child(5) {
animation-delay: .4s; }
.loader-i:nth-child(6) {
animation-delay: .5s; }

View File

@ -0,0 +1,79 @@
@keyframes fadeOut {
0% {
opacity: .2;
}
20% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: .2;
transform: scale(0.3);
}
}
.loading {
display: flex;
justify-content: space-between;
position: absolute;
left: 50%;
top: 50%;
width: 146px;
margin: -30px 0 0 -81.5px;
padding-top: 50px;
&:before {
@include image-2x('./images/loading.png');
content: '';
position: absolute;
left: 0;
top: 0;
width: 146px;
height: 35px;
background-image: url('./images/loading.png');
background-position: 0 0;
}
&-container {
position: fixed;
z-index: 1000000;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: fade-out(#231d73, 0.2);
}
&-i {
animation-duration: 2s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: fadeOut;
animation-timing-function: linear;
opacity:.2;
width: 9px;
height: 9px;
border-radius: 50%;
background-color: #fff;
&:nth-child(2) {
animation-delay: .1s;
}
&:nth-child(3) {
animation-delay: .2s;
}
&:nth-child(4) {
animation-delay: .3s;
}
&:nth-child(5) {
animation-delay: .4s;
}
&:nth-child(6) {
animation-delay: .5s;
}
}
}

View File

@ -0,0 +1,65 @@
import React from 'react';
import { inject, observer } from "mobx-react";
@inject("ballotStore")
@observer
export class BallotKeysMetadata extends React.Component {
render() {
const { ballotStore } = this.props;
return (
<div>
<div className="hidden">
<div className="left">
<div className="form-el">
<label for="key">Affected Key</label>
<input type="text" id="key"
value={ballotStore.affectedKey}
onChange={e => ballotStore.changeBallotMetadata(e, "affectedKey", "ballotKeys")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="key">Mining Key</label>
<input type="text" id="key"
value={ballotStore.miningKey}
onChange={e => ballotStore.changeBallotMetadata(e, "miningKey", "ballotKeys")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="left">
<div className="form-el">
<label for="memo">Memo</label>
<input type="text" id="memo"
value={ballotStore.memo}
onChange={e => ballotStore.changeBallotMetadata(e, "memo", "ballotKeys")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="key">Ballot End</label>
<input type="date" id="key"
value={ballotStore.endTime}
onChange={e => ballotStore.changeBallotMetadata(e, "endTime")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
</div>
<hr />
</div>
);
}
}

View File

@ -0,0 +1,41 @@
import React from 'react';
import { inject, observer } from "mobx-react";
@inject("ballotStore")
@observer
export class BallotMinThresholdMetadata extends React.Component {
render() {
const { ballotStore } = this.props;
return (
<div>
<div className="hidden">
<div className="left">
<div className="form-el">
<label for="key">Proposed Value</label>
<input type="number" id="key"
value={ballotStore.affectedKey}
onChange={e => ballotStore.changeBallotMetadata(e, "proposedValue")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="key">Ballot End</label>
<input type="date" id="key"
value={ballotStore.endTime}
onChange={e => ballotStore.changeBallotMetadata(e, "endTime")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
</div>
<hr />
</div>
);
}
}

View File

@ -0,0 +1,41 @@
import React from 'react';
import { inject, observer } from "mobx-react";
@inject("ballotStore")
@observer
export class BallotProxyMetadata extends React.Component {
render() {
const { ballotStore } = this.props;
return (
<div>
<div className="hidden">
<div className="left">
<div className="form-el">
<label for="key">Proposed Address</label>
<input type="text" id="key"
value={ballotStore.affectedKey}
onChange={e => ballotStore.changeBallotMetadata(e, "proposedAddress")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="key">Ballot End</label>
<input type="date" id="key"
value={ballotStore.endTime}
onChange={e => ballotStore.changeBallotMetadata(e, "endTime")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
</div>
<hr />
</div>
);
}
}

View File

@ -0,0 +1,84 @@
import React from 'react';
import { inject, observer } from "mobx-react";
@inject("ballotStore")
@observer
export class KeysTypes extends React.Component {
render() {
const { ballotStore } = this.props;
return (
<div className="hidden">
<div className="left">
<div className="radio-container">
<input type="radio" name="key-control" id="add-key"
value={ballotStore.KeysBallotType.add}
checked={ballotStore.isAddKeysBallotType}
onChange={e => ballotStore.changeKeysBallotType(e, ballotStore.KeysBallotType.add)}
/>
<label for="add-key" className="radio radio_icon radio_add">Add key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
<div className="radio-container">
<input type="radio" name="key-control" id="remove-key"
value={ballotStore.KeysBallotType.remove}
checked={ballotStore.isRemoveKeysBallotType}
onChange={e => ballotStore.changeKeysBallotType(e, ballotStore.KeysBallotType.remove)}
/>
<label for="remove-key" className="radio radio_icon radio_remove">Remove key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
<div className="radio-container">
<input type="radio" name="key-control" id="swap-key"
value={ballotStore.KeysBallotType.swap}
checked={ballotStore.isSwapKeysBallotType}
onChange={e => ballotStore.changeKeysBallotType(e, ballotStore.KeysBallotType.swap)}
/>
<label for="swap-key" className="radio radio_icon radio_swap">Swap key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="radio-container">
<input type="radio" name="keys" id="mining-key"
value={ballotStore.KeyType.mining}
checked={ballotStore.isMiningKeyType}
onChange={e => ballotStore.changeKeyType(e, ballotStore.KeyType.mining)}
/>
<label for="mining-key" className="radio">Mining Key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
<div className="radio-container">
<input type="radio" name="keys" id="payout-key"
value={ballotStore.KeyType.payout}
checked={ballotStore.isPayoutKeyType}
onChange={e => ballotStore.changeKeyType(e, ballotStore.KeyType.payout)}
/>
<label for="payout-key" className="radio">Payout Key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
<div className="radio-container">
<input type="radio" name="keys" id="voting-key"
value={ballotStore.KeyType.voting}
checked={ballotStore.isVotingKeyType}
onChange={e => ballotStore.changeKeyType(e, ballotStore.KeyType.voting)}
/>
<label for="voting-key" className="radio">Voting Key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
</div>
);
}
}

View File

@ -1,8 +1,14 @@
import React from 'react';
import { inject, observer } from "mobx-react";
import Select from 'react-select';
import moment from 'moment';
import swal from 'sweetalert2';
import { Validator } from './Validator';
import { KeysTypes } from './KeysTypes';
import { BallotKeysMetadata } from './BallotKeysMetadata';
import { BallotMinThresholdMetadata } from './BallotMinThresholdMetadata';
import { BallotProxyMetadata } from './BallotProxyMetadata';
@inject("ballotStore", "validatorStore", "contractsStore")
@inject("commonStore", "ballotStore", "validatorStore", "contractsStore")
@observer
export class NewBallot extends React.Component {
constructor(props) {
@ -10,23 +16,118 @@ export class NewBallot extends React.Component {
this.onClick = this.onClick.bind(this);
}
checkValidation() {
const { commonStore, contractsStore, ballotStore, validatorStore } = this.props;
const isAfter = moment(ballotStore.endTime).isAfter(moment());
if (ballotStore.isNewValidatorPersonalData) {
for (let validatorProp in validatorStore) {
if (validatorStore[validatorProp].length === 0) {
swal("Warning!", `Validator ${validatorProp} is empty`, "warning");
commonStore.hideLoading();
return false;
}
}
}
if (!isAfter) {
swal("Warning!", "Ballot end time should be greater than now", "warning");
commonStore.hideLoading();
return false;
}
if (ballotStore.isBallotForKey) {
for (let ballotKeysProp in ballotStore.ballotKeys) {
if (ballotStore.ballotKeys[ballotKeysProp].length === 0) {
swal("Warning!", `Ballot ${ballotKeysProp} is empty`, "warning");
commonStore.hideLoading();
return false;
}
}
let isAffectedKeyAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotKeys.affectedKey);
if (!isAffectedKeyAddress) {
swal("Warning!", `Ballot affectedKey isn't address`, "warning");
commonStore.hideLoading();
return false;
}
let isMiningKeyAddress = contractsStore.web3Instance.isAddress(ballotStore.ballotKeys.miningKey);
if (!isMiningKeyAddress) {
swal("Warning!", `Ballot miningKey isn't address`, "warning");
commonStore.hideLoading();
return false;
}
}
if (ballotStore.isBallotForMinThreshold) {
for (let ballotMinThresholdProp in ballotStore.ballotMinThreshold) {
if (ballotStore.ballotMinThreshold[ballotMinThresholdProp].length === 0) {
swal("Warning!", `Ballot ${ballotMinThresholdProp} is empty`, "warning");
commonStore.hideLoading();
return false;
}
}
}
if (ballotStore.isBallotForProxy) {
for (let ballotProxyProp in ballotStore.ballotProxy) {
if (ballotStore.ballotProxy[ballotProxyProp].length === 0) {
swal("Warning!", `Ballot ${ballotProxyProp} is empty`, "warning");
commonStore.hideLoading();
return false;
}
}
}
return true;
}
onClick() {
const { contractsStore, ballotStore } = this.props;
const curDate = new Date();
const curDateInSeconds = curDate.getSeconds()/1000;
contractsStore.votingToChangeKeys.votingToChangeKeysInstance.methods.createVotingForKeys(
curDateInSeconds,
curDateInSeconds,
ballotStore.affectedKey,
ballotStore.keyType,
ballotStore.miningKey,
ballotStore.ballotType
)
.send({from: contractsStore.votingKey});
const { commonStore, contractsStore, ballotStore } = this.props;
commonStore.showLoading();
const isFormValid = this.checkValidation();
if (isFormValid) {
const curDate = new Date();
const curDateInSeconds = moment(curDate).unix();
const inputToMethod = [
curDateInSeconds,
ballotStore.endTimeUnix,
ballotStore.ballotKeys.affectedKey,
ballotStore.ballotKeys.keyType,
ballotStore.ballotKeys.miningKey,
ballotStore.ballotType
];
console.log(inputToMethod)
contractsStore.votingToChangeKeys.votingToChangeKeysInstance.methods.createVotingForKeys(
...inputToMethod
)
.send({from: contractsStore.votingKey})
.on("error", (e) => {
commonStore.hideLoading();
swal("Error!", e.message, "error");
});
}
}
render() {
const { ballotStore, validatorStore } = this.props;
const { ballotStore } = this.props;
let validator = ballotStore.isNewValidatorPersonalData ? <Validator />: "";
let keysTypes = ballotStore.isBallotForKey ? <KeysTypes />: "";
let metadata
switch (ballotStore.ballotType) {
case ballotStore.BallotType.keys:
metadata = <BallotKeysMetadata />;
break;
case ballotStore.BallotType.minThreshold:
metadata = <BallotMinThresholdMetadata />;
break;
case ballotStore.BallotType.proxy:
metadata = <BallotProxyMetadata />;
break;
}
return (
<section className="container new">
<h1 className="title">New Ballot</h1>
@ -60,212 +161,25 @@ export class NewBallot extends React.Component {
</p>
</div>
</div>
</div>
<hr />
<div className="hidden">
<div className="left">
<div className="form-el">
<label for="full-name">Full Name</label>
<input type="text" id="full-name"
value={validatorStore.fullName}
onChange={e => validatorStore.changeValidatorMetadata(e, "fullName")}
<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 for="ballot-for-proxy" className="radio">Ballot for proxy</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="address">Address</label>
<input type="text" id="address"
value={validatorStore.address}
onChange={e => validatorStore.changeValidatorMetadata(e, "address")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="left">
<div className="form-el">
<label for="us-state">State</label>
<Select id="us-state"
value={validatorStore.state}
onChange={e => validatorStore.changeValidatorMetadata(e, "state")}
options={[
{ value: '', label: '' },
{ value: 'Alabama', label: 'Alabama' },
{ value: 'Florida', label: 'Florida' },
]}
>
</Select>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="zip-code">Zip Code</label>
<input type="number" id="zip-code"
value={validatorStore.zipCode}
onChange={e => validatorStore.changeValidatorMetadata(e, "zipCode")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="left">
<div className="form-el">
<label for="license-id">License ID</label>
<input type="text" id="license-id"
value={validatorStore.licenseID}
onChange={e => validatorStore.changeValidatorMetadata(e, "licenseID")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="license-expiration">License Expiration</label>
<input type="date" id="license-expiration"
value={validatorStore.licenseExpiration}
onChange={e => validatorStore.changeValidatorMetadata(e, "licenseExpiration")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
</div>
<hr />
<div className="hidden">
<div className="left">
<div className="radio-container">
<input type="radio" name="key-control" id="add-key"
value={ballotStore.KeysBallotType.add}
checked={ballotStore.isAddKeysBallotType}
onChange={e => ballotStore.changeKeysBallotType(e, ballotStore.KeysBallotType.add)}
/>
<label for="add-key" className="radio radio_icon radio_add">Add key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
<div className="radio-container">
<input type="radio" name="key-control" id="remove-key"
value={ballotStore.KeysBallotType.remove}
checked={ballotStore.isRemoveKeysBallotType}
onChange={e => ballotStore.changeKeysBallotType(e, ballotStore.KeysBallotType.remove)}
/>
<label for="remove-key" className="radio radio_icon radio_remove">Remove key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
<div className="radio-container">
<input type="radio" name="key-control" id="swap-key"
value={ballotStore.KeysBallotType.swap}
checked={ballotStore.isSwapKeysBallotType}
onChange={e => ballotStore.changeKeysBallotType(e, ballotStore.KeysBallotType.swap)}
/>
<label for="swap-key" className="radio radio_icon radio_swap">Swap key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="radio-container">
<input type="radio" name="keys" id="mining-key"
value={ballotStore.KeyType.mining}
checked={ballotStore.isMiningKeyType}
onChange={e => ballotStore.changeKeyType(e, ballotStore.KeyType.mining)}
/>
<label for="mining-key" className="radio">Mining Key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
<div className="radio-container">
<input type="radio" name="keys" id="payout-key"
value={ballotStore.KeyType.payout}
checked={ballotStore.isPayoutKeyType}
onChange={e => ballotStore.changeKeyType(e, ballotStore.KeyType.payout)}
/>
<label for="payout-key" className="radio">Payout Key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
<div className="radio-container">
<input type="radio" name="keys" id="voting-key"
value={ballotStore.KeyType.voting}
checked={ballotStore.isVotingKeyType}
onChange={e => ballotStore.changeKeyType(e, ballotStore.KeyType.voting)}
/>
<label for="voting-key" className="radio">Voting Key</label>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
</div>
<div className="hidden">
<div className="left">
<div className="form-el">
<label for="memo">Memo</label>
<input type="text" id="memo"
value={ballotStore.memo}
onChange={e => ballotStore.changeBallotMetadata(e, "memo")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="key">Affected Key</label>
<input type="text" id="key"
value={ballotStore.affectedKey}
onChange={e => ballotStore.changeBallotMetadata(e, "affectedKey")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="left">
<div className="form-el">
<label for="key">Mining Key</label>
<input type="text" id="key"
value={ballotStore.miningKey}
onChange={e => ballotStore.changeBallotMetadata(e, "miningKey")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="key">Ballot End</label>
<input type="date" id="key"
value={ballotStore.endTime}
onChange={e => ballotStore.changeBallotMetadata(e, "endTime")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore
</p>
</div>
</div>
</div>
<hr />
{validator}
{keysTypes}
{metadata}
<div className="new-form-footer">
<div className="info">
Minimum 3 from 12 validators required to pass the proposal

View File

@ -0,0 +1,96 @@
import React from 'react';
import { inject, observer } from "mobx-react";
import Select from 'react-select';
@inject("validatorStore")
@observer
export class Validator extends React.Component {
render() {
const { validatorStore } = this.props;
return (
<div>
<div className="hidden">
<div className="left">
<div className="form-el">
<label for="full-name">Full Name</label>
<input type="text" id="full-name"
value={validatorStore.fullName}
onChange={e => validatorStore.changeValidatorMetadata(e, "fullName")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="address">Address</label>
<input type="text" id="address"
value={validatorStore.address}
onChange={e => validatorStore.changeValidatorMetadata(e, "address")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="left">
<div className="form-el">
<label for="us-state">State</label>
<Select id="us-state"
value={validatorStore.state}
onChange={e => validatorStore.changeValidatorMetadata(e, "state")}
options={[
{ value: '', label: '' },
{ value: 'Alabama', label: 'Alabama' },
{ value: 'Florida', label: 'Florida' },
]}
>
</Select>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="zip-code">Zip Code</label>
<input type="number" id="zip-code"
value={validatorStore.zipCode}
onChange={e => validatorStore.changeValidatorMetadata(e, "zipCode")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="left">
<div className="form-el">
<label for="license-id">License ID</label>
<input type="text" id="license-id"
value={validatorStore.licenseID}
onChange={e => validatorStore.changeValidatorMetadata(e, "licenseID")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
<div className="right">
<div className="form-el">
<label for="license-expiration">License Expiration</label>
<input type="date" id="license-expiration"
value={validatorStore.licenseExpiration}
onChange={e => validatorStore.changeValidatorMetadata(e, "licenseExpiration")}
/>
<p className="hint">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
</p>
</div>
</div>
</div>
<hr />
</div>
);
}
}

View File

@ -4,14 +4,15 @@ import { BrowserRouter } from 'react-router-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'mobx-react';
import commonStore from './stores/CommonStore';
import validatorStore from './stores/ValidatorStore';
import ballotStore from './stores/BallotStore';
import contractsStore from './stores/ContractsStore';
import swal from 'sweetalert2';
import getWeb3 from './getWeb3'
import getWeb3 from './getWeb3';
import "babel-polyfill";
const stores = { contractsStore, ballotStore, validatorStore };
const stores = { commonStore, contractsStore, ballotStore, validatorStore };
function generateElement(msg){
let errorNode = document.createElement("div");
@ -27,6 +28,7 @@ class AppMainRouter extends Component {
super(props);
getWeb3().then(async (web3Config) => {
contractsStore.setWeb3Instance(web3Config);
contractsStore.setVotingToChangeKeys(web3Config);
contractsStore.setVotingToChangeMinThreshold(web3Config);
contractsStore.setVotingToChangeProxy(web3Config);

View File

@ -1,4 +1,5 @@
import { observable, computed, action } from 'mobx';
import moment from 'moment';
class BallotStore {
BallotType = {
@ -17,22 +18,37 @@ class BallotStore {
payout: 3
};
@observable ballotType;
@observable keysBallotType;
@observable keyType;
@observable memo;
@observable affectedKey;
@observable miningKey;
@observable endTime;
@observable ballotKeys;
@observable ballotMinThreshold;
@observable ballotProxy;
constructor() {
this.ballotType = this.BallotType.keys;
this.keyType = this.KeyType.mining;
this.keysBallotType = this.KeysBallotType.add;
this.memo = "";
this.affectedKey = "";
this.miningKey = "";
this.endTime = 0;
this.endTime = "";
this.ballotKeys = {
keyType: this.KeyType.mining,
keysBallotType: this.KeysBallotType.add,
memo: "",
affectedKey: "",
miningKey: ""
};
this.ballotMinThreshold = {
proposedValue: ""
};
this.ballotProxy = {
proposedAddress: ""
};
}
@computed get endTimeUnix() {
console.log(this.endTime)
return moment(this.endTime).unix();
}
@computed get isBallotForKey() {
@ -48,27 +64,33 @@ class BallotStore {
}
@computed get isAddKeysBallotType() {
return this.keysBallotType === this.KeysBallotType.add
return this.ballotKeys.keysBallotType === this.KeysBallotType.add
}
@computed get isRemoveKeysBallotType() {
return this.keysBallotType === this.KeysBallotType.remove
return this.ballotKeys.keysBallotType === this.KeysBallotType.remove
}
@computed get isSwapKeysBallotType() {
return this.keysBallotType === this.KeysBallotType.swap
return this.ballotKeys.keysBallotType === this.KeysBallotType.swap
}
@computed get isMiningKeyType() {
return this.keyType === this.KeyType.mining
return this.ballotKeys.keyType === this.KeyType.mining
}
@computed get isVotingKeyType() {
return this.keyType === this.KeyType.voting
return this.ballotKeys.keyType === this.KeyType.voting
}
@computed get isPayoutKeyType() {
return this.keyType === this.KeyType.payout
return this.ballotKeys.keyType === this.KeyType.payout
}
@computed get isNewValidatorPersonalData() {
return ballotStore.isBallotForKey
&& ballotStore.isAddKeysBallotType
&& ballotStore.isMiningKeyType;
}
@action("change ballot type")
@ -80,18 +102,21 @@ class BallotStore {
@action("change keys ballot type")
changeKeysBallotType = (e, _keysBallotType) => {
console.log("change keys ballot type", _keysBallotType);
this.keysBallotType = _keysBallotType;
this.ballotKeys.keysBallotType = _keysBallotType;
}
@action("change affected key type")
changeKeyType = (e, _keyType) => {
console.log("change affected key type", _keyType);
this.keyType = _keyType;
this.ballotKeys.keyType = _keyType;
}
@action("change ballot metadata")
changeBallotMetadata = (e, field) => {
this[field] = e.target.value;
changeBallotMetadata = (e, field, parent) => {
if (parent)
this[parent][field] = e.target.value;
else
this[field] = e.target.value;
console.log("ballot metadata", field, this[field])
}
}

24
src/stores/CommonStore.js Normal file
View File

@ -0,0 +1,24 @@
import { observable, computed, action } from 'mobx';
class CommonStore {
@observable loading;
constructor() {
this.loading = false;
}
@action("show loading")
showLoading() {
this.loading = true;
}
@action("hide loading")
hideLoading() {
this.loading = false;
}
}
const commonStore = new CommonStore();
export default commonStore;
export { CommonStore };

View File

@ -12,6 +12,7 @@ class ContractsStore {
@observable votingToChangeProxy;
@observable votingKey;
@observable miningKey;
@observable web3Instance;
constructor() {
this.votingToChangeKeys = null;
@ -21,6 +22,11 @@ class ContractsStore {
this.miningKey = null;
}
@action("Set web3Instance")
setWeb3Instance = (web3Config) => {
this.web3Instance = web3Config.web3Instance;
}
@action("Set VotingToChangeKeys contract")
setVotingToChangeKeys = (web3Config) => {
this.votingToChangeKeys = new VotingToChangeKeys({