Oracles network Voting Dapp. Initial commit.

This commit is contained in:
viktor 2017-06-14 15:04:12 +03:00
commit 7312cda57f
72 changed files with 5179 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules/
.DS_Store

890
README.md Normal file

File diff suppressed because one or more lines are too long

BIN
assets/images/bg_footer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
assets/images/bg_header.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
assets/images/loading.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
assets/images/logos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
assets/images/logos@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
assets/images/person.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
assets/images/socials.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,44 @@
function addBallot(api, func, ballotViewObj, address, contractAddr, cb) {
var funcHex = func.hexEncode();
var funcParamsNumber = 7;
var standardLength = 32;
SHA3Encrypt(api, funcHex, function(funcEncode) {
var funcEncodePart = funcEncode.substring(0,10);
var parameterLocation = standardLength * funcParamsNumber;
if (ballotViewObj.miningKey.indexOf("0x") > -1)
ballotViewObj.miningKey = ballotViewObj.miningKey.substr(2);
ballotViewObj.miningKey = ballotViewObj.miningKey.toLowerCase();
if (ballotViewObj.owner.indexOf("0x") > -1)
ballotViewObj.owner = ballotViewObj.owner.substr(2);
ballotViewObj.owner = ballotViewObj.owner.toLowerCase();
ballotViewObj.addAction = JSON.parse(ballotViewObj.addAction);
var memoHex = "0x" + toUnifiedLengthRight(toHexString(toUTF8Array(ballotViewObj.memo)));
var data = funcEncodePart
+ toUnifiedLengthLeft(ballotViewObj.ballotID.toString(16))
+ toUnifiedLengthLeft(ballotViewObj.owner)
+ toUnifiedLengthLeft(ballotViewObj.miningKey)
+ toUnifiedLengthLeft(ballotViewObj.affectedKey)
+ toUnifiedLengthLeft(ballotViewObj.affectedKeyType.toString(16))
+ toUnifiedLengthLeft((+ballotViewObj.addAction).toString())
+ toUnifiedLengthLeft(parameterLocation.toString(16))
+ toUnifiedLengthLeft(bytesCount(ballotViewObj.memo).toString(16)) + memoHex.substring(2);
estimateGas(api, address, contractAddr, data, function(estimatedGas, err) {
if (err) return cb(null, err);
estimatedGas += 100000;
sendTx(api, address, contractAddr, data, estimatedGas, function(txHash, err) {
if (err) return cb(txHash, err);
cb(txHash);
});
});
});
}

View File

@ -0,0 +1,43 @@
function addValidator(api, func, validatorViewObj, address, contractAddr, cb) {
var funcHex = func.hexEncode();
var funcParamsNumber = 7;
var standardLength = 32;
SHA3Encrypt(api, funcHex, function(funcEncode) {
var funcEncodePart = funcEncode.substring(0,10);
if (validatorViewObj.miningKey.indexOf("0x") > -1)
validatorViewObj.miningKey = validatorViewObj.miningKey.substr(2);
validatorViewObj.miningKey = validatorViewObj.miningKey.toLowerCase();
var fullNameHex = "0x" + toUnifiedLengthRight(toHexString(toUTF8Array(validatorViewObj.fullName)));
var streetNameHex = "0x" + toUnifiedLengthRight(toHexString(toUTF8Array(validatorViewObj.streetName)));
var stateHex = "0x" + toUnifiedLengthRight(toHexString(toUTF8Array(validatorViewObj.state)));
var parameterLocation1 = standardLength * funcParamsNumber;
var parameterLocation2 = parameterLocation1 + standardLength*(countRows(fullNameHex));
var parameterLocation3 = parameterLocation2 + standardLength*(countRows(streetNameHex));
var data = funcEncodePart
+ toUnifiedLengthLeft(validatorViewObj.miningKey)
+ toUnifiedLengthLeft(validatorViewObj.zip.toString(16))
+ toUnifiedLengthLeft(validatorViewObj.licenseID.toString(16))
+ toUnifiedLengthLeft(validatorViewObj.licenseExpiredAt.toString(16))
+ toUnifiedLengthLeft(parameterLocation1.toString(16))
+ toUnifiedLengthLeft(parameterLocation2.toString(16))
+ toUnifiedLengthLeft(parameterLocation3.toString(16))
+ toUnifiedLengthLeft(bytesCount(validatorViewObj.fullName).toString(16)) + fullNameHex.substring(2)
+ toUnifiedLengthLeft(bytesCount(validatorViewObj.streetName).toString(16)) + streetNameHex.substring(2)
+ toUnifiedLengthLeft(bytesCount(validatorViewObj.state).toString(16)) + stateHex.substring(2);
estimateGas(api, address, contractAddr, data, function(estimatedGas, err) {
if (err) return cb(null, err);
estimatedGas += 100000;
sendTx(api, address, contractAddr, data, estimatedGas, function(txHash, err) {
if (err) return cb(txHash, err);
cb(txHash);
});
});
});
}

View File

@ -0,0 +1,9 @@
function showAlert(err, msg) {
if (err.type != "REQUEST_REJECTED") {
swal({
title: "Error",
text: msg,
type: "error"
});
}
}

View File

@ -0,0 +1,5 @@
function generateBallotID() {
var min = 10000000;
var max = 99999999;
return Math.floor(Math.random() * (max - min)) + min;
}

View File

@ -0,0 +1,123 @@
function SHA3Encrypt(api, str, cb) {
api._web3.sha3(str).then(function(strEncode) {
cb(strEncode, null);
}).catch(function(err) {
console.log(err);
cb("", err);
});
}
function estimateGas(api, acc, contractAddr, data, cb) {
api.eth.estimateGas({
from: acc,
data: data,
to: contractAddr
}).then(function(res) {
var gasWillUsed = res.c[0];
gasWillUsed += 10000;
cb(gasWillUsed);
}).catch(function(err) {
console.log(err);
cb(null, err);
});
}
function sendTx(api, acc, contractAddr, data, estimatedGas, cb) {
api.eth.sendTransaction({
from: acc,
data: data,
to: contractAddr,
gas: estimatedGas
}).then(function(txHash) {
cb(txHash);
}).catch(function(err) {
console.log(err);
cb(null, err);
});
}
function call(api, acc, contractAddr, data, cb) {
var props;
if (acc) props = { from: acc, data: data, to: contractAddr };
else props = { data: data, to: contractAddr };
api.eth.call(props)
.then(function(data) {
cb(data);
}).catch(function(err) {
console.log(err);
cb(null, err);
});
}
function getTxCallBack(txHash, cb) {
web3.eth.getTransaction(txHash, function(err, txDetails) {
if (err)
console.log(err);
if (!txDetails.blockNumber) {
setTimeout(function() {
getTxCallBack(txHash, cb);
}, 2000)
} else cb();
});
};
function getContractStringDataFromAddressKey(api, acc, func, inputVal, i, contractAddr, cb) {
var funcHex = func.hexEncode();
var funcParamsNumber = 1;
var standardLength = 32;
var parameterLocation = standardLength * funcParamsNumber;
SHA3Encrypt(api, funcHex, function(funcEncode) {
var funcEncodePart = funcEncode.substring(0,10);
var data = funcEncodePart
+ toUnifiedLengthLeft(inputVal);
call(api, acc, contractAddr, data, function(respHex) {
console.log(respHex);
cb(i, hex2a(respHex));
});
});
}
function getContractIntDataFromAddressKey(api, acc, func, inputVal, i, contractAddr, cb) {
var funcHex = func.hexEncode();
var funcParamsNumber = 1;
var standardLength = 32;
var parameterLocation = standardLength * funcParamsNumber;
SHA3Encrypt(api, funcHex, function(funcEncode) {
var funcEncodePart = funcEncode.substring(0,10);
var data = funcEncodePart
+ toUnifiedLengthLeft(inputVal);
call(api, acc, contractAddr, data, function(respHex) {
cb(i, parseInt(respHex, 16));
});
});
}
function getContractAddressDataFromAddressKey(api, acc, func, inputVal, i, contractAddr, cb) {
var funcHex = func.hexEncode();
var funcParamsNumber = 1;
var standardLength = 32;
var parameterLocation = standardLength * funcParamsNumber;
SHA3Encrypt(api, funcHex, function(funcEncode) {
var funcEncodePart = funcEncode.substring(0,10);
var data = funcEncodePart
+ toUnifiedLengthLeft(inputVal);
call(api, acc, contractAddr, data, function(respHex) {
cb(i, respHex);
});
});
}

View File

@ -0,0 +1,93 @@
function hex2a(hexx) {
var hex = hexx.toString();//force conversion
var str = '';
for (var i = 0; i < hex.length; i += 2) {
var code = parseInt(hex.substr(i, 2), 16);
if (code != 0 && !isNaN(code)) {
str += String.fromCharCode(code);
}
}
str = str.substr(2);
return str;
}
function toUnifiedLengthLeft(strIn) {//for numbers
var strOut = "";
for (var i = 0; i < 64 - strIn.length; i++) {
strOut += "0"
}
strOut += strIn;
return strOut;
}
function countRows(strIn) {
var rowsCount = 0;
if (strIn.length%64 > 0)
rowsCount = parseInt(strIn.length/64) + 1;
else
rowsCount = parseInt(strIn.length/64);
return rowsCount;
}
function toUnifiedLengthRight(strIn) {//for strings
var strOut = "";
strOut += strIn;
var rowsCount = countRows(strIn);
for (var i = 0; i < rowsCount*64 - strIn.length; i++) {
strOut += "0"
}
return strOut;
}
String.prototype.hexEncode = function(){
var hex, i;
var result = "";
for (i=0; i<this.length; i++) {
hex = this.charCodeAt(i).toString(16);
result += hex.slice(-4);
}
return result
}
function toUTF8Array(str) {
var utf8 = [];
for (var i=0; i < str.length; i++) {
var charcode = str.charCodeAt(i);
if (charcode < 0x80) utf8.push(charcode);
else if (charcode < 0x800) {
utf8.push(0xc0 | (charcode >> 6),
0x80 | (charcode & 0x3f));
}
else if (charcode < 0xd800 || charcode >= 0xe000) {
utf8.push(0xe0 | (charcode >> 12),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
// surrogate pair
else {
i++;
// UTF-16 encodes 0x10000-0x10FFFF by
// subtracting 0x10000 and splitting the
// 20 bits of 0x0-0xFFFFF into two halves
charcode = 0x10000 + (((charcode & 0x3ff)<<10)
| (str.charCodeAt(i) & 0x3ff));
utf8.push(0xf0 | (charcode >>18),
0x80 | ((charcode>>12) & 0x3f),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
}
return utf8;
}
function toHexString(byteArray) {
return byteArray.map(function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('')
}
function bytesCount(s) {
return encodeURI(s).split(/%..|./).length - 1;
}

View File

@ -0,0 +1,23 @@
function createCookie(name, value, days) {
var expires;
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
} else {
expires = "";
}
document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
}
function readCookie(name) {
var nameEQ = encodeURIComponent(name) + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
}
return null;
}

View File

@ -0,0 +1,101 @@
function formatDate(date, format, utc) {
//var MMMM = ["\x00", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var MMMM = ["\x00", "января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"];
var MMM = ["\x01", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var dddd = ["\x02", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var ddd = ["\x03", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
function ii(i, len) {
var s = i + "";
len = len || 2;
while (s.length < len) s = "0" + s;
return s;
}
var y = utc ? date.getUTCFullYear() : date.getFullYear();
format = format.replace(/(^|[^\\])yyyy+/g, "$1" + y);
format = format.replace(/(^|[^\\])yy/g, "$1" + y.toString().substr(2, 2));
format = format.replace(/(^|[^\\])y/g, "$1" + y);
var M = (utc ? date.getUTCMonth() : date.getMonth()) + 1;
format = format.replace(/(^|[^\\])MMMM+/g, "$1" + MMMM[0]);
format = format.replace(/(^|[^\\])MMM/g, "$1" + MMM[0]);
format = format.replace(/(^|[^\\])MM/g, "$1" + ii(M));
format = format.replace(/(^|[^\\])M/g, "$1" + M);
var d = utc ? date.getUTCDate() : date.getDate();
format = format.replace(/(^|[^\\])dddd+/g, "$1" + dddd[0]);
format = format.replace(/(^|[^\\])ddd/g, "$1" + ddd[0]);
format = format.replace(/(^|[^\\])dd/g, "$1" + ii(d));
format = format.replace(/(^|[^\\])d/g, "$1" + d);
var H = utc ? date.getUTCHours() : date.getHours();
format = format.replace(/(^|[^\\])HH+/g, "$1" + ii(H));
format = format.replace(/(^|[^\\])H/g, "$1" + H);
var h = H > 12 ? H - 12 : H == 0 ? 12 : H;
format = format.replace(/(^|[^\\])hh+/g, "$1" + ii(h));
format = format.replace(/(^|[^\\])h/g, "$1" + h);
var m = utc ? date.getUTCMinutes() : date.getMinutes();
format = format.replace(/(^|[^\\])mm+/g, "$1" + ii(m));
format = format.replace(/(^|[^\\])m/g, "$1" + m);
var s = utc ? date.getUTCSeconds() : date.getSeconds();
format = format.replace(/(^|[^\\])ss+/g, "$1" + ii(s));
format = format.replace(/(^|[^\\])s/g, "$1" + s);
var f = utc ? date.getUTCMilliseconds() : date.getMilliseconds();
format = format.replace(/(^|[^\\])fff+/g, "$1" + ii(f, 3));
f = Math.round(f / 10);
format = format.replace(/(^|[^\\])ff/g, "$1" + ii(f));
f = Math.round(f / 10);
format = format.replace(/(^|[^\\])f/g, "$1" + f);
var T = H < 12 ? "AM" : "PM";
format = format.replace(/(^|[^\\])TT+/g, "$1" + T);
format = format.replace(/(^|[^\\])T/g, "$1" + T.charAt(0));
var t = T.toLowerCase();
format = format.replace(/(^|[^\\])tt+/g, "$1" + t);
format = format.replace(/(^|[^\\])t/g, "$1" + t.charAt(0));
var tz = -date.getTimezoneOffset();
var K = utc || !tz ? "Z" : tz > 0 ? "+" : "-";
if (!utc) {
tz = Math.abs(tz);
var tzHrs = Math.floor(tz / 60);
var tzMin = tz % 60;
K += ii(tzHrs) + ":" + ii(tzMin);
}
format = format.replace(/(^|[^\\])K/g, "$1" + K);
var day = (utc ? date.getUTCDay() : date.getDay()) + 1;
format = format.replace(new RegExp(dddd[0], "g"), dddd[day]);
format = format.replace(new RegExp(ddd[0], "g"), ddd[day]);
format = format.replace(new RegExp(MMMM[0], "g"), MMMM[M]);
format = format.replace(new RegExp(MMM[0], "g"), MMM[M]);
format = format.replace(/\\(.)/g, "$1");
return format;
};
function getDateDiff(dateStart, dateEnd) {
var periodInMinutes = Math.floor((dateEnd - dateStart)/60);
if (periodInMinutes <= 0) {
return "00:00";
}
var hours = Math.floor(periodInMinutes/60);
var hoursStr = hours.toString();
if (hours < 9)
hoursStr = "0" + hours.toString();
var minutes = periodInMinutes%60;
var minutesStr = minutes.toString();
if (minutes < 9)
minutesStr = "0" + minutes.toString();
return hoursStr + ":" + minutesStr;
}

View File

@ -0,0 +1,26 @@
function filterBallots(searchInput) {
return ballotsArrayFiltered.map(function(ballot, i) {
if (ballot) {
var searchValidated = validateSearch(ballot, searchInput.toLowerCase());
if (!searchValidated) return null;
else return ballot;
} else return null;
})
}
function validateSearch(ballot, searchInput) {
var ballotID = Object.keys(ballot)[0];
var ballotObj = ballot[ballotID];
if (ballotObj["memo"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (ballotObj["fullName"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (ballotObj["address"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (ballotObj["state"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (ballotObj["zip"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (ballotObj["zip"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (ballotObj["licenseID"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (ballotObj["licenseExpiredAt"].toLowerCase().indexOf(searchInput) > -1) return true;
else if (ballotObj["miningKey"].toString().indexOf(searchInput) > -1) return true;
return false;
}

View File

@ -0,0 +1,113 @@
function getBallots(api, func, acc, contractAddress, cb) {
var funcHex = func.hexEncode();
SHA3Encrypt(api, funcHex, function(funcEncode) {
var funcEncodePart = funcEncode.substring(0,10);
var data = funcEncodePart;
call(api, null, contractAddress, data, function(ballotsResp) {
ballotsResp = ballotsResp.substring(2, ballotsResp.length);
var ballotsArray = [];
var item = "";
for (var i = 0; i < ballotsResp.length; i++) {
item+=ballotsResp[i];
if ((i + 1)%64 == 0) {
item = item.substr(item.length - 40, 40);
ballotsArray.push(item);
item = "";
}
}
ballotsArray.shift();
ballotsArray.shift(); //number of elements
if (ballotsArray.length == 0) {
cb(ballotsArray);
return;
}
var ballotsArrayOut = [];
var iasync = [];
var ballotDataCount = 10;
for (var i = 0; i < ballotsArray.length; i++) {
iasync.push(0);
getBallotMemo(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("memo", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
ballotCreatedAt(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("createdAt", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
getBallotVotingStart(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("votingStart", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
getBallotVotingEnd(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("votingEnd", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
getVotesFor(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("votesFor", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
getVotesAgainst(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("votesAgainst", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
getBallotAction(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("action", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
ballotIsVoted(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("voted", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
getBallotMiningKey(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("miningKey", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
getBallotOwner(api, acc, ballotsArray[i], i, contractAddress, function(_i, resp) {
iasync[_i]++;
ballotsArrayOut = getBallotsPropertyCallback("owner", api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb);
});
}
});
});
}
function getBallotsPropertyCallback(prop, api, contractAddress, resp, _i, iasync, ballotsArray, ballotDataCount, ballotsArrayOut, cb) {
if (!ballotsArrayOut[_i]) {
var ballot = {};
ballot[ballotsArray[_i]] = {};
ballot[ballotsArray[_i]][prop] = resp;
ballotsArrayOut.push(ballot);
} else ballotsArrayOut[_i][ballotsArray[_i]][prop] = resp;
var finish = true;
for (var j = 0; j < iasync.length; j++) {
if (iasync[j] < ballotDataCount) {
finish = false;
break;
}
}
if (finish) {
for (var j = 0; j < ballotsArray.length; j++) {
var jasync = 0;
var miningKey = ballotsArrayOut[j][ballotsArray[j]].miningKey;
if (miningKey.length > 40) miningKey = miningKey.substr(miningKey.length - 40);
}
cb(ballotsArrayOut);
return false;
} else return ballotsArrayOut;
}

View File

@ -0,0 +1,116 @@
function getBallotMemo(api, acc, ballotID, i, contractAddr, cb) {
var func = "getBallotMemo(uint256)";
getContractStringDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function ballotCreatedAt(api, acc, ballotID, i, contractAddr, cb) {
var func = "ballotCreatedAt(uint256)";
getContractIntDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function getBallotVotingStart(api, acc, ballotID, i, contractAddr, cb) {
var func = "getBallotVotingStart(uint256)";
getContractIntDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function getBallotVotingEnd(api, acc, ballotID, i, contractAddr, cb) {
var func = "getBallotVotingEnd(uint256)";
getContractIntDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function getVotesFor(api, acc, ballotID, i, contractAddr, cb) {
var func = "getVotesFor(uint256)";
getContractIntDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function getVotesAgainst(api, acc, ballotID, i, contractAddr, cb) {
var func = "getVotesAgainst(uint256)";
getContractIntDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function getBallotAction(api, acc, ballotID, i, contractAddr, cb) {
var func = "getBallotAction(uint256)";
getContractIntDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function ballotIsVoted(api, acc, ballotID, i, contractAddr, cb) {
var func = "ballotIsVoted(uint256)";
getContractIntDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function getBallotMiningKey(api, acc, ballotID, i, contractAddr, cb) {
var func = "getBallotMiningKey(uint256)";
getContractAddressDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function getBallotOwner(api, acc, ballotID, i, contractAddr, cb) {
var func = "getBallotOwner(uint256)";
getContractStringDataFromAddressKey(api, acc, func, ballotID, i, contractAddr, cb);
}
function getBallotData(api, acc, ballotID, contractAddress, cb) {
var iasync = 0;
var ballotDataCount = 10;
var ballot = {};
getBallotMemo(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("memo", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
ballotCreatedAt(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("createdAt", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
getBallotVotingStart(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("votingStart", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
getBallotVotingEnd(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("votingEnd", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
getVotesFor(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("votesFor", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
getVotesAgainst(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("votesAgainst", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
getBallotAction(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("action", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
ballotIsVoted(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("voted", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
getBallotMiningKey(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("miningKey", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
getBallotOwner(api, acc, ballotID, null, contractAddress, function(_i, resp) {
iasync++;
ballot = getBallotPropertyCallback("owner", api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb);
});
}
function getBallotPropertyCallback(prop, api, contractAddress, ballotID, resp, iasync, ballot, ballotDataCount, cb) {
if (Object.keys(ballot).length == 0) {
ballot[ballotID] = {};
ballot[ballotID][prop] = resp;
} else ballot[ballotID][prop] = resp;
if (iasync == ballotDataCount) {
cb(ballot[ballotID]);
return false;
} else return ballot;
}

View File

@ -0,0 +1,119 @@
function getBallotView(acc, ballotID, ballotPropsObj, isVotingEnabled, api, contractAddress, cb) {
if (ballotPropsObj) {
return ballotViewObject(ballotID, ballotPropsObj, isVotingEnabled);
} else {
getBallotData(api, acc, ballotID, contractAddress, function(ballotPropsObj) {
cb(ballotViewObject(ballotID, ballotPropsObj, isVotingEnabled));
});
}
}
function ballotViewObject(ballotID, ballotPropsObj, isVotingEnabled) {
//votes
var votesFor = ballotPropsObj["votesFor"];
var votesAgainst = ballotPropsObj["votesAgainst"];
var votesTotal = ballotPropsObj["votesFor"] + ballotPropsObj["votesAgainst"];
var votesForPerc = 0;
var votesAgainstPerc = 0;
if (votesTotal > 0) {
votesForPerc = Math.round((votesFor / votesTotal) * 100, 0);
votesAgainstPerc = Math.round((votesAgainst / votesTotal) * 100, 0);
}
//action
var actionDN;
switch(ballotPropsObj["action"]) {
case 0:
actionDN = "Remove Notary";
break;
case 1:
actionDN = "Add new Notary";
break;
}
//miningKey
var miningKey = ballotPropsObj["miningKey"];
if (miningKey.length > 40) miningKey = "0x" + miningKey.substr(miningKey.length - 40);
//time to start/end
var timeToVotingStart = getDateDiff(Math.floor(Date.now() / 1000), parseInt(ballotPropsObj["votingStart"]));
var timeToVotingEnd = getDateDiff(Math.floor(Date.now() / 1000), parseInt(ballotPropsObj["votingEnd"]));
var timeToVotingStartEnd = timeToVotingStart;
var timeToVotingStartEndLabel = "To start";
if (timeToVotingStart == "00:00") {
timeToVotingStartEnd = timeToVotingEnd;
timeToVotingStartEndLabel = "To end"
}
return `<div class="vote-i" ballot-id="` + ballotID + `">
<div class="vote-header">
<div class="vote-person left">
<img src="./assets/images/person.png" alt="" class="vote-person-img">
<p class="vote-person-name">` + (ballotPropsObj["owner"]?ballotPropsObj["owner"]:`Allison Williams`) + `</p>
<div class="vote-person-create">` + formatDate(new Date(parseInt(ballotPropsObj["createdAt"])*1000), "MM/dd/yyyy h:mm TT") + `</div>
</div>
<div class="vote-time right">
<div class="vote-time-timer">` + timeToVotingStartEnd + `</div>
<div class="vote-time-to">` + timeToVotingStartEndLabel + `</div>
</div>
` + (isVotingEnabled?``:`<a href="#" class="vote-now right" ballot-id="` + ballotID + `" ` + (timeToVotingEnd == "00:00"?`hidden`:``) + `>Vote now</a>`) + `
</div>
<div class="vote-body">
<div class="vote-body-i">
<p class="vote-body-title">
Proposal
<span class="vote-tooltip-container">
<span class="vote-tooltip-icon"></span>
<span class="vote-tooltip">
<span class="vote-tooltip-text">
<span class="vote-tooltip-title">How does it work?</span>
<span class="vote-tooltip-description">
If you are a validator in Oracles network you can sign a vote with your voting key.
Please refer to voting FAQ on
<a href="https://forums.notarycoin.com">https://forums.notarycoin.com</a>
</span>
</span>
<span class="vote-tooltip-shadow"></span>
</span>
</span>
</p>
<p class="vote-body-description">
` + ballotPropsObj["memo"] + `
</p>
</div>
<div class="vote-body-i">
<p class="vote-body-title">Mining key</p>
<p class="vote-body-description">
` + miningKey + `
</p>
</div>
<div class="vote-body-i">
<p class="vote-body-title">Title</p>
<p class="vote-body-description">
` + actionDN + `
</p>
</div>
</div>
<div class="vote-rating">
<div class="vote-rating-i left">
<p class="vote-rating-value left">Yes</p>
<div class="vote-rating-got right">
<strong>` + votesForPerc + `%</strong>
<p>Votes: ` + votesFor + `</p>
</div>
<div class="vote-rating-scale vote-rating-scale_yes">
<div class="vote-rating-scale-active" style="width: ` + votesForPerc + `%"></div>
</div>`
+ (isVotingEnabled? `<a href="#" class="vote-button vote-rating-yes left">Vote</a>`:``) +
`</div>
<div class="vote-rating-i right">
<p class="vote-rating-value left">No</p>
<div class="vote-button vote-rating-got right">
<strong>` + votesAgainstPerc + `%</strong>
<p>Votes: ` + votesAgainst + `</p>
</div>
<div class="vote-rating-scale vote-rating-scale_no">
<div class="vote-rating-scale-active" style="width: ` + votesAgainstPerc + `%"></div>
</div>`
+ (isVotingEnabled? `<a href="#" class="vote-button vote-rating-no right">Vote</a>`:``) +
`</div>
</div>
</div>`;
}

View File

@ -0,0 +1,281 @@
"use strict";
$(function() {
$(".loading-container").hide();
var api = window.parity.api;
var config;
var ballotsArrayFiltered = [];
var accounts = web3.eth.accounts;
var votingKey;
if (readCookie('votingKey'))
votingKey = readCookie('votingKey');
for (var i = 0; i < accounts.length; i++) {
if (readCookie('votingKey') == accounts[i] || (!readCookie('votingKey') && i == 0))
$option = "<option name='key' value=" + accounts[i] + " selected>" + accounts[i] + "</option>"
else
$option = "<option name='key' value=" + accounts[i] + ">" + accounts[i] + "</option>"
$(".key-select").append($option);
}
//key select onchange event
$(".key-select").change(function() {
createCookie('votingKey', $(this).val(), 365);
votingKey = $(this).val();
});
$.getJSON("./assets/javascripts/config.json", function(_config) {
config = _config;
//choose key button onclick event
$(".choose-key-button").on("click", function() {
ballotsNavPan();
$(".key-content").addClass("hidden");
$(".content").removeClass("hidden");
$(".container.vote").empty();
$(".container.new-ballot").addClass("hidden");
$(".container.vote").removeClass("hidden");
$(".loading-container").hide();
votingKey = $(".key-select").val();
getBallots(api,
"getBallots()",
votingKey,
config.Ethereum[config.environment].contractAddress,
function(_ballotsArray) {
ballotsArrayFiltered = _ballotsArray;
getBallotsCallBack(_ballotsArray);
}
);
// ballots list nav filters onclick events
$(".nav-i").on("click", function() {
$(".search-input").val('');
$(".loading-container").show();
if ($(this).hasClass("nav-i_actual")) {
$(".nav-i").removeClass("nav-i_active");
$(this).addClass("nav-i_active");
getBallotsArray();
} else if ($(this).hasClass("nav-i_unanswered")) {
$(".nav-i").removeClass("nav-i_active");
$(this).addClass("nav-i_active");
getBallotsArray({filter: "unanswered"});
} else if ($(this).hasClass("nav-i_expired")) {
$(".nav-i").removeClass("nav-i_active");
$(this).addClass("nav-i_active");
getBallotsArray({filter: "expired"});
}
});
// search input onkeyup event
$(".search-input").on("keyup", function() {
var searchInput = $(this).val();
var ballotsArrayFiltered = filterBallots(searchInput);
$(".container.vote").empty();
getBallotsCallBack(ballotsArrayFiltered);
});
});
});
//back button onclick event
$(".back").on("click", function() {
ballotsNavPan();
getBallotsArray();
});
//settings button onclick event
$(".header-settings").on("click", function() {
$(".key-content").removeClass("hidden");
$(".content").addClass("hidden");
});
//new ballot button onclick event
$(".header-new-ballot").on("click", function() {
$(".key-content").addClass("hidden");
$(".content").removeClass("hidden");
$(".container.new-ballot").removeClass("hidden");
$(".container.vote").addClass("hidden");
$(".container.new-ballot").empty();
$(".container.new-ballot").load("./newBallot.html", function() {
newBallotNavPan();
$(".new-ballot-add").on("click", function() {
$(".loading-container").show();
var ballotViewObj = {
ballotID: generateBallotID(),
memo: $("#memo").val(),
miningKey: $("#key").val(),
affectedKey: $("#key").val(),
affectedKeyType: 0,
owner: votingKey,
addAction: $("input[name=type]:checked").val()
};
var validatorViewObj = {
miningKey: $("#key").val(),
fullName: $("#full-name").val(),
streetName: $("#address").val(),
state: $("#state").val(),
zip: $("#zip").val(),
licenseID: $("#license-id").val(),
licenseExpiredAt: new Date($("#license-expiration").val()).getTime() / 1000,
};
var isAddress = web3.isAddress($("#key").val());
if (!isAddress) {
$(".loading-container").hide();
showAlert(err, "Incorrect mining key");
return;
}
addBallot(api,
"addBallot(uint256,address,address,address,uint256,bool,string)",
ballotViewObj,
votingKey,
config.Ethereum[config.environment].contractAddress,
function(txHash, err) {
if (err) {
$(".loading-container").hide();
showAlert(err, err.message);
return;
}
addValidator(api,
"addValidator(address,uint256,uint256,uint256,string,string,string)",
validatorViewObj,
votingKey,
config.Ethereum[config.environment].contractAddress,
function(txHash, err) {
if (err) {
$(".loading-container").hide();
showAlert(err, err.message);
return;
}
getTxCallBack(txHash, function() {
$(".loading-container").hide();
$(".back").trigger("click");
});
}
);
}
);
});
});
});
function getBallotsCallBack(_ballotsArray) {
for(var i = 0; i < _ballotsArray.length; i++) {
var ballot = _ballotsArray[i];
if (ballot) {
var ballotID = Object.keys(ballot)[0];
var ballotPropsObj = ballot[ballotID];
var ballotView = getBallotView(votingKey, ballotID, ballotPropsObj, false);
$(".container.vote").append(ballotView);
}
}
//vote now button onclick event
$(".vote-now").on("click", function() {
getBallotView(
votingKey,
$(this).attr("ballot-id"),
null,
true,
api,
config.Ethereum[config.environment].contractAddress,
function(ballotView)
{
$(".container.vote").empty();
$(".container.vote").append(ballotView);
newBallotNavPan();
//vote button onclick event
$(".vote-button").on("click", function(e) {
voteButtonClick(e, $(this));
});
});
});
}
function voteButtonClick(e, $this) {
$(".loading-container").show();
var voteFor = $this.hasClass("vote-rating-yes")?true:false;
var ballotID = $this.closest(".vote-i").attr("ballot-id");
vote(api,
"vote(uint256,bool)",
ballotID,
voteFor,
votingKey,
config.Ethereum[config.environment].contractAddress,
function(txHash, err) {
if (err) {
$(".loading-container").hide();
showAlert(err, "You are already voted");
return;
}
getTxCallBack(txHash, function() {
$(".loading-container").hide();
$(".back").trigger("click");
});
}
);
}
//change to new ballot navigation pan
function newBallotNavPan() {
$(".nav").addClass("hidden");
$(".search-form").addClass("hidden");
$(".back").removeClass("hidden");
}
//change to ballots navigation pan
function ballotsNavPan() {
$(".nav").removeClass("hidden");
$(".search-form").removeClass("hidden");
$(".back").addClass("hidden");
}
function getBallotsArray(filterObj) {
$(".container.new-ballot").addClass("hidden");
$(".container.vote").removeClass("hidden");
$(".container.vote").empty();
getBallots(api,
"getBallots()",
votingKey,
config.Ethereum[config.environment].contractAddress,
function(_ballotsArray) {
$(".loading-container").hide();
if (!filterObj) {
ballotsArrayFiltered = _ballotsArray;
getBallotsCallBack(ballotsArrayFiltered);
return;
}
if (filterObj.filter == "expired") {
var _ballotsArrayFiltered = [];
for (var i = 0; i < _ballotsArray.length; i++) {
var ballot = _ballotsArray[i];
var ballotID = Object.keys(ballot)[0];
if (new Date(ballot[ballotID].votingEnd*1000) < new (Date)) { //expired
_ballotsArrayFiltered.push(ballot);
}
}
ballotsArrayFiltered = _ballotsArrayFiltered;
getBallotsCallBack(ballotsArrayFiltered);
} else if (filterObj.filter == "unanswered") {
var _ballotsArrayFiltered = [];
for (var i = 0; i < _ballotsArray.length; i++) {
var ballot = _ballotsArray[i];
var ballotID = Object.keys(ballot)[0];
if (!ballot[ballotID].voted && (new Date(ballot[ballotID].votingEnd*1000) >= new (Date))) {
_ballotsArrayFiltered.push(ballot);
}
}
ballotsArrayFiltered = _ballotsArrayFiltered;
getBallotsCallBack(ballotsArrayFiltered);
}
}
);
}
});

View File

@ -0,0 +1,23 @@
function vote(api, func, ballotID, action, address, contractAddr, cb) {
var funcHex = func.hexEncode();
var funcParamsNumber = 2;
var standardLength = 32;
SHA3Encrypt(api, funcHex, function(funcEncode) {
var funcEncodePart = funcEncode.substring(0,10);
var data = funcEncodePart
+ toUnifiedLengthLeft(ballotID.toString(16))
+ toUnifiedLengthLeft((+action).toString());
estimateGas(api, address, contractAddr, data, function(estimatedGas, err) {
if (err) return cb(null, err);
estimatedGas += 100000;
sendTx(api, address, contractAddr, data, estimatedGas, function(txHash, err) {
if (err) return cb(txHash, err);
cb(txHash);
});
});
});
}

894
assets/javascripts/config.json Executable file

File diff suppressed because one or more lines are too long

1
assets/javascripts/sweetalert.min.js vendored Executable file

File diff suppressed because one or more lines are too long

3
assets/javascripts/vendor/index.js vendored Executable file
View File

@ -0,0 +1,3 @@
//=require jquery.min.js
//=require parity.js
//=require web3.js

4
assets/javascripts/vendor/jquery.min.js vendored Executable file

File diff suppressed because one or more lines are too long

1
assets/javascripts/vendor/parity.js vendored Executable file

File diff suppressed because one or more lines are too long

1
assets/javascripts/vendor/web3.js vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
@import './index/*';

View File

@ -0,0 +1,24 @@
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url(https://fonts.gstatic.com/s/opensans/v13/k3k702ZOKiLJc3WVjuplzBampu5_7CjHW5spxoeN3Vs.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}
html,
body {
color: #333;
line-height: 1;
font-size: 14px;
font-family: 'Open Sans', sans-serif;
-webkit-font-smoothing: antialiased;
}

View File

@ -0,0 +1,10 @@
@mixin image-2x($image, $width: 100%, $height: 100%) {
@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) {
background-image: url($image);
background-size: $width $height;
}
}

View File

@ -0,0 +1,43 @@
%stretch-width {
left: 0;
right: 0;
}
%btn {
cursor: pointer;
transition: 0.3s background-color;
border-radius: 3px;
border: 0;
padding: 0 15px 0 32px;
background-color: #08b3f2;
background-repeat: no-repeat;
background-position: left 15px center;
color: #fff;
line-height: 36px;
font-size: 13px;
text-decoration: none;
text-transform: uppercase;
font-weight: bold;
&:hover {
background-color: #20bdf7;
}
&-new {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAOUlEQVR42tXQsQEAIAgDQcAn+4+snRZxAK79KokrIcNBwgYdc0Migwxk8Qsd1TJWDf/KQWobqt+9G4coA99W7as5AAAAAElFTkSuQmCC);
background-size: 12px 12px;
}
&-vote {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAASCAMAAAB2Mu6sAAAAgVBMVEX///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+xZKUEAAAAKnRSTlMAAQIDPVBWYmNkZmpxeHp7fIOEhYaHiZeZmp6foKGio6TV2dze5unx9f63Mu9fAAAAgElEQVR4AXXO1w7CMBSD4VM2lFE2lD0I1O//gIBrCUUn/Hf5rCixRI3V695KeLMEcEn4Dp+C9z2+DZ0f6IXz4x8/0Sf63c/P9DEP7fDM5VkpZw8Ao9rX9JnVBWjJNvSlqW7F67GzAZdiS1+QooXNLaqvRe/6ZWquXuVcdW7XPJY3R9MVHwqyyb8AAAAASUVORK5CYII=);
background-size: 12px 9px;
}
}
%item {
margin-bottom: 30px;
border-radius: 8px;
border: 1px solid #eee;
background-color: #fff;
color: #333;
}

View File

@ -0,0 +1,56 @@
html,
body {
margin: 0;
padding: 0;
}
p, h1, h2, h3, h4 {
margin: 0;
padding: 0;
font-family: 'Open Sans', sans-serif;
}
html {
height: 100%;
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
background-position: center center;
}
body {
position: relative;
display: table;
width: 100%;
min-width: 960px;
height: 100%;
box-sizing: border-box;
padding: 80px 0 60px;
}
.container {
max-width: 960px;
margin: 0 auto;
}
.content {
display: table-cell;
vertical-align: top;
background-color: #fbfbfb;
text-align: center;
}
.key-content {
display: table-cell;
vertical-align: middle;
background-color: #fbfbfb;
text-align: center;
}
.left {
float: left;
}
.right {
float: right;
}

View File

@ -0,0 +1,3 @@
.hidden {
display:none;
}

View File

@ -0,0 +1,64 @@
%title {
color: #333;
text-transform: uppercase;
font-size: 16px;
font-weight: bold;
}
%description {
color: #8197a2;
line-height: 24px;
font-size: 14px;
font-weight: normal;
}
.choose-key {
@extend %item;
padding: 30px;
display: inline-block;
h1 {
@extend %title;
margin-bottom: 20px;
}
h2 {
@extend %description;
margin-bottom: 20px;
}
&-button {
@extend %btn;
display: inline-block;
background-color: #08b3f2;
background-image: url(data:image/png;base64,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);
&:hover {
background-color: #079dd4;
}
}
select {
outline: none;
font-family: 'Open Sans', sans-serif;
}
select {
transition: 0.3s border-color;
width: 100%;
border-radius: 3px;
box-sizing: border-box;
border: 1px solid #eee;
&:focus {
border-color: #08b3f2;
}
}
select {
padding: 0 15px;
height: 36px;
width: 380px;
font-size: 14px;
background: #fff;
}
}

View File

@ -0,0 +1,38 @@
.footer {
@extend %stretch-width;
position: absolute;
z-index: 1;
bottom: 0;
padding: 15px 10px;
color: #fff;
line-height: 30px;
font-size: 12px;
background-image: url(../images/bg_footer.png);
background-repeat: no-repeat;
background-size: cover;
.container {
position: relative;
overflow: hidden;
}
&-logo {
@include image-2x('../images/logos@2x.png', 163px, 66px);
position: relative;
z-index: 2;
display: inline-block;
vertical-align: middle;
width: 100px;
height: 24px;
background-image: url(../images/logos.png);
background-position: 0 0;
}
&-rights {
@extend %stretch-width;
position: absolute;
z-index: 1;
top: 0;
text-align: center;
}
}

View File

@ -0,0 +1,37 @@
.header {
@extend %stretch-width;
position: absolute;
z-index: 1;
top: 0;
padding: 18px 10px;
background-image: url(../images/bg_header.png);
background-repeat: no-repeat;
background-size: cover;
&-settings {
float: right;
text-transform: uppercase;
color: #fff;
text-decoration: none;
line-height: 39px;
margin-right: 40px;
font-size: 13px;
font-weight: bold;
}
&-logo {
@include image-2x('../images/logos@2x.png', 163px, 66px);
float: left;
width: 149px;
height: 35px;
background-image: url(../images/logos.png);
background-position: 0 -24px;
}
&-new-ballot {
@extend %btn;
@extend %btn-new;
float: right;
margin-top: 3px;
}
}

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@2x.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,34 @@
.nav {
font-size: 0;
&-i {
transition: 0.3s color;
position: relative;
display: inline-block;
vertical-align: middle;
margin-right: 40px;
color: #8197a2;
text-transform: uppercase;
text-decoration: none;
line-height: normal;
font-size: 14px;
font-weight: bold;
&:hover,
&_active {
color: #444;
}
&_active {
&:before {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: -30px;
height: 3px;
background-color: #08b3f2;
}
}
}
}

View File

@ -0,0 +1,117 @@
.new-ballot {
@extend %item;
padding: 10px 20px;
margin-bottom: 30px;
text-align: left;
box-sizing: border-box;
&-inputs {
overflow: hidden;
}
.left,
.right {
width: 48%;
}
label {
&:not(.radio) {
display: block;
margin-bottom: 15px;
margin-top: 20px;
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
}
}
button,
input,
textarea {
outline: none;
font-family: 'Open Sans', sans-serif;
}
input,
textarea {
transition: 0.3s border-color;
width: 100%;
border-radius: 3px;
box-sizing: border-box;
border: 1px solid #eee;
&:focus {
border-color: #08b3f2;
}
}
textarea {
padding: 15px;
height: 110px;
resize: none;
}
input {
padding: 0 15px;
height: 36px;
}
input[type="radio"] {
display: none;
&:checked + .radio:after {
opacity: 1;
}
}
.radio {
cursor: pointer;
display: inline-block;
vertical-align: top;
position: relative;
padding-left: 30px;
margin-top: 20px;
margin-right: 40px;
font-size: 12px;
&:before,
&:after {
content: '';
position: absolute;
top: 50%;
border-radius: 50%;
}
&:before {
left: 0;
width: 20px;
height: 20px;
margin-top: -10px;
box-sizing: border-box;
border: 1px solid #d8d9db;
}
&:after {
transition: 0.3s opacity;
opacity: 0;
left: 5px;
width: 10px;
height: 10px;
margin-top: -5px;
background-color: #08b3f2;
}
}
&-description {
margin-top: 10px;
color: #8197a2;
font-size: 12px;
line-height: 18px;
}
&-add {
@extend %btn;
@extend %btn-vote;
margin-top: 20px;
}
}

View File

@ -0,0 +1,59 @@
.search {
margin-bottom: 30px;
border-bottom: 1px solid #eee;
background-color: #fff;
line-height: 80px;
text-align: left;
.back {
transition: 0.3s opacity;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAUCAMAAACgaw2xAAAAjVBMVEUAtfX///8AtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUAtfUmVRXZAAAALnRSTlMAAAQKDxAXISIpKzc+P1laYm1vdneQlJWjpKyvs7W2ycrP0NLY3uDh4u3u+f3+FQ2PgAAAAJlJREFUGNOV0ckSgjAQRdEWghMiKiLihBOiIPf/P88FSEEiC98yp6o79VrkG3uZPRYigzrN+zAEChMme6CMDfASoNgoHfwUeAWWdMFa50A6F+mCExXAeSYajA/AO1SigXsFKJPd8dTKdip3fubWD+6lZ5SMquWOvlxEVd/1DBAryIHUN6CuJDcqaUqMVE/txH8cSsRePbPWaT+TOR0SIiH2HAAAAABJRU5ErkJggg==);
background-repeat: no-repeat;
background-position: left center;
background-size: 12px 10px;
padding-left: 20px;
color: #08b3f2;
text-decoration: none;
font-size: 14px;
font-weight: bold;
&:hover {
opacity: 0.8;
}
}
.container {
position: relative;
}
&-input {
display: block;
transition: 0.3s width,
0.3s border-color;
cursor: pointer;
position: absolute;
z-index: 1;
right: 0;
top: 50%;
width: 40px;
height: 40px;
margin: -20px 0 0;
outline: none;
border-radius: 5px;
border: 1px solid transparent;
box-sizing: border-box;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAA6lBMVEWAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6PrSx+9AAAATXRSTlMAAgMGCAkKDA0UFRYXISIjJDM0NTo7PD0/QEFERUlQWVpoaWp0dXaZm5ydnqSlpra4ub/AwcTFxsjKzM3Oz9bX2N3e6ers7fX5+vz9/pKojzsAAAGRSURBVHgBjZRtX4IwFMUXmKaBYmhWauSzEmkl+ZAaaJGo8P2/TnejEGHrt/PqcM9f2cbdRVHJDWPhuK6zMBoyYkrQJp4fyptoAp2rWn5MVpWCpXo+Rb1UnMvNg/eZ3bIkilK5YwarmOdinI2rB105lhT9gGv2CZme4dpGPf21usHVWTpS6uPKaxbFlDVxvR/ZL35+EVFC4jNOwr2ffeC1XCCKMnjt1t95avCwVxFV6h5C7ffhDbyOGBpAOAmsDCfmKSxQwWme2Cb8ZoyYGkPcJM4A12WDXYgN4lbgrtlgBeIlcQ44iQ1KEH8T54IT2aAIscsP8r+abzMr4p7AdXiOh/vA8/9/wgP5hGFTDDiaImizKzpXjLaZYOHuzFAbl0TCyVUY0a7CCCe1Y+GRkIn/zBBOT1xXqxhbXzBj6rQBUDiWCjAAiLY3UfLy3Seo2S7hkVJqmxijkef0IVXfJkhUs+OYDfu9o5CCNvUi2PSBnN9tkgTJreHS2e2c5bBFRjOVpCskK7zkGnGSn4hHlfXX/Q90qIZ+dL9jIAAAAABJRU5ErkJggg==);
background-size: 20px 20px;
background-repeat: no-repeat;
background-position: right 10px center;
color: #333;
font-size: 14px;
&:focus {
cursor: text;
width: 300px;
border-color: #eee;
padding: 0 40px 0 10px;
}
}
}

View File

@ -0,0 +1,60 @@
.socials {
position: relative;
z-index: 2;
float: right;
font-size: 0;
&-i {
transition: 0.3s background-color;
position: relative;
display: inline-block;
vertical-align: top;
width: 30px;
height: 30px;
margin-left: 10px;
border-radius: 50%;
background-color: fade-out(#fff, 0.8);
&:hover {
@media screen and (min-width: 768px) {
background-color: fade-out(#fff, 0.6);
}
}
&:before {
@include image-2x('../images/socials@2x.png', 15px, 40px);
content: '';
position: absolute;
left: 50%;
top: 50%;
background-image: url(../images/socials.png);
}
&_reddit {
&:before {
width: 15px;
height: 13px;
margin: -6.5px 0 0 -7.5px;
background-position: 0 -15px;
}
}
&_twitter {
&:before {
width: 15px;
height: 12px;
margin: -6px 0 0 -7.5px;
background-position: 0 -28px;
}
}
&_bitcoin {
&:before {
width: 11px;
height: 15px;
margin: -7.5px 0 0 -5.5px;
background-position: 0 0;
}
}
}
}

View File

@ -0,0 +1,276 @@
.vote {
text-align: left;
&-i {
@extend %item;
}
&-body {
display: table;
width: 100%;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
font-size: 0;
&-i {
display: table-cell;
vertical-align: top;
width: 33.333%;
box-sizing: border-box;
padding: 30px 20px;
&:not(:first-child) {
border-left: 1px solid #eee;
}
&:nth-child(2n) {
word-break: break-all;
}
}
&-title {
position: relative;
margin-bottom: 20px;
color: #8197a2;
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
}
&-description {
color: #444;
line-height: 24px;
font-size: 14px;
}
}
&-header {
overflow: hidden;
padding: 20px;
}
&-now {
@extend %btn;
@extend %btn-vote;
margin-right: 20px;
}
&-person {
position: relative;
padding-left: 50px;
&-img {
position: absolute;
left: 0;
top: 0;
width: 36px;
height: 36px;
}
&-name {
margin-bottom: 8px;
color: #333;
font-size: 14px;
font-weight: bold;
}
&-choose {
padding-left: 20px;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAMAAABF0y+mAAAAw1BMVEWAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6OAl6M9jT1MAAAAQHRSTlMAAQIDBQYHDA0bHB8gISQmJyg+P0BGR0lKU1RZYmNrbHV2iYqLo6Spqqusra7Cw8TFysvM29zk5ufo6/Lz+Pn8DzgVHgAAATNJREFUeNplk+1agkAQhQfRykQTrJTEUjSCvtTQECPk/q+qPQ7LsnR+7DOzL898LiRlOP46zfN0vXQM0tXydkWlndeqs/620LTtK3Z7LBo6OpLd5fDzl6nVubSnIXv3zIY/8N4HVGrwBj8bwjaR77SgmhYn5DWF5eE7ZoribkZkoIeI78ZJMmYrQkcGjZD9mq+SokjY6qKqEfniDIiFYMR6FqZPn+J8+A9dYX5QKs5eBaFz3p4wUkLwizrkvB2UcoZXJUwYHiqIsDclnBzAvicyrFYQpBW0lK0oqVbkEHR1fzEEHl/YhCHG1yKaoYi5zubl4Mn8wsqe6uwRK4tNmHaG717VsiP4mV1uih9G4FrttuUG7GGGTLOioUwyRI51Ftv6o94rtNcfNbCz2uB32KycCv0BfU5XCrQEyKwAAAAASUVORK5CYII=);
background-size: 14px 14px;
background-repeat: no-repeat;
background-position: left center;
color: #8197a2;
line-height: 14px;
font-size: 12px;
}
}
&-time {
color: #8197a2;
&-timer {
font-size: 24px;
font-weight: bold;
}
&-to {
width: 100%;
text-align: right;
text-transform: uppercase;
font-size: 12px;
}
}
&-rating {
overflow: hidden;
padding: 30px 20px;
&-i {
width: 48%;
color: #8197a2;
text-transform: uppercase;
font-size: 12px;
strong {
margin-right: 5px;
color: #333;
font-weight: bold;
}
p {
display: inline;
}
}
&-value,
&-got {
margin-bottom: 10px;
}
&-scale {
clear: left;
height: 10px;
border-radius: 5px;
background-color: #efefef;
$this: &;
&-active {
height: 100%;
border-radius: 5px;
}
&_yes {
#{$this}-active {
background-color: #08b3f2;
}
}
&_no {
#{$this}-active {
background-color: #6d2eae;
}
}
}
}
&-tooltip {
transform: translate3d(0,-10px,0);
opacity: 0;
pointer-events: none;
position: absolute;
z-index: 2;
transition: opacity 0.3s, transform 0.3s;
left: -275px;
top: 0;
width: 578px;
padding-top: 30px;
box-sizing: border-box;
&:before {
transform: rotate(-45deg);
content: '';
position: absolute;
z-index: 1;
left: 50%;
top: 22px;
width: 20px;
height: 20px;
margin-left: -12px;
border-radius: 2px;
background-color: #fff;
box-shadow: 0px 0 20px 0 fade-out(#000, 0.9);
}
$this: &;
&-text {
display: block;
position: relative;
z-index: 2;
text-align: left;
box-sizing: border-box;
border-radius: 5px;
padding: 25px;
background-color: #fff;
color: #333;
}
&-shadow {
content: '';
position: absolute;
left: 0;
right: 0;
top: 30px;
bottom: 0;
border-radius: 5px;
box-shadow: 0px 20px 40px 0 fade-out(#000, 0.7);
}
&-title {
display: block;
margin-bottom: 15px;
font-size: 16px;
}
&-description {
line-height: 24px;
font-size: 14px;
font-weight: normal;
text-transform: none;
a {
color: #08b3f2;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
&-icon {
position: relative;
display: block;
width: 24px;
height: 24px;
margin-top: -6px;
border-radius: 50%;
background-color: #08b3f2;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAYCAMAAADqO6ysAAAAFVBMVEX///////////////////////////9nSIHRAAAABnRSTlMASUrk5udXTd49AAAAJUlEQVQI12NgZGFhZGBhY2MBEawMTKzMTAzYAEIdGxCQS8DtAABR5AGfy9XNLgAAAABJRU5ErkJggg==);
background-repeat: no-repeat;
background-position: center center;
background-size: 2px 12px;
}
&-container {
position: relative;
z-index: 10;
float: right;
&:hover {
#{$this} {
pointer-events: auto;
opacity: 1;
transform: translate3d(0,0,0) rotate3d(0,0,0,0);
}
}
}
}
.vote-rating-yes,
.vote-rating-no {
@extend %btn;
@extend %btn-vote;
margin-top: 20px;
}
.vote-rating-no {
background-color: #6d2eae;
&:hover {
background-color: #5d2795;
}
}
}

File diff suppressed because one or more lines are too long

BIN
ballot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
ballots.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
favicons/fav_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
favicons/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
favicons/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
favicons/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

18
favicons/manifest.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

BIN
favicons/mstile-150x150.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

39
gulpfile.js Executable file
View File

@ -0,0 +1,39 @@
'use strict';
const gulp = require('gulp');
const sass = require('gulp-sass');
const sassGlob = require('gulp-sass-glob');
const autoprefixer = require('gulp-autoprefixer');
const uglifycss = require('gulp-uglifycss');
const include = require('gulp-include');
const addsrc = require('gulp-add-src');
const order = require('gulp-order');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
gulp.task('sass', function() {
return gulp.src(['assets/stylesheets/*.scss'])
.pipe(sassGlob())
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(uglifycss())
.pipe(gulp.dest('assets/stylesheets/'));
});
gulp.task('javascript', function() {
return gulp.src('assets/javascripts/application/*.js')
.pipe(addsrc('assets/javascripts/vendor/index.js'))
.pipe(order([
"assets/javascripts/vendor/index.js",
"assets/javascripts/application/*.js"
], {base: '.'}))
.pipe(include())
.pipe(concat('application.js'))
// .pipe(uglify())
.pipe(gulp.dest('assets/javascripts'));
});
gulp.task('watch', function() {
gulp.watch('assets/stylesheets/**/*.scss', ['sass']);
gulp.watch('assets/javascripts/application/*.js', ['javascript']);
});

82
index.html Executable file
View File

@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="theme-color" content="#6151cc">
<meta name="msapplication-config" content="./favicons/browserconfig.xml">
<!-- <meta property="og:title" content="">
<meta property="og:description" content=""> -->
<!-- <meta property="og:url" content="https://oracles.org/"> -->
<!-- <meta property="og:image" content="https://www.notarycoin.com/assets/images/share.png"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./assets/stylesheets/index.css">
<link rel="stylesheet" type="text/css" href="./assets/stylesheets/sweetalert.css">
<link rel="apple-touch-icon" href="./favicons/favicon-192x192.png">
<link rel="icon" type="image/png" sizes="192x192" href="./favicons/favicon-192x192.png">
<link rel="mask-icon" color="#6151cc" href="./favicons/safari-pinned-tab.svg">
<link rel="manifest" href="./favicons/manifest.webmanifest">
</head>
<body>
<header class="header">
<div class="container">
<a href="#" class="header-logo"></a>
<a href="#" class="header-new-ballot">New ballot</a>
<a href="#" class="header-settings">Settings</a>
</div>
</header>
<section class="key-content">
<div class="choose-key">
<h1>Lorem ipsum dolor</h1>
<select class="key-select">
</select>
<h2>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do <br>
Duis laoreet eros nec rutrum. Suspendisse lorem in varius.
</h2>
<a href="#" class="choose-key-button">Continue</a>
</div>
</section>
<section class="content hidden">
<div class="search">
<div class="container">
<div class="nav">
<a href="#" class="nav-i nav-i_actual nav-i_active">All</a>
<a href="#" class="nav-i nav-i_unanswered">Unanswered</a>
<a href="#" class="nav-i nav-i_expired">Expired</a>
</div>
<a href="#" class="back">Back</a>
<form action="" class="search-form">
<input type="text" class="search-input">
</form>
</div>
</div>
<div class="container new-ballot"></div>
<div class="container vote"></div>
</section>
<div class="loading-container">
<div class="loading">
<div class="loading-i"></div>
<div class="loading-i"></div>
<div class="loading-i"></div>
<div class="loading-i"></div>
<div class="loading-i"></div>
<div class="loading-i"></div>
</div>
</div>
<footer class="footer">
<div class="container">
<a href="#" class="footer-logo"></a>
<div class="socials">
<a href="#" class="socials-i socials-i_reddit"></a>
<a href="https://twitter.com/notarycoin" class="socials-i socials-i_twitter"></a>
<a href="#" class="socials-i socials-i_bitcoin"></a>
</div>
<p class="footer-rights">2017 Oracles. All rights reserved.</p>
</div>
</footer>
<script src="./assets/javascripts/sweetalert.min.js" type="text/javascript"></script>
<script src="./assets/javascripts/application.js" type="text/javascript"></script>
</body>
</html>

8
manifest.json Normal file
View File

@ -0,0 +1,8 @@
{
"id": "Voting",
"name": "Voting",
"description": "Oracles Voting",
"version": "1.0.0",
"author": "Oracles",
"iconUrl": "./favicons/fav_2.png"
}

36
newBallot.html Normal file
View File

@ -0,0 +1,36 @@
<form action="">
<div class="new-ballot-inputs">
<div class="left">
<label for="full-name">Full name</label>
<input type="text" id="full-name">
<label for="address">Address</label>
<input type="text" id="address">
<label for="state">State</label>
<input type="text" id="state">
<label for="zip">Zip code</label>
<input type="number" id="zip">
<label for="license-id">License id</label>
<input type="number" id="license-id">
<label for="license-expiration">License expiration</label>
<input type="date" id="license-expiration">
</div>
<div class="right">
<label for="memo">Memo</label>
<textarea id="memo"></textarea>
<div class="new-ballot-description">
Please type your memo, for example, add or remove mining key, full name,
and a reason.
</div>
<label for="key">Mining key</label>
<input type="text" id="key">
<div class="new-ballot-description">
Affected mining key
</div>
<input type="radio" name="type" id="type_add" value=1 checked>
<label class="radio" for="type_add">Add</label>
<input type="radio" name="type" id="type_remove" value=0>
<label class="radio" for="type_remove">Remove</label>
</div>
</div>
<button type="button" class="new-ballot-add">Add ballot</button>
</form>

BIN
new_ballot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

38
package.json Executable file
View File

@ -0,0 +1,38 @@
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "gulpfile.js",
"devDependencies": {
"web3": "^0.18.2",
"gulp": "^3.9.1",
"gulp-add-src": "^0.2.0",
"gulp-autoprefixer": "^3.1.1",
"gulp-concat": "^2.6.1",
"gulp-include": "^2.3.1",
"gulp-order": "^1.1.1",
"gulp-postcss": "^6.2.0",
"gulp-sass": "^2.3.2",
"gulp-sass-glob": "^1.0.6",
"gulp-uglify": "^2.0.0",
"gulp-uglifycss": "^1.0.6",
"http-server": "^0.9.0"
},
"scripts": {
"sass": "gulp sass",
"coffee": "gulp javascript",
"watch": "gulp watch",
"start": "http-server -a localhost -p 8000"
},
"repository": {
"type": "git",
"url": ""
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "/issues"
},
"homepage": "#README"
}

BIN
settings.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB