├── .gitignore ├── CITATION.cff ├── Ethereum ├── Build │ ├── Election.json │ └── ElectionFact.json ├── Contract │ └── Election.sol ├── compile.js ├── deploy.js ├── election.js ├── election_factory.js └── web3.js ├── LICENSE ├── README.md ├── components ├── Header.js └── Layout.js ├── config └── database.js ├── controllers ├── candidate.js ├── company.js └── voter.js ├── ipfs.js ├── models ├── company.js └── voter.js ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── company_login.js ├── election │ ├── candidate_list.js │ ├── canvasjs.min.js │ ├── canvasjs.react.js │ ├── company_dashboard.js │ ├── create_election.js │ ├── vote.js │ └── voting_list.js ├── homepage.js └── voter_login.js ├── routes.js ├── routes ├── candidate.js ├── company.js └── voter.js ├── screenshots ├── candidate_list.PNG ├── candidate_registeration_mail.PNG ├── company_login.PNG ├── create_election.PNG ├── dashboard.PNG ├── homepage.PNG ├── successful_voting.PNG ├── unsuccessful_voting.PNG ├── voter_login.PNG ├── voter_registeration_mail.PNG ├── voterlist.PNG └── winner_candidate_mail.PNG ├── server.js └── static ├── banner.jpg ├── blockchain.jpg ├── blocv.png ├── bootstrap.min.css.map ├── bv.png ├── ether2.png ├── hometest.css ├── logo.png ├── logo3.png ├── test.css ├── themify-icons.css └── vlcss.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .next/ -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # YAML 1.2 2 | --- 3 | authors: 4 | - 5 | family-names: Mehta 6 | given-names: Ansh 7 | - 8 | family-names: Mehta 9 | given-names: Charmee 10 | - 11 | family-names: Gada 12 | given-names: Sayyam 13 | - 14 | affiliation: "Prof." 15 | family-names: Kadukar 16 | given-names: Neeta 17 | cff-version: "1.1.0" 18 | date-released: 2019-06-01 19 | message: "If you use this software, please cite it using these metadata." 20 | repository-code: "https://github.com/mehtaAnsh/BlockChainVoting" 21 | title: BlockChainVoting 22 | version: "v1.0" 23 | ... -------------------------------------------------------------------------------- /Ethereum/Contract/Election.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | 3 | contract ElectionFact { 4 | 5 | struct ElectionDet { 6 | address deployedAddress; 7 | string el_n; 8 | string el_d; 9 | } 10 | 11 | mapping(string=>ElectionDet) companyEmail; 12 | 13 | function createElection(string memory email,string memory election_name, string memory election_description) public{ 14 | address newElection = new Election(msg.sender , election_name, election_description); 15 | 16 | companyEmail[email].deployedAddress = newElection; 17 | companyEmail[email].el_n = election_name; 18 | companyEmail[email].el_d = election_description; 19 | } 20 | 21 | function getDeployedElection(string memory email) public view returns (address,string,string) { 22 | address val = companyEmail[email].deployedAddress; 23 | if(val == 0) 24 | return (0,"","Create an election."); 25 | else 26 | return (companyEmail[email].deployedAddress,companyEmail[email].el_n,companyEmail[email].el_d); 27 | } 28 | } 29 | 30 | contract Election { 31 | 32 | //election_authority's address 33 | address election_authority; 34 | string election_name; 35 | string election_description; 36 | bool status; 37 | 38 | //election_authority's address taken when it deploys the contract 39 | constructor(address authority , string name, string description) public { 40 | election_authority = authority; 41 | election_name = name; 42 | election_description = description; 43 | status = true; 44 | } 45 | 46 | //Only election_authority can call this function 47 | modifier owner() { 48 | require(msg.sender == election_authority, "Error: Access Denied."); 49 | _; 50 | } 51 | //candidate election_description 52 | 53 | struct Candidate { 54 | string candidate_name; 55 | string candidate_description; 56 | string imgHash; 57 | uint8 voteCount; 58 | string email; 59 | } 60 | 61 | //candidate mapping 62 | 63 | mapping(uint8=>Candidate) public candidates; 64 | 65 | //voter election_description 66 | 67 | struct Voter { 68 | uint8 candidate_id_voted; 69 | bool voted; 70 | } 71 | 72 | //voter mapping 73 | 74 | mapping(string=>Voter) voters; 75 | 76 | //counter of number of candidates 77 | 78 | uint8 numCandidates; 79 | 80 | //counter of number of voters 81 | 82 | uint8 numVoters; 83 | 84 | //function to add candidate to mapping 85 | 86 | function addCandidate(string memory candidate_name, string memory candidate_description, string memory imgHash,string memory email) public owner { 87 | uint8 candidateID = numCandidates++; //assign id of the candidate 88 | candidates[candidateID] = Candidate(candidate_name,candidate_description,imgHash,0,email); //add the values to the mapping 89 | } 90 | //function to vote and check for double voting 91 | 92 | function vote(uint8 candidateID,string e) public { 93 | 94 | //if false the vote will be registered 95 | require(!voters[e].voted, "Error:You cannot double vote"); 96 | 97 | voters[e] = Voter (candidateID,true); //add the values to the mapping 98 | numVoters++; 99 | candidates[candidateID].voteCount++; //increment vote counter of candidate 100 | 101 | } 102 | 103 | //function to get count of candidates 104 | 105 | function getNumOfCandidates() public view returns(uint8) { 106 | return numCandidates; 107 | } 108 | 109 | //function to get count of voters 110 | 111 | function getNumOfVoters() public view returns(uint8) { 112 | return numVoters; 113 | } 114 | 115 | //function to get candidate information 116 | 117 | function getCandidate(uint8 candidateID) public view returns (string memory, string memory, string memory, uint8,string memory) { 118 | return (candidates[candidateID].candidate_name, candidates[candidateID].candidate_description, candidates[candidateID].imgHash, candidates[candidateID].voteCount, candidates[candidateID].email); 119 | } 120 | 121 | //function to return winner candidate information 122 | 123 | function winnerCandidate() public view owner returns (uint8) { 124 | uint8 largestVotes = candidates[0].voteCount; 125 | uint8 candidateID; 126 | for(uint8 i = 1;i { 13 | const accounts = await web3.eth.getAccounts(); 14 | 15 | console.log('Attemping to deploy from account', accounts[0]); 16 | 17 | const result = await new web3.eth.Contract(JSON.parse(eF.interface)) 18 | .deploy({ data: '0x' + eF.bytecode }) 19 | .send({ gas: '3000000', from: accounts[0] }); 20 | 21 | console.log('Contract deployed to: ', result.options.address); 22 | }; 23 | deploy(); 24 | -------------------------------------------------------------------------------- /Ethereum/election.js: -------------------------------------------------------------------------------- 1 | import web3 from './web3'; 2 | import Election from './Build/Election.json'; 3 | 4 | export default address => { 5 | return new web3.eth.Contract( 6 | JSON.parse(Election.interface), 7 | address 8 | ); 9 | }; -------------------------------------------------------------------------------- /Ethereum/election_factory.js: -------------------------------------------------------------------------------- 1 | import web3 from './web3'; 2 | import ElectionFactory from './Build/ElectionFact.json'; 3 | 4 | const instance = new web3.eth.Contract( 5 | JSON.parse(ElectionFactory.interface), 6 | '0xF5d3574DDc21D8Bd8bcB380de232cbbc8161234e' 7 | ); 8 | 9 | export default instance; -------------------------------------------------------------------------------- /Ethereum/web3.js: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3'; 2 | 3 | let web3; 4 | 5 | if (typeof window !== 'undefined' && typeof window.web3 !== 'undefined') { 6 | console.log(window.ethereum.enable()); 7 | web3 = new Web3(window.web3.currentProvider); 8 | console.log('Web3: ', web3); 9 | } else { 10 | const provider = new Web3.providers.HttpProvider('https://rinkeby.infura.io/v3/29bcae4ee7454a118a2b0f0f4d86c0e0'); 11 | web3 = new Web3(provider); 12 | console.log('Web3 else: ', web3); 13 | } 14 | 15 | export default web3; 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ansh Mehta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BlockChainVoting 2 | 3 | A blockchain-based E-voting system, created as the final year project of Shri Bhagubhai Mafatlal Polytechnic. Teammates include me, Sayyam Gada and Charmee Mehta. 4 | > The application is MIT-Licensed. 5 | 6 | ## Build Setup 7 | 8 | ```bash 9 | # install dependencies 10 | npm install 11 | 12 | # serve with hot reload at localhost:3000 13 | npm start 14 | ``` 15 | 16 | Create your own .env file and the file should contain: 17 | ```bash 18 | EMAIL=YOUR_EMAIL_ID 19 | PASSWORD=YOUR_PASSWORD_FOR_EMAIL_ID 20 | ``` 21 | Install MetaMask extension (https://metamask.io/download.html) and make sure to have some Ether to test the application locally. Ether can be fetched from Rinkeby Faucet (https://faucet.rinkeby.io) 22 | 23 | #### Note: 24 | - Make sure to install Node.js v11.14.0 to make sure the app runs fine. Testing for other node versions is yet to be done. 25 | - MongoDB must be working in background on localhost:27017 26 | 27 | ###### Please star the repo if it helped you in any way! 28 | 29 | ## Tech Stack: 30 | 31 | - Solidity/Web3 (for writing/connecting the Blockchain contract) 32 | - Next.js & Semantic UI React (front-end) 33 | - MongoDB/ExpressJS/Node.js (back-end) 34 | - IPFS (file storage for images) 35 | 36 | ## Screenshots of the app: 37 | 38 | Homepage of the application: 39 | 40 | ![](screenshots/homepage.PNG) 41 | 42 | Company registers/logs in: 43 | 44 | ![](screenshots/company_login.PNG) 45 | 46 | Company creates an election if not created: 47 | 48 | ![](screenshots/create_election.PNG) 49 | 50 | Dashboard on successful election creation: 51 | 52 | ![](screenshots/dashboard.PNG) 53 | 54 | List of candidates for the election (here, you can add candidates): 55 | 56 | ![](screenshots/candidate_list.PNG) 57 | 58 | Candidate has been notified on the mail: 59 | 60 | ![](screenshots/candidate_registeration_mail.PNG) 61 | 62 | List of voters for the election (here, you can add voters): 63 | 64 | ![](screenshots/voterlist.PNG) 65 | 66 | Voters have been sent their secure usernames and passwords on the mail: 67 | 68 | ![](screenshots/voter_registeration_mail.PNG) 69 | 70 | Voter login page: 71 | 72 | ![](screenshots/voter_login.PNG) 73 | 74 | Successful voting scenario: 75 | 76 | ![](screenshots/successful_voting.PNG) 77 | 78 | Unsuccessful voting scenario: 79 | 80 | ![](screenshots/unsuccessful_voting.PNG) 81 | 82 | Notification to each candidate and voter for the winner of candidates: 83 | 84 | ![](screenshots/winner_candidate_mail.PNG) 85 | -------------------------------------------------------------------------------- /components/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Menu } from 'semantic-ui-react'; 3 | import Cookies from 'js-cookie'; 4 | 5 | export default props => { 6 | return ( 7 |
8 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | {Cookies.get('company_email') || Cookies.get('voter_email')} 23 | 24 | 25 | 26 |
27 | {props.children} 28 |
29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /components/Layout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from './Header'; 3 | import {Container} from 'semantic-ui-react'; 4 | import Head from 'next/head'; 5 | 6 | export default (props) =>{ 7 | return( 8 | 9 | 10 | 14 | 15 | 16 |
17 | {props.children} 18 | 19 | ); 20 | }; -------------------------------------------------------------------------------- /config/database.js: -------------------------------------------------------------------------------- 1 | //Set up mongoose connection 2 | const mongoose = require('mongoose'); 3 | const mongoDB = 'mongodb://localhost/BlockVotes'; 4 | mongoose.connect(mongoDB,{ useNewUrlParser: true }); 5 | mongoose.Promise = global.Promise; 6 | module.exports = mongoose; -------------------------------------------------------------------------------- /controllers/candidate.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | var nodemailer = require('nodemailer'); 3 | 4 | module.exports = { 5 | register: function (req, res, cb) { 6 | var transporter = nodemailer.createTransport({ 7 | service: 'gmail', 8 | auth: { 9 | user: process.env.EMAIL, 10 | pass: process.env.PASSWORD, 11 | }, 12 | }); 13 | const mailOptions = { 14 | from: process.env.EMAIL, 15 | to: req.body.email, 16 | subject: req.body.election_name + 'Registration', 17 | html: 'Congrats you have been registered for ' + req.body.election_name + ' election.', 18 | }; 19 | transporter.sendMail(mailOptions, function (err, info) { 20 | if (err) { 21 | res.json({ status: 'error', message: 'mail error', data: null }); 22 | console.log(err); 23 | } else console.log(info); 24 | res.json({ status: 'success', message: 'mail sent successfully!!!', data: null }); 25 | }); 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /controllers/company.js: -------------------------------------------------------------------------------- 1 | const CompanyModel = require('../models/company'); 2 | const bcrypt = require('bcrypt'); 3 | const path = require('path'); 4 | module.exports = { 5 | create: function(req, res, cb) { 6 | CompanyModel.findOne({email:req.body.email}, function(err, result) { 7 | if(err){ 8 | cb(err); 9 | } 10 | else{ 11 | if(!result){ 12 | CompanyModel.create({ email: req.body.email, password: req.body.password }, function (err, result) { 13 | if (err) 14 | cb(err); 15 | else{ 16 | CompanyModel.findOne({email:req.body.email}, function(err, CompanyInfo) { 17 | if (err) 18 | cb(err); 19 | else{ 20 | res.json({status: "success", message: "Company added successfully!!!", data:{id:CompanyInfo._id}}); 21 | } 22 | }); 23 | } 24 | }); 25 | } 26 | else{ 27 | res.json({status: "error", message: "Company already exists ", data:null}); 28 | } 29 | } 30 | 31 | }); 32 | }, 33 | authenticate: function(req, res, cb) { 34 | CompanyModel.findOne({email:req.body.email}, function(err, CompanyInfo){ 35 | if (err) 36 | cb(err); 37 | else { 38 | if(bcrypt.compareSync(req.body.password, CompanyInfo.password) && CompanyInfo.email == req.body.email) { 39 | 40 | res.json({status:"success", message: "company found!!!", data:{id: CompanyInfo._id, email: CompanyInfo.email}}); 41 | } 42 | else { 43 | res.json({status:"error", message: "Invalid email/password!!!", data:null}); 44 | } 45 | } 46 | }); 47 | } 48 | } -------------------------------------------------------------------------------- /controllers/voter.js: -------------------------------------------------------------------------------- 1 | const VoterModel = require('../models/voter'); 2 | 3 | const bcrypt = require('bcrypt'); 4 | 5 | const path = require('path'); 6 | 7 | var nodemailer = require('nodemailer'); 8 | 9 | const saltRounds = 10; 10 | 11 | module.exports = { 12 | create: function (req, res, cb) { 13 | VoterModel.findOne( 14 | { email: req.body.email, election_address: req.body.election_address }, 15 | function (err, result) { 16 | if (err) { 17 | cb(err); 18 | } else { 19 | if (!result) { 20 | VoterModel.create( 21 | { 22 | email: req.body.email, 23 | password: req.body.email, 24 | election_address: req.body.election_address, 25 | }, 26 | function (err, voter) { 27 | if (err) cb(err); 28 | else { 29 | console.log(voter); 30 | 31 | console.log(voter.email); 32 | 33 | console.log(req.body.election_description); 34 | 35 | console.log(req.body.election_name); 36 | 37 | var transporter = nodemailer.createTransport({ 38 | service: 'gmail', 39 | 40 | auth: { 41 | user: process.env.EMAIL, 42 | 43 | pass: process.env.PASSWORD, 44 | }, 45 | }); 46 | 47 | const mailOptions = { 48 | from: process.env.EMAIL, // sender address 49 | 50 | to: voter.email, // list of receivers 51 | 52 | subject: req.body.election_name, // Subject line 53 | 54 | html: 55 | req.body.election_description + 56 | '
Your voting id is:' + 57 | voter.email + 58 | '
' + 59 | 'Your password is:' + 60 | voter.password + 61 | '
Click here to visit the website', // plain text body 62 | }; 63 | 64 | transporter.sendMail(mailOptions, function (err, info) { 65 | if (err) { 66 | res.json({ 67 | status: 'error', 68 | message: 'Voter could not be added', 69 | data: null, 70 | }); 71 | 72 | console.log(err); 73 | } else { 74 | console.log(info); 75 | 76 | res.json({ 77 | status: 'success', 78 | message: 'Voter added successfully!!!', 79 | data: null, 80 | }); 81 | } 82 | }); 83 | } 84 | } 85 | ); 86 | } else { 87 | res.json({ status: 'error', message: 'Voter already exists ', data: null }); 88 | } 89 | } 90 | } 91 | ); 92 | }, 93 | 94 | authenticate: function (req, res, cb) { 95 | VoterModel.findOne({ email: req.body.email, password: req.body.password }, function (err, voterInfo) { 96 | if (err) cb(err); 97 | else { 98 | if (voterInfo) 99 | res.json({ 100 | status: 'success', 101 | message: 'voter found!!!', 102 | data: { id: voterInfo._id, election_address: voterInfo.election_address }, 103 | }); 104 | //res.sendFile(path.join(__dirname+'/index.html')); 105 | else { 106 | res.json({ status: 'error', message: 'Invalid email/password!!!', data: null }); 107 | } 108 | } 109 | }); 110 | }, 111 | 112 | getAll: function (req, res, cb) { 113 | let voterList = []; 114 | 115 | VoterModel.find({ election_address: req.body.election_address }, function (err, voters) { 116 | if (err) cb(err); 117 | else { 118 | for (let voter of voters) voterList.push({ id: voter._id, email: voter.email }); 119 | 120 | count = voterList.length; 121 | 122 | res.json({ 123 | status: 'success', 124 | message: 'voters list found!!!', 125 | data: { voters: voterList }, 126 | count: count, 127 | }); 128 | } 129 | }); 130 | }, 131 | 132 | updateById: function (req, res, cb) { 133 | VoterModel.findOne({ email: req.body.email }, function (err, result) { 134 | if (err) { 135 | cb(err); 136 | } else { 137 | console.log('email:' + req.body.email); 138 | console.log('findOne:' + result); 139 | if (!result) { 140 | password = bcrypt.hashSync(req.body.email, saltRounds); 141 | console.log('email not found'); 142 | console.log('voterID:' + req.params.voterId); 143 | VoterModel.findByIdAndUpdate( 144 | req.params.voterId, 145 | { email: req.body.email, password: password }, 146 | function (err, voter) { 147 | if (err) cb(err); 148 | console.log('update method object:' + voter); 149 | } 150 | ); 151 | VoterModel.findById(req.params.voterId, function (err, voterInfo) { 152 | if (err) cb(err); 153 | else { 154 | console.log('Inside find after update' + voterInfo); 155 | var transporter = nodemailer.createTransport({ 156 | service: 'gmail', 157 | auth: { 158 | user: process.env.EMAIL, 159 | pass: process.env.PASSWORD, 160 | }, 161 | }); 162 | const mailOptions = { 163 | from: process.env.EMAIL, // sender address 164 | to: voterInfo.email, // list of receivers 165 | subject: req.body.election_name, // Subject line 166 | html: 167 | req.body.election_description + 168 | '
Your voting id is:' + 169 | voterInfo.email + 170 | '
' + 171 | 'Your password is:' + 172 | voterInfo.password + 173 | '
Click here to visit the website', // plain text body 174 | }; 175 | transporter.sendMail(mailOptions, function (err, info) { 176 | if (err) { 177 | res.json({ status: 'error', message: 'Voter could not be added', data: null }); 178 | console.log(err); 179 | } else { 180 | console.log(info); 181 | res.json({ 182 | status: 'success', 183 | message: 'Voter updated successfully!!!', 184 | data: null, 185 | }); 186 | } 187 | }); 188 | } 189 | }); 190 | } else { 191 | res.json({ status: 'error', message: 'Voter already exists ', data: null }); 192 | } 193 | } 194 | }); 195 | }, 196 | 197 | deleteById: function (req, res, cb) { 198 | VoterModel.findByIdAndRemove(req.params.voterId, function (err, voterInfo) { 199 | if (err) cb(err); 200 | else { 201 | res.json({ status: 'success', message: 'voter deleted successfully!!!', data: null }); 202 | } 203 | }); 204 | }, 205 | 206 | resultMail: function (req, res, cb) { 207 | VoterModel.find({ election_address: req.body.election_address }, function (err, voters) { 208 | if (err) cb(err); 209 | else { 210 | const election_name = req.body.election_name; 211 | 212 | const winner_candidate = req.body.winner_candidate; 213 | 214 | for (let voter of voters) { 215 | var transporter = nodemailer.createTransport({ 216 | service: 'gmail', 217 | 218 | auth: { 219 | user: process.env.EMAIL, 220 | 221 | pass: process.env.PASSWORD, 222 | }, 223 | }); 224 | 225 | const mailOptions = { 226 | from: process.env.EMAIL, // sender address 227 | 228 | to: voter.email, // list of receivers 229 | 230 | subject: election_name + ' results', // Subject line 231 | 232 | html: 233 | 'The results of ' + 234 | election_name + 235 | ' are out.
The winner candidate is: ' + 236 | winner_candidate + 237 | '.', 238 | }; 239 | 240 | transporter.sendMail(mailOptions, function (err, info) { 241 | if (err) { 242 | res.json({ status: 'error', message: 'mail error', data: null }); 243 | 244 | console.log(err); 245 | } else console.log(info); 246 | 247 | res.json({ status: 'success', message: 'mails sent successfully!!!', data: null }); 248 | }); 249 | } 250 | 251 | var transporter = nodemailer.createTransport({ 252 | service: 'gmail', 253 | 254 | auth: { 255 | user: process.env.EMAIL, 256 | 257 | pass: process.env.PASSWORD, 258 | }, 259 | }); 260 | 261 | const mailOptions = { 262 | from: process.env.EMAIL, // sender address 263 | 264 | to: req.body.candidate_email, // list of receivers 265 | 266 | subject: req.body.election_name + ' results !!!', // Subject line 267 | 268 | html: 'Congratulations you won ' + req.body.election_name + ' election.', // plain text body 269 | }; 270 | 271 | transporter.sendMail(mailOptions, function (err, info) { 272 | if (err) { 273 | res.json({ status: 'error', message: 'mail error', data: null }); 274 | 275 | console.log(err); 276 | } else console.log(info); 277 | 278 | res.json({ status: 'success', message: 'mail sent successfully!!!', data: null }); 279 | }); 280 | } 281 | }); 282 | }, 283 | }; 284 | -------------------------------------------------------------------------------- /ipfs.js: -------------------------------------------------------------------------------- 1 | const IPFS = require('ipfs-api'); 2 | const ipfs = new IPFS({host: 'ipfs.infura.io', port: 5001, protocol: 'https' }); 3 | export default ipfs; -------------------------------------------------------------------------------- /models/company.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const bcrypt = require('bcrypt'); 3 | const saltRounds = 10; 4 | //Define a schema 5 | const Schema = mongoose.Schema; 6 | const CompanySchema = new Schema({ 7 | email: { //mail of the company 8 | type: String, 9 | required: true 10 | }, 11 | password: { //password of the company 12 | type: String, 13 | required: true 14 | } 15 | }); 16 | // hash user password before saving into database 17 | CompanySchema.pre('save', function(cb){ 18 | this.password = bcrypt.hashSync(this.password, saltRounds); 19 | cb(); 20 | }); 21 | module.exports = mongoose.model('CompanyList', CompanySchema); -------------------------------------------------------------------------------- /models/voter.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const bcrypt = require('bcrypt'); 3 | const saltRounds = 10; 4 | //Define a schema 5 | const Schema = mongoose.Schema; 6 | const VoterSchema = new Schema ({ 7 | email: { 8 | type: String, 9 | required: true, 10 | }, 11 | password: { 12 | type: String, 13 | required: true 14 | }, 15 | election_address: { 16 | type: String, 17 | required: true 18 | } 19 | }); 20 | // hash user password before saving into database 21 | VoterSchema.pre('save', function(cb) { 22 | this.password = bcrypt.hashSync(this.password, saltRounds); 23 | cb(); 24 | }); 25 | module.exports = mongoose.model('VoterList', VoterSchema) -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const withCSS = require('@zeit/next-css') 2 | module.exports = withCSS() -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "projecteth", 3 | "version": "1.0.0", 4 | "main": "server.js", 5 | "dependencies": { 6 | "@zeit/next-css": "^1.0.1", 7 | "bcrypt": "^3.0.6", 8 | "body-parser": "^1.18.3", 9 | "chart.js": "^2.8.0", 10 | "chartjs": "^0.3.24", 11 | "chartjs-plugin-annotation": "^0.5.7", 12 | "dotenv": "^8.2.0", 13 | "express": "^4.16.4", 14 | "fs-extra": "^7.0.1", 15 | "ganache-cli": "^6.4.1", 16 | "ipfs-api": "^26.1.2", 17 | "js-cookie": "^2.2.0", 18 | "mongoose": "^5.5.1", 19 | "next": "^8.0.3", 20 | "next-routes": "^1.4.2", 21 | "nodemailer": "^6.1.0", 22 | "path": "^0.12.7", 23 | "react": "^16.8.5", 24 | "react-chartjs-2": "^2.7.6", 25 | "react-dom": "^16.8.5", 26 | "react-helmet": "^5.2.0", 27 | "semantic-ui-css": "^2.4.1", 28 | "semantic-ui-react": "^0.86.0", 29 | "solc": "^0.4.25", 30 | "truffle-hdwallet-provider": "^1.0.5", 31 | "web3": "^1.0.0-beta.52" 32 | }, 33 | "devDependencies": { 34 | "mocha": "^6.1.4" 35 | }, 36 | "scripts": { 37 | "test": "mocha", 38 | "start": "node server.js" 39 | }, 40 | "keywords": [], 41 | "author": "", 42 | "license": "ISC", 43 | "description": "A blockchain-based E-voting system, created for the final year project of my college, with the help of my Project partners, Sayyam Gada and Charmee Mehta.", 44 | "repository": { 45 | "type": "git", 46 | "url": "git+https://github.com/mehtaAnsh/BlockChainVoting-Private.git" 47 | }, 48 | "bugs": { 49 | "url": "https://github.com/mehtaAnsh/BlockChainVoting-Private/issues" 50 | }, 51 | "homepage": "https://github.com/mehtaAnsh/BlockChainVoting-Private#readme" 52 | } 53 | -------------------------------------------------------------------------------- /pages/company_login.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { 3 | Button, 4 | Divider, 5 | Transition, 6 | Form, 7 | Grid, 8 | Segment, 9 | Message 10 | } from "semantic-ui-react"; 11 | import {Router} from '../routes' 12 | import web3 from "../Ethereum/web3"; 13 | import Election_Factory from "../Ethereum/election_factory"; 14 | import Cookies from 'js-cookie'; 15 | import {Helmet} from 'react-helmet' 16 | 17 | class DividerExampleVerticalForm extends Component { 18 | state = { visible: true, email: ''}; 19 | toggleVisibility = () => this.setState({ visible: !this.state.visible }); 20 | returnBackImage = () => ( 21 |
22 | 31 |
32 | ) 33 | 34 | signup = event => { 35 | const email = document.getElementById('signup_email').value; 36 | const password = document.getElementById('signup_password').value; 37 | const repeat_password = document.getElementById('signup_repeat_password').value; 38 | if(password!=repeat_password){ 39 | alert("Passwords do not match"); 40 | } 41 | else { 42 | var http = new XMLHttpRequest(); 43 | var url = 'company/register'; 44 | var params = 'email='+email+'&password='+password; 45 | http.open('POST', url, true); 46 | //Send the proper header information along with the request 47 | http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 48 | http.onreadystatechange = function() {//Call a function when the state changes. 49 | if(http.readyState == 4 && http.status == 200) { 50 | var responseObj = JSON.parse(http.responseText) 51 | if(responseObj.status=="success") { 52 | Cookies.set('company_email', encodeURI(responseObj.data.email)); 53 | alert("Added!"); 54 | Router.pushRoute(`/company_login`); 55 | } 56 | else { 57 | alert(responseObj.message); 58 | } 59 | } 60 | 61 | } 62 | http.send(params); 63 | } 64 | } 65 | signin = async event => { 66 | const email = document.getElementById('signin_email').value; 67 | this.setState({email: document.getElementById('signin_email').value}); 68 | const password = document.getElementById("signin_password").value; 69 | var http = new XMLHttpRequest(); 70 | var url = "company/authenticate"; 71 | var params = "email=" + email + "&password=" + password; 72 | http.open("POST", url, true); 73 | //Send the proper header information along with the request 74 | http.setRequestHeader( 75 | "Content-type", 76 | "application/x-www-form-urlencoded" 77 | ); 78 | http.onreadystatechange = function() { 79 | //Call a function when the state changes. 80 | if (http.readyState == 4 && http.status == 200) { 81 | var responseObj = JSON.parse(http.responseText); 82 | if(responseObj.status=="success") { 83 | Cookies.set('company_id', encodeURI(responseObj.data.id)); 84 | Cookies.set('company_email', encodeURI(responseObj.data.email)); 85 | } 86 | else { 87 | alert(responseObj.message); 88 | } 89 | 90 | } 91 | }; 92 | http.send(params); 93 | try { 94 | const accounts = await web3.eth.getAccounts(); 95 | const summary = await Election_Factory.methods.getDeployedElection(this.state.email).call({from: accounts[0]}); 96 | if(summary[2] == "Create an election.") { 97 | Router.pushRoute(`/election/create_election`); 98 | } 99 | else { 100 | Cookies.set('address',summary[0]); 101 | Router.pushRoute(`/election/${summary[0]}/company_dashboard`); 102 | } 103 | } 104 | catch (err) { 105 | console.log(err.Message); 106 | } 107 | } 108 | 109 | render() { 110 | const { visible } = this.state; 111 | return ( 112 |
113 | 117 | 118 | Company Login 119 | 120 |
121 | {this.returnBackImage()} 122 | 123 | 124 | 173 | 174 | 175 | 176 | 181 |
182 |

Sign up

183 | 191 | 200 | 209 | 218 | 219 |
220 | 221 | 222 | 223 | 224 |
225 |
226 | ); 227 | } 228 | } 229 | export default DividerExampleVerticalForm; 230 | -------------------------------------------------------------------------------- /pages/election/candidate_list.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Grid, Table, Button, Form, Image, Header, Icon, Menu, Modal, Sidebar, Container, Card } from 'semantic-ui-react'; 3 | import Layout from '../../components/Layout'; 4 | import web3 from '../../Ethereum/web3'; 5 | import Cookies from 'js-cookie'; 6 | import {Link,Router} from '../../routes'; 7 | import Election from '../../Ethereum/election'; 8 | import ipfs from '../../ipfs'; 9 | import {Helmet} from 'react-helmet'; 10 | class VotingList extends Component { 11 | 12 | state = { 13 | election_address: Cookies.get('address'), 14 | election_name: '', 15 | election_description: '', 16 | candidates: [], 17 | cand_name: '', 18 | cand_desc: '', 19 | buffer: '', 20 | ipfsHash: null, 21 | loading: false 22 | } 23 | 24 | async componentDidMount() { 25 | try { 26 | const add = Cookies.get('address'); 27 | const election = Election(add); 28 | const summary = await election.methods.getElectionDetails().call(); 29 | this.setState({ 30 | election_name: summary[0], 31 | election_description: summary[1] 32 | }); 33 | const c = await election.methods.getNumOfCandidates.call(); 34 | if(c == 0) 35 | alert("Register a candidate first!"); 36 | 37 | let candidates = []; 38 | for(let i=0 ; i { 43 | i++; 44 | console.log(candidate[2]); 45 | return { 46 | header: candidate[0], 47 | description: candidate[1], 48 | image: ( 49 | 50 | ), 51 | extra: ( 52 |
53 | 54 | {candidate[3].toString()} 55 |
56 | ) 57 | }; 58 | 59 | }); 60 | this.setState({item: items}); 61 | } catch(err) { 62 | console.log(err.message); 63 | alert("Redirecting you to login page..."); 64 | Router.pushRoute('/company_login'); 65 | } 66 | } 67 | getElectionDetails = () => { 68 | const { 69 | election_name, 70 | election_description 71 | } = this.state; 72 | 73 | return ( 74 |
75 |
76 | 77 | 78 | {election_name} 79 | {election_description} 80 | 81 |
82 |
83 | ); 84 | } 85 | 86 | renderTable = () => { 87 | return () 88 | } 89 | 90 | captureFile = (event) => { 91 | event.stopPropagation() 92 | event.preventDefault() 93 | const file = event.target.files[0] 94 | let reader = new window.FileReader() 95 | reader.readAsArrayBuffer(file) 96 | reader.onloadend = () => this.convertToBuffer(reader) 97 | }; 98 | 99 | convertToBuffer = async(reader) => { 100 | //file is converted to a buffer for upload to IPFS 101 | const buffer = await Buffer.from(reader.result); 102 | //set this buffer -using es6 syntax 103 | this.setState({buffer}); 104 | }; 105 | 106 | onSubmit = async (event) => { 107 | event.preventDefault(); 108 | this.setState({loading: true}); 109 | const accounts = await web3.eth.getAccounts(); 110 | 111 | try { 112 | await ipfs.add(this.state.buffer, (err, ipfsHash) => { 113 | this.setState({ ipfsHash: ipfsHash[0].hash }); 114 | 115 | const add = Cookies.get('address'); 116 | const election = Election(add); 117 | 118 | election.methods.addCandidate(this.state.cand_name,this.state.cand_desc,this.state.ipfsHash,document.getElementById('email').value).send({ 119 | from: accounts[0]}, (error, transactionHash) => {} 120 | ); 121 | }) 122 | alert("Added!"); 123 | } catch (err) { 124 | alert("Error in file processing."); 125 | } 126 | //ajax script below 127 | const email = document.getElementById('email').value; 128 | var http = new XMLHttpRequest(); 129 | var url = "/candidate/registerCandidate"; 130 | var params = "email=" + email+ "&election_name=" + this.state.election_name; 131 | http.open("POST", url, true); 132 | //Send the proper header information along with the request 133 | http.setRequestHeader( 134 | "Content-type", 135 | "application/x-www-form-urlencoded" 136 | ); 137 | http.onreadystatechange = function() { 138 | //Call a function when the state changes. 139 | if (http.readyState == 4 && http.status == 200) { 140 | var responseObj = JSON.parse(http.responseText); 141 | if(responseObj.status=="success") { 142 | alert(responseObj.message); 143 | } 144 | else { 145 | alert(responseObj.message); 146 | } 147 | } 148 | }; 149 | http.send(params); 150 | this.setState({loading: false}); 151 | }; 152 | 153 | GridExampleGrid = () => {columns} 154 | SidebarExampleVisible = () => ( 155 | 156 | 157 | 158 |

MENU


159 |
160 | 161 | 162 | 163 | 164 | Dashboard 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | Candidate List 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | Voter List 181 | 182 | 183 | 184 |
185 | 191 |
192 |
193 | ) 194 | signOut() { 195 | Cookies.remove('address'); 196 | Cookies.remove('company_email'); 197 | Cookies.remove('company_id'); 198 | alert("Logging out."); 199 | Router.pushRoute('/homepage'); 200 | } 201 | 202 | 203 | render() { 204 | const {Body, Row, HeaderCell, Header} = Table; 205 | return ( 206 |
207 | 208 | Candidate list! 209 | 210 | 211 | 212 | 213 | 214 | {this.SidebarExampleVisible()} 215 | 216 | 217 | {this.getElectionDetails()} 218 |
219 |
220 | 221 | 222 |
223 | Candidate List 224 |
225 | 226 | 227 | {this.renderTable()} 228 |
229 |
230 |
231 | 232 | 233 |
234 | Add Candidate 235 |
236 | 237 | 238 | 239 |
240 | this.setState({ cand_name: event.target.value })} 245 | textAlign='center' 246 | 247 | /> 248 | 249 |

Image:

250 | 251 | 252 |
253 | 257 | 261 |



262 |

Description:

263 | this.setState({ cand_desc: event.target.value })} 270 | /> 271 |

272 |

E-mail ID:

273 | 277 |
278 | 279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 | ); 289 | } 290 | } 291 | 292 | 293 | export default VotingList -------------------------------------------------------------------------------- /pages/election/canvasjs.react.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var CanvasJS = require('./canvasjs.min'); 3 | CanvasJS = CanvasJS.Chart ? CanvasJS : window.CanvasJS; 4 | 5 | class CanvasJSChart extends React.Component { 6 | static _cjsContainerId = 0 7 | constructor(props) { 8 | super(props); 9 | this.options = props.options ? props.options : {}; 10 | this.containerProps = props.containerProps ? props.containerProps : {width: "100%", position: "relative"}; 11 | this.containerProps.height = props.containerProps && props.containerProps.height ? props.containerProps.height : this.options.height ? this.options.height + "px" : "400px"; 12 | this.chartContainerId = "canvasjs-react-chart-container-" + CanvasJSChart._cjsContainerId++; 13 | } 14 | componentDidMount() { 15 | //Create Chart and Render 16 | this.chart = new CanvasJS.Chart(this.chartContainerId, this.options); 17 | this.chart.render(); 18 | 19 | if(this.props.onRef) 20 | this.props.onRef(this.chart); 21 | } 22 | shouldComponentUpdate(nextProps, nextState){ 23 | //Check if Chart-options has changed and determine if component has to be updated 24 | return !(nextProps.options === this.options); 25 | } 26 | componentDidUpdate() { 27 | //Update Chart Options & Render 28 | this.chart.options = this.props.options; 29 | this.chart.render(); 30 | } 31 | componentWillUnmount() { 32 | //Destroy chart and remove reference 33 | this.chart.destroy(); 34 | if(this.props.onRef) 35 | this.props.onRef(undefined); 36 | } 37 | render() { 38 | //return React.createElement('div', { id: this.chartContainerId, style: this.containerProps }); 39 | return
40 | } 41 | } 42 | 43 | var CanvasJSReact = { 44 | CanvasJSChart: CanvasJSChart, 45 | CanvasJS: CanvasJS 46 | }; 47 | 48 | export default CanvasJSReact; -------------------------------------------------------------------------------- /pages/election/company_dashboard.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Grid, Step, Icon, Menu, Sidebar, Container, Modal, Card, Header, Button, Item } from 'semantic-ui-react'; 3 | import Layout from '../../components/Layout'; 4 | import { Bar } from 'react-chartjs-2'; 5 | import 'chartjs-plugin-annotation'; 6 | import Election from '../../Ethereum/election'; 7 | import Cookies from 'js-cookie'; 8 | import web3 from '../../Ethereum/web3'; 9 | import { Link, Router } from '../../routes'; 10 | import { Helmet } from 'react-helmet'; 11 | 12 | var b = 0; 13 | let cand = []; 14 | let graphEmail = []; 15 | let graphVotes = []; 16 | 17 | const options = { 18 | maintainAspectRatio: true, 19 | responsive: true, 20 | scales: { 21 | yAxes: [ 22 | { 23 | height: '500px', 24 | stacked: true, 25 | gridLines: { 26 | display: true, 27 | color: 'rgba(255,99,132,0.2)', 28 | }, 29 | }, 30 | ], 31 | xAxes: [ 32 | { 33 | width: '500px', 34 | gridLines: { 35 | display: false, 36 | }, 37 | }, 38 | ], 39 | }, 40 | }; 41 | 42 | const data = { 43 | labels: graphEmail, 44 | datasets: [ 45 | { 46 | label: 'Vote Counts', 47 | backgroundColor: 'rgba(255,99,132,0.2)', 48 | borderColor: 'rgba(255,99,132,1)', 49 | borderWidth: 2, 50 | hoverBackgroundColor: 'rgba(255,99,132,0.4)', 51 | hoverBorderColor: 'rgba(255,99,132,1)', 52 | data: graphVotes, 53 | }, 54 | ], 55 | }; 56 | 57 | class ContainerExampleContainer extends Component { 58 | state = { 59 | election_address: Cookies.get('address'), 60 | election_name: '', 61 | election_desc: '', 62 | voters: 0, 63 | candidates: 0, 64 | visible: false, 65 | loading: false, 66 | b: 0, 67 | }; 68 | async componentDidMount() { 69 | var http = new XMLHttpRequest(); 70 | var url = '/voter/'; 71 | var params = 'election_address=' + Cookies.get('address'); 72 | http.open('POST', url, true); 73 | //Send the proper header information along with the request 74 | http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 75 | http.onreadystatechange = function () { 76 | //Call a function when the state changes. 77 | if (http.readyState == 4 && http.status == 200) { 78 | var responseObj = JSON.parse(http.responseText); 79 | if (responseObj.status == 'success') { 80 | b = responseObj.count; 81 | } 82 | } 83 | }; 84 | http.send(params); 85 | try { 86 | const add = Cookies.get('address'); 87 | const election = Election(add); 88 | const summary = await election.methods.getElectionDetails().call(); 89 | const v = await election.methods.getNumOfVoters().call(); 90 | this.setState({ voters: v }); 91 | const c = await election.methods.getNumOfCandidates().call(); 92 | this.setState({ candidates: c }); 93 | this.setState({ 94 | election_name: summary[0], 95 | election_desc: summary[1], 96 | }); 97 | 98 | for (let i = 0; i < c; i++) { 99 | const tp = await election.methods.getCandidate(i).call(); 100 | graphEmail.push(tp[0]); 101 | graphVotes.push(tp[3]); 102 | } 103 | this.returnGraph(); 104 | } catch (err) { 105 | console.log(err.message); 106 | alert('Redirecting you to login page...'); 107 | Router.pushRoute('/company_login'); 108 | } 109 | this.setState({ b: b }); 110 | } 111 | 112 | getElectionDetails = () => { 113 | const { election_name, election_desc } = this.state; 114 | 115 | return ( 116 |
117 |
118 | 119 | 120 | {election_name} 121 | {election_desc} 122 | 123 |
124 |
125 | ); 126 | }; 127 | CardExampleGroupProps = () => ; 128 | GridExampleGrid = () => {columns}; 129 | SidebarExampleVisible = () => ( 130 | 131 | 141 | 142 |

MENU

143 |
144 |
145 | 146 | 147 | 148 | 149 | Dashboard 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | Candidate List 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | Voter List 166 | 167 | 168 | 169 |
170 | 176 |
177 |
178 | ); 179 | signOut() { 180 | Cookies.remove('address'); 181 | Cookies.remove('company_email'); 182 | Cookies.remove('company_id'); 183 | alert('Logging out.'); 184 | Router.pushRoute('/homepage'); 185 | } 186 | endElection = async event => { 187 | let candidate = 0; 188 | try { 189 | this.setState({ loading: true }); 190 | const add = Cookies.get('address'); 191 | const election = Election(add); 192 | candidate = await election.methods.winnerCandidate().call(); 193 | cand = await election.methods.getCandidate(candidate).call(); 194 | var http = new XMLHttpRequest(); 195 | var url = '/voter/resultMail'; 196 | var params = 197 | 'election_address=' + 198 | Cookies.get('address') + 199 | '&election_name=' + 200 | this.state.election_name + 201 | '&candidate_email=' + 202 | cand[4] + 203 | '&winner_candidate=' + 204 | cand[0]; 205 | http.open('POST', url, true); 206 | //Send the proper header information along with the request 207 | http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 208 | http.onreadystatechange = function () { 209 | //Call a function when the state changes. 210 | if (http.readyState == 4 && http.status == 200) { 211 | var responseObj = JSON.parse(http.responseText); 212 | if (responseObj.status == 'success') { 213 | alert('Mail sent!'); 214 | } else { 215 | alert(responseObj.message); 216 | } 217 | } 218 | }; 219 | this.setState({ loading: true }); 220 | http.send(params); 221 | } catch (err) { 222 | console.log(err.message); 223 | } 224 | }; 225 | 226 | returnModal = () =>

I won the election

; 227 | 228 | returnGraph = () => ; 229 | 230 | render() { 231 | return ( 232 |
233 | 234 | Dashboard 235 | 236 | 237 | 238 | 239 | {this.SidebarExampleVisible()} 240 | 241 | 242 | 243 | {this.getElectionDetails()} 244 | 252 | 253 | 254 | 255 | 260 | 261 | {this.CardExampleGroupProps()} 262 | 263 | 264 |
265 |
266 | 272 | {this.returnGraph()} 273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 | ); 281 | } 282 | } 283 | 284 | export default ContainerExampleContainer; 285 | -------------------------------------------------------------------------------- /pages/election/create_election.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Button, Form, Grid, Header, Segment, Icon, Message } from 'semantic-ui-react'; 3 | import web3 from '../../Ethereum/web3'; 4 | import Election_Factory from '../../Ethereum/election_factory'; 5 | import { Router } from '../../routes'; 6 | import Cookies from 'js-cookie'; 7 | class LoginForm extends Component { 8 | state = { 9 | //retrieve the company's email via cookie 10 | election_name: '', 11 | election_description: '', 12 | loading: false, 13 | errorMess: '', 14 | }; 15 | 16 | signin = async event => { 17 | event.preventDefault(); 18 | this.setState({ loading: true, errorMess: '' }); 19 | try { 20 | const email = Cookies.get('company_email'); 21 | const accounts = await web3.eth.getAccounts(); 22 | const bool = await Election_Factory.methods 23 | .createElection(email, this.state.election_name, this.state.election_description) 24 | .send({ from: accounts[0] }); 25 | 26 | if (bool) { 27 | const summary = await Election_Factory.methods.getDeployedElection('xyz').call(); 28 | this.setState({ loading: false }); 29 | Cookies.set('address', summary[0]); 30 | Router.pushRoute(`/election/${summary[0]}/company_dashboard`); 31 | } 32 | } catch (err) { 33 | this.setState({ errorMess: err.message }); 34 | } 35 | }; 36 | 37 | LoginForm = () => ( 38 |
39 | 47 | 48 | 49 | 50 |
51 | 52 |
53 | Create an election! 54 |
55 | this.setState({ election_name: event.target.value })} 63 | required={true} 64 | /> 65 | this.setState({ election_description: event.target.value })} 77 | /> 78 | 79 | 89 | 90 | 91 | Note: 92 | Election creation will take several minutes. 93 | 94 |
95 |
96 |
97 |
98 |
99 | ); 100 | 101 | render() { 102 | return ( 103 |
104 | 105 | {/* */} 106 | {this.LoginForm()} 107 |
108 | ); 109 | } 110 | } 111 | 112 | export default LoginForm; 113 | -------------------------------------------------------------------------------- /pages/election/vote.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Grid, Button, Header, Icon, Image, Menu, Sidebar, Container, Card } from 'semantic-ui-react'; 3 | import Layout from '../../components/Layout'; 4 | import web3 from '../../Ethereum/web3'; 5 | import Election from '../../Ethereum/election'; 6 | import Cookies from 'js-cookie'; 7 | import {Router} from '../../routes'; 8 | import {Helmet} from 'react-helmet'; 9 | 10 | class VotingList extends Component { 11 | 12 | state = { 13 | numCand: '', 14 | election_address: Cookies.get('address'), 15 | election_name: '', 16 | election_description: '', 17 | candidates: [], 18 | cand_name: '', 19 | cand_desc: '', 20 | buffer: '', 21 | ipfsHash: null, 22 | loading: false 23 | }; 24 | GridExampleGrid = () => {columns} 25 | SidebarExampleVisible = () => ( 26 | 27 | 28 | 29 | 30 |

MENU


31 |
32 | 33 | 34 | Dashboard 35 | 36 |
37 | 43 |
44 |
45 | ) 46 | 47 | signOut() { 48 | Cookies.remove('address'); 49 | Cookies.remove('voter_email'); 50 | alert("Logging out."); 51 | Router.pushRoute('/homepage'); 52 | } 53 | 54 | async componentDidMount() { 55 | try { 56 | const add = Cookies.get('address'); 57 | const election = Election(add); 58 | const summary = await election.methods.getElectionDetails().call(); 59 | this.setState({ 60 | election_name: summary[0], 61 | election_description: summary[1] 62 | }); 63 | const c = await election.methods.getNumOfCandidates.call(); 64 | 65 | let candidates = []; 66 | for(let i=0 ; i { 71 | i++; 72 | return { 73 | header: candidate[0], 74 | description: candidate[1], 75 | image: ( 76 | 77 | ), 78 | extra: ( 79 |
80 | 81 | {candidate[3].toString()} 82 | 83 |
84 | ) 85 | }; 86 | 87 | }); 88 | this.setState({item: items}); 89 | } catch(err) { 90 | console.log(err.message); 91 | alert("Session expired. Redirecting you to login page..."); 92 | Router.pushRoute('/voter_login'); 93 | } 94 | } 95 | getElectionDetails = () => { 96 | const { 97 | election_name, 98 | election_description 99 | } = this.state; 100 | 101 | return ( 102 |
103 |
104 | 105 | 106 | {election_name} 107 | {election_description} 108 | 109 |
110 |
111 | ); 112 | } 113 | 114 | renderTable = () => { 115 | return () 116 | } 117 | 118 | vote = async event => { 119 | const e = parseInt(event.currentTarget.id,10); 120 | const accounts = await web3.eth.getAccounts(); 121 | const add = Cookies.get('address'); 122 | const election = Election(add); 123 | await election.methods.vote(e,Cookies.get('voter_email')).send({from: accounts[0]}); 124 | alert("Voted!") 125 | } 126 | 127 | render() { 128 | return ( 129 |
130 | 131 | Vote 132 | 133 | 134 | 135 | 136 | 137 | {this.SidebarExampleVisible()} 138 | 139 | 140 | {this.getElectionDetails()} 141 | 142 | 143 | {this.renderTable()} 144 | 145 | 146 | 147 | 148 | 149 |
150 | ); 151 | } 152 | } 153 | 154 | 155 | export default VotingList -------------------------------------------------------------------------------- /pages/election/voting_list.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Grid, Header, Button, Form, Input, Icon, Menu, Modal, Sidebar, Container, Card } from 'semantic-ui-react'; 3 | import Layout from '../../components/Layout'; 4 | import Cookies from 'js-cookie'; 5 | import {Link,Router} from '../../routes'; 6 | import Election from '../../Ethereum/election'; 7 | import {Helmet} from 'react-helmet'; 8 | class VotingList extends Component { 9 | 10 | state = { 11 | election_address: Cookies.get('address'), 12 | election_name: '', 13 | election_description: '', 14 | emailArr: [], 15 | idArr: [], 16 | item: [], 17 | } 18 | 19 | async componentDidMount() { 20 | var http = new XMLHttpRequest(); 21 | var url = '/voter/'; 22 | var params = 'election_address='+this.state.election_address; 23 | http.open("POST", url, true); 24 | let email=[]; 25 | let id=[] 26 | //Send the proper header information along with the request 27 | http.setRequestHeader( 28 | "Content-type", 29 | "application/x-www-form-urlencoded" 30 | ); 31 | http.onreadystatechange = function() { 32 | //Call a function when the state changes. 33 | if (http.readyState == 4 && http.status == 200) { 34 | var responseObj = JSON.parse(http.responseText); 35 | if(responseObj.status=="success") { 36 | for (let voter of responseObj.data.voters) { 37 | email.push(voter.email); 38 | id.push(voter.id); 39 | } 40 | } 41 | } 42 | }; 43 | http.send(params); 44 | this.state.emailArr.push(email); 45 | this.state.idArr.push(id); 46 | 47 | try { 48 | const add = Cookies.get('address'); 49 | const election = Election(add); 50 | const summary = await election.methods.getElectionDetails().call(); 51 | this.setState({ 52 | election_name: summary[0], 53 | election_description: summary[1] 54 | }); 55 | 56 | } catch(err) { 57 | console.log(err.message); 58 | alert("Redirecting you to login page..."); 59 | Router.pushRoute('/company_login'); 60 | } 61 | let ea = []; 62 | ea = this.state.emailArr[0]; 63 | let ia = []; 64 | ia = this.state.idArr[0]; 65 | 66 | let i=-1; 67 | const items = ia.map(ia => { 68 | i++; 69 | return { 70 | header: email[i], 71 | description: ( 72 |
73 |
74 | 75 | 77 | Edit 78 | 79 | }closeIcon 80 | > 81 | Edit E-mail ID 82 |
83 | 84 | 85 | 86 | 87 | 98 | 99 |
100 |
101 | 102 |
103 | ) 104 | }; 105 | }); 106 | this.setState({item: items}); 107 | } 108 | 109 | updateEmail = event => { 110 | 111 | const d = event.currentTarget.id; 112 | const st = 'EmailVal'+event.currentTarget.id; 113 | const a = document.getElementById(st).value; 114 | const b = this.state.election_name; 115 | const c = this.state.election_description; 116 | //further proceed 117 | 118 | var http = new XMLHttpRequest(); 119 | var url = '/voter/'+d; 120 | var params = 'email='+a+'&election_name='+b+'&election_description='+c; 121 | http.open("PUT", url, true); 122 | //Send the proper header information along with the request 123 | http.setRequestHeader( 124 | "Content-type", 125 | "application/x-www-form-urlencoded" 126 | ); 127 | http.onreadystatechange = function() { 128 | //Call a function when the state changes. 129 | if (http.readyState == 4 && http.status == 200) { 130 | var responseObj = JSON.parse(http.responseText); 131 | if(responseObj.status=="success") { 132 | alert(responseObj.message); 133 | } 134 | } 135 | }; 136 | http.send(params); 137 | } 138 | 139 | deleteEmail = event => { 140 | //further proceed 141 | 142 | var http = new XMLHttpRequest(); 143 | var url = '/voter/'+event.currentTarget.value; 144 | http.open("DELETE", url, true); 145 | //Send the proper header information along with the request 146 | http.setRequestHeader( 147 | "Content-type", 148 | "application/x-www-form-urlencoded" 149 | ); 150 | http.onreadystatechange = function() { 151 | //Call a function when the state changes. 152 | if (http.readyState == 4 && http.status == 200) { 153 | var responseObj = JSON.parse(http.responseText); 154 | if(responseObj.status=="success") { 155 | alert(responseObj.message); 156 | } 157 | } 158 | }; 159 | http.send(); 160 | } 161 | 162 | renderTable = () => { 163 | return () 164 | } 165 | 166 | GridExampleGrid = () => {columns} 167 | SidebarExampleVisible = () => ( 168 | 169 | 170 | 171 |

MENU


172 |
173 | 174 | 175 | 176 | 177 | Dashboard 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | Candidate List 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | Voter List 194 | 195 | 196 | 197 |
198 | 204 |
205 |
206 | ) 207 | signOut() { 208 | Cookies.remove('address'); 209 | Cookies.remove('company_email'); 210 | Cookies.remove('company_id'); 211 | alert("Logging out."); 212 | Router.pushRoute('/homepage'); 213 | } 214 | 215 | register = event => { 216 | 217 | const email = document.getElementById('register_voter_email').value; 218 | 219 | var http = new XMLHttpRequest(); 220 | var url = "/voter/register"; 221 | var params = "email=" + email+"&election_address=" + this.state.election_address+ "&election_name=" + this.state.election_name + "&election_description=" + this.state.election_description; 222 | http.open("POST", url, true); 223 | //Send the proper header information along with the request 224 | http.setRequestHeader( 225 | "Content-type", 226 | "application/x-www-form-urlencoded" 227 | ); 228 | http.onreadystatechange = function() { 229 | //Call a function when the state changes. 230 | if (http.readyState == 4 && http.status == 200) { 231 | var responseObj = JSON.parse(http.responseText); 232 | if(responseObj.status=="success") { 233 | alert(responseObj.message); 234 | } 235 | else { 236 | alert(responseObj.message); 237 | } 238 | } 239 | }; 240 | http.send(params); 241 | } 242 | 243 | render() { 244 | return ( 245 |
246 | 247 | Voting list 248 | 249 | 250 | 251 | 252 | 253 | {this.SidebarExampleVisible()} 254 | 255 | 256 |
257 |
258 | 259 | 260 |
261 | Voter List 262 |
263 | 264 | 265 | {this.renderTable()} 266 |
267 |
268 |
269 | 270 | 271 |
272 | Register Voter 273 |
274 | 275 |
276 | 277 | 285 | 286 |

287 | 288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 | ); 298 | } 299 | } 300 | 301 | 302 | export default VotingList -------------------------------------------------------------------------------- /pages/homepage.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React, { Component } from 'react'; 3 | import { Link } from '../routes'; 4 | import { 5 | Button, 6 | Container, 7 | Divider, 8 | Grid, 9 | Header, 10 | Icon, 11 | Image, 12 | List, 13 | Menu, 14 | Responsive, 15 | Segment, 16 | Sidebar, 17 | Visibility, 18 | } from 'semantic-ui-react'; 19 | import '../static/hometest.css'; 20 | import { Helmet } from 'react-helmet'; 21 | const HomepageHeading = ({ mobile }) => ( 22 | 23 |
35 |
46 |
47 |
48 | Register/ Sign in for the company 49 |
50 | 51 | 55 | 56 |
57 | 58 |
59 |
60 | {' '} 61 | Sign in for Voters! 62 |
63 | 64 | 68 | 69 |
70 | 71 | ); 72 | 73 | HomepageHeading.propTypes = { 74 | mobile: PropTypes.bool, 75 | }; 76 | 77 | class DesktopContainer extends Component { 78 | state = {}; 79 | 80 | hideFixedMenu = () => this.setState({ fixed: false }); 81 | showFixedMenu = () => this.setState({ fixed: true }); 82 | 83 | render() { 84 | const { children } = this.props; 85 | const { fixed } = this.state; 86 | 87 | return ( 88 | 89 | 90 | 91 | HomePage 92 | 93 | 94 | 95 | 96 | 104 | 105 |

114 | BlockVotes 115 |

116 |
117 |
118 | 119 |
120 |
121 | 122 | {children} 123 |
124 | ); 125 | } 126 | } 127 | 128 | DesktopContainer.propTypes = { 129 | children: PropTypes.node, 130 | }; 131 | 132 | const ResponsiveContainer = ({ children }) => ( 133 |
134 | {children} 135 |
136 | ); 137 | 138 | ResponsiveContainer.propTypes = { 139 | children: PropTypes.node, 140 | }; 141 | 142 | const HomepageLayout = () => ( 143 | 144 | 145 | 146 | 147 | 148 |
149 | Private 150 |
151 |

152 | Doesn't give any information
153 | regarding personal data. 154 |

155 |
156 | Secure 157 |
158 |

159 | Not even a single chance of shutting
down of the system. 160 |

161 |
162 | 163 | 164 | 165 |
166 | Decentralized 167 |
168 |

169 | Decentralized technology gives you the
power to store your assets in a network. 170 |

171 |
172 | Immutable 173 |
174 |

175 | Keeps its ledgers in a never-ending
state of forwarding momentum. 176 |

177 |
178 |
179 |
180 |
181 | 182 | 183 | 184 |
185 | A fascinating quote 186 |
187 |

188 | "We have elected to put our money and faith in a mathematical framework that is free of politics and 189 | human error." 190 |

191 |
192 | Tyler Winklevoss 193 |
194 |
195 |
196 |
197 | ); 198 | export default HomepageLayout; 199 | -------------------------------------------------------------------------------- /pages/voter_login.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Button, Form, Grid, Header, Image, Message, Segment } from 'semantic-ui-react'; 3 | import Cookies from 'js-cookie'; 4 | import { Router } from '../routes'; 5 | import { Helmet } from 'react-helmet'; 6 | 7 | class LoginForm extends Component { 8 | state = { 9 | election_address: '', 10 | }; 11 | 12 | LoginForm = () => ( 13 |
14 | 22 | 23 | 24 | 25 |
26 | 27 |
28 | Login 29 |
30 | 38 | 47 | 48 | 51 |
52 |
53 |
54 |
55 |
56 | ); 57 | signin = event => { 58 | const email = document.getElementById('signin_email').value; 59 | const password = document.getElementById('signin_password').value; 60 | var http = new XMLHttpRequest(); 61 | var url = 'voter/authenticate'; 62 | var params = 'email=' + email + '&password=' + password; 63 | http.open('POST', url, true); 64 | //Send the proper header information along with the request 65 | http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 66 | http.onreadystatechange = function () { 67 | //Call a function when the state changes. 68 | if (http.readyState == 4 && http.status == 200) { 69 | var responseObj = JSON.parse(http.responseText); 70 | if (responseObj.status == 'success') { 71 | Cookies.set('voter_email', encodeURI(email)); 72 | Cookies.set('address', encodeURI(responseObj.data.election_address)); 73 | Router.pushRoute(`/election/${responseObj.data.election_address}/vote`); 74 | } else { 75 | alert(responseObj.message); 76 | } 77 | } 78 | }; 79 | http.send(params); 80 | }; 81 | 82 | render() { 83 | return ( 84 |
85 | 86 | 87 | Voter login 88 | 89 | 90 | {this.LoginForm()} 91 |
92 | ); 93 | } 94 | } 95 | 96 | export default LoginForm; 97 | -------------------------------------------------------------------------------- /routes.js: -------------------------------------------------------------------------------- 1 | const routes = require('next-routes')(); 2 | 3 | routes 4 | .add('/homepage','/homepage') 5 | .add('/company_login','/company_login') 6 | .add('/voter_login','/voter_login') 7 | .add('/election/:address/company_dashboard','/election/company_dashboard') 8 | .add('/election/:address/voting_list','/election/voting_list') 9 | .add('/election/:address/addcand','/election/addcand') 10 | .add('/election/:address/vote','/election/vote') 11 | .add('/election/:address/candidate_list','/election/candidate_list'); 12 | module.exports = routes; -------------------------------------------------------------------------------- /routes/candidate.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const candidateController = require('../controllers/candidate'); 4 | router.post('/registerCandidate',candidateController.register); 5 | module.exports = router; -------------------------------------------------------------------------------- /routes/company.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const CompanyController = require('../controllers/company'); 4 | router.post('/register', CompanyController.create); 5 | router.post('/authenticate', CompanyController.authenticate); 6 | module.exports = router; -------------------------------------------------------------------------------- /routes/voter.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const voterController = require('../controllers/voter'); 4 | router.post('/register', voterController.create); 5 | router.post('/authenticate', voterController.authenticate); 6 | router.post('/', voterController.getAll); 7 | router.put('/:voterId', voterController.updateById); 8 | router.delete('/:voterId', voterController.deleteById); 9 | router.post('/resultMail', voterController.resultMail); 10 | module.exports = router; -------------------------------------------------------------------------------- /screenshots/candidate_list.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/candidate_list.PNG -------------------------------------------------------------------------------- /screenshots/candidate_registeration_mail.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/candidate_registeration_mail.PNG -------------------------------------------------------------------------------- /screenshots/company_login.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/company_login.PNG -------------------------------------------------------------------------------- /screenshots/create_election.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/create_election.PNG -------------------------------------------------------------------------------- /screenshots/dashboard.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/dashboard.PNG -------------------------------------------------------------------------------- /screenshots/homepage.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/homepage.PNG -------------------------------------------------------------------------------- /screenshots/successful_voting.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/successful_voting.PNG -------------------------------------------------------------------------------- /screenshots/unsuccessful_voting.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/unsuccessful_voting.PNG -------------------------------------------------------------------------------- /screenshots/voter_login.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/voter_login.PNG -------------------------------------------------------------------------------- /screenshots/voter_registeration_mail.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/voter_registeration_mail.PNG -------------------------------------------------------------------------------- /screenshots/voterlist.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/voterlist.PNG -------------------------------------------------------------------------------- /screenshots/winner_candidate_mail.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/screenshots/winner_candidate_mail.PNG -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const next = require('next'); 2 | const express = require('express'); 3 | const voter = require('./routes/voter'); 4 | const company = require('./routes/company'); 5 | const candidate = require('./routes/candidate'); 6 | const bodyParser = require('body-parser'); 7 | const mongoose = require('./config/database'); 8 | const exp = express(); 9 | const path = require('path'); 10 | 11 | require('dotenv').config({ path: __dirname + '/.env' }); 12 | 13 | mongoose.connection.on('error', console.error.bind(console, 'MongoDB connection error:')); 14 | 15 | exp.use( 16 | bodyParser.urlencoded({ 17 | extended: true, 18 | }) 19 | ); 20 | exp.use(bodyParser.json()); 21 | exp.get('/', function (req, res) { 22 | res.sendFile(path.join(__dirname + '/pages/homepage.js')); 23 | }); 24 | 25 | exp.use('/company', company); 26 | 27 | exp.use('/voter', voter); 28 | 29 | exp.use('/candidate', candidate); 30 | 31 | const app = next({ 32 | dev: process.env.NODE_ENV !== 'production', 33 | }); 34 | 35 | const routes = require('./routes'); 36 | const handler = routes.getRequestHandler(app); 37 | 38 | app.prepare().then(() => { 39 | exp.use(handler).listen(3000, function () { 40 | console.log('Node server listening on port 3000'); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /static/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/static/banner.jpg -------------------------------------------------------------------------------- /static/blockchain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/static/blockchain.jpg -------------------------------------------------------------------------------- /static/blocv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/static/blocv.png -------------------------------------------------------------------------------- /static/bv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/static/bv.png -------------------------------------------------------------------------------- /static/ether2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/static/ether2.png -------------------------------------------------------------------------------- /static/hometest.css: -------------------------------------------------------------------------------- 1 | #__next > div > div > div:nth-child(2) > div 2 | { 3 | /* background-image: url("bg2.png"); 4 | */ 5 | background-color: #0688ba; 6 | background: url('/static/banner.jpg') no-repeat; 7 | /* background-size:cover; */ 8 | background-origin: inherit; 9 | 10 | } 11 | #__next > div > div > div:nth-child(2) > div > div.ui.large.inverted.pointing.secondary.menu 12 | { 13 | border-width: 0mm; 14 | } -------------------------------------------------------------------------------- /static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/static/logo.png -------------------------------------------------------------------------------- /static/logo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehtaAnsh/BlockChainVoting/f4ff491fa26ea3e9557a122eb911f0742bc88b9a/static/logo3.png -------------------------------------------------------------------------------- /static/test.css: -------------------------------------------------------------------------------- 1 | /* .example { 2 | color: wheat; 3 | font-size: 50px; 4 | } 5 | .bg{ 6 | width:100%; 7 | height:80%; 8 | z-index: -100; 9 | } 10 | 11 | .ui buttons{ 12 | position: absolute !important; 13 | z-index: 1000; 14 | top:0px; 15 | } 16 | .ui primary button{ 17 | position: absolute !important; 18 | /* z-index: 1000;*/ 19 | /* top:100px; 20 | } 21 | #__next > div > div.ui.buttons > button:nth-child(1) 22 | { 23 | position: absolute !important; 24 | top:0px; 25 | left:0px; 26 | z-index:100; 27 | } 28 | #__next > div > div.ui.buttons > button:nth-child(3) 29 | { 30 | position: absolute !important; 31 | top:0px; 32 | left:83px; 33 | z-index:100; 34 | } 35 | #__next > div > div.ui.grid.grid1 > div { 36 | padding-top: 10%; 37 | } 38 | #__next > div > div.ui.buttons > div 39 | { 40 | position: absolute !important; 41 | top:0px; 42 | left:85px; 43 | z-index:102; 44 | } 45 | #__next > div > div.ui.grid > div > div.middle.aligned.ten.wide.column > div 46 | { 47 | width:300px; 48 | left:30%; 49 | 50 | } 51 | .row{ 52 | position: absolute !important; 53 | top:20px; 54 | } 55 | body{ 56 | overflow: hidden; 57 | } 58 | body { */ 59 | /* background: #1D1F20; */ 60 | /* padding: 6px; 61 | } 62 | */ 63 | /* canvas { 64 | border: 1px dotted red; 65 | } 66 | */ 67 | /* .chart-container { 68 | position: absolute; 69 | margin: 0; 70 | height: 0; 71 | width: 85%; 72 | padding-left: 4%; 73 | padding-top: 0px; 74 | } 75 | #__next > div > div.ui.grid > div > div:nth-child(2) > div:nth-child(2) > img 76 | { 77 | position: relative; 78 | margin: auto; 79 | top: 10; 80 | } 81 | #__next > div > div > div > div.ui.container > div.sixteen.wide.column > div.column > div 82 | { 83 | position: relative; 84 | margin: auto; 85 | top: 0; 86 | } */ 87 | 88 | /* #__next > canvas{ 89 | position: relative; 90 | margin: auto; 91 | height: 100%; 92 | width: 100%; 93 | } */ 94 | -------------------------------------------------------------------------------- /static/themify-icons.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'themify'; 3 | src:url('../fonts/themify.eot?-fvbane'); 4 | src:url('../fonts/themify.eot?#iefix-fvbane') format('embedded-opentype'), 5 | url('../fonts/themify.woff?-fvbane') format('woff'), 6 | url('../fonts/themify.ttf?-fvbane') format('truetype'), 7 | url('../fonts/themify.svg?-fvbane#themify') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | [class^="ti-"], [class*=" ti-"] { 13 | font-family: 'themify'; 14 | speak: none; 15 | font-style: normal; 16 | font-weight: bold; 17 | font-variant: normal; 18 | text-transform: none; 19 | line-height: 1.42857; 20 | 21 | /* Better Font Rendering =========== */ 22 | -webkit-font-smoothing: antialiased; 23 | -moz-osx-font-smoothing: grayscale; 24 | } 25 | 26 | .ti-wand:before { 27 | content: "\e600"; 28 | } 29 | .ti-volume:before { 30 | content: "\e601"; 31 | } 32 | .ti-user:before { 33 | content: "\e602"; 34 | } 35 | .ti-unlock:before { 36 | content: "\e603"; 37 | } 38 | .ti-unlink:before { 39 | content: "\e604"; 40 | } 41 | .ti-trash:before { 42 | content: "\e605"; 43 | } 44 | .ti-thought:before { 45 | content: "\e606"; 46 | } 47 | .ti-target:before { 48 | content: "\e607"; 49 | } 50 | .ti-tag:before { 51 | content: "\e608"; 52 | } 53 | .ti-tablet:before { 54 | content: "\e609"; 55 | } 56 | .ti-star:before { 57 | content: "\e60a"; 58 | } 59 | .ti-spray:before { 60 | content: "\e60b"; 61 | } 62 | .ti-signal:before { 63 | content: "\e60c"; 64 | } 65 | .ti-shopping-cart:before { 66 | content: "\e60d"; 67 | } 68 | .ti-shopping-cart-full:before { 69 | content: "\e60e"; 70 | } 71 | .ti-settings:before { 72 | content: "\e60f"; 73 | } 74 | .ti-search:before { 75 | content: "\e610"; 76 | } 77 | .ti-zoom-in:before { 78 | content: "\e611"; 79 | } 80 | .ti-zoom-out:before { 81 | content: "\e612"; 82 | } 83 | .ti-cut:before { 84 | content: "\e613"; 85 | } 86 | .ti-ruler:before { 87 | content: "\e614"; 88 | } 89 | .ti-ruler-pencil:before { 90 | content: "\e615"; 91 | } 92 | .ti-ruler-alt:before { 93 | content: "\e616"; 94 | } 95 | .ti-bookmark:before { 96 | content: "\e617"; 97 | } 98 | .ti-bookmark-alt:before { 99 | content: "\e618"; 100 | } 101 | .ti-reload:before { 102 | content: "\e619"; 103 | } 104 | .ti-plus:before { 105 | content: "\e61a"; 106 | } 107 | .ti-pin:before { 108 | content: "\e61b"; 109 | } 110 | .ti-pencil:before { 111 | content: "\e61c"; 112 | } 113 | .ti-pencil-alt:before { 114 | content: "\e61d"; 115 | } 116 | .ti-paint-roller:before { 117 | content: "\e61e"; 118 | } 119 | .ti-paint-bucket:before { 120 | content: "\e61f"; 121 | } 122 | .ti-na:before { 123 | content: "\e620"; 124 | } 125 | .ti-mobile:before { 126 | content: "\e621"; 127 | } 128 | .ti-minus:before { 129 | content: "\e622"; 130 | } 131 | .ti-medall:before { 132 | content: "\e623"; 133 | } 134 | .ti-medall-alt:before { 135 | content: "\e624"; 136 | } 137 | .ti-marker:before { 138 | content: "\e625"; 139 | } 140 | .ti-marker-alt:before { 141 | content: "\e626"; 142 | } 143 | .ti-arrow-up:before { 144 | content: "\e627"; 145 | } 146 | .ti-arrow-right:before { 147 | content: "\e628"; 148 | } 149 | .ti-arrow-left:before { 150 | content: "\e629"; 151 | } 152 | .ti-arrow-down:before { 153 | content: "\e62a"; 154 | } 155 | .ti-lock:before { 156 | content: "\e62b"; 157 | } 158 | .ti-location-arrow:before { 159 | content: "\e62c"; 160 | } 161 | .ti-link:before { 162 | content: "\e62d"; 163 | } 164 | .ti-layout:before { 165 | content: "\e62e"; 166 | } 167 | .ti-layers:before { 168 | content: "\e62f"; 169 | } 170 | .ti-layers-alt:before { 171 | content: "\e630"; 172 | } 173 | .ti-key:before { 174 | content: "\e631"; 175 | } 176 | .ti-import:before { 177 | content: "\e632"; 178 | } 179 | .ti-image:before { 180 | content: "\e633"; 181 | } 182 | .ti-heart:before { 183 | content: "\e634"; 184 | } 185 | .ti-heart-broken:before { 186 | content: "\e635"; 187 | } 188 | .ti-hand-stop:before { 189 | content: "\e636"; 190 | } 191 | .ti-hand-open:before { 192 | content: "\e637"; 193 | } 194 | .ti-hand-drag:before { 195 | content: "\e638"; 196 | } 197 | .ti-folder:before { 198 | content: "\e639"; 199 | } 200 | .ti-flag:before { 201 | content: "\e63a"; 202 | } 203 | .ti-flag-alt:before { 204 | content: "\e63b"; 205 | } 206 | .ti-flag-alt-2:before { 207 | content: "\e63c"; 208 | } 209 | .ti-eye:before { 210 | content: "\e63d"; 211 | } 212 | .ti-export:before { 213 | content: "\e63e"; 214 | } 215 | .ti-exchange-vertical:before { 216 | content: "\e63f"; 217 | } 218 | .ti-desktop:before { 219 | content: "\e640"; 220 | } 221 | .ti-cup:before { 222 | content: "\e641"; 223 | } 224 | .ti-crown:before { 225 | content: "\e642"; 226 | } 227 | .ti-comments:before { 228 | content: "\e643"; 229 | } 230 | .ti-comment:before { 231 | content: "\e644"; 232 | } 233 | .ti-comment-alt:before { 234 | content: "\e645"; 235 | } 236 | .ti-close:before { 237 | content: "\e646"; 238 | } 239 | .ti-clip:before { 240 | content: "\e647"; 241 | } 242 | .ti-angle-up:before { 243 | content: "\e648"; 244 | } 245 | .ti-angle-right:before { 246 | content: "\e649"; 247 | } 248 | .ti-angle-left:before { 249 | content: "\e64a"; 250 | } 251 | .ti-angle-down:before { 252 | content: "\e64b"; 253 | } 254 | .ti-check:before { 255 | content: "\e64c"; 256 | } 257 | .ti-check-box:before { 258 | content: "\e64d"; 259 | } 260 | .ti-camera:before { 261 | content: "\e64e"; 262 | } 263 | .ti-announcement:before { 264 | content: "\e64f"; 265 | } 266 | .ti-brush:before { 267 | content: "\e650"; 268 | } 269 | .ti-briefcase:before { 270 | content: "\e651"; 271 | } 272 | .ti-bolt:before { 273 | content: "\e652"; 274 | } 275 | .ti-bolt-alt:before { 276 | content: "\e653"; 277 | } 278 | .ti-blackboard:before { 279 | content: "\e654"; 280 | } 281 | .ti-bag:before { 282 | content: "\e655"; 283 | } 284 | .ti-move:before { 285 | content: "\e656"; 286 | } 287 | .ti-arrows-vertical:before { 288 | content: "\e657"; 289 | } 290 | .ti-arrows-horizontal:before { 291 | content: "\e658"; 292 | } 293 | .ti-fullscreen:before { 294 | content: "\e659"; 295 | } 296 | .ti-arrow-top-right:before { 297 | content: "\e65a"; 298 | } 299 | .ti-arrow-top-left:before { 300 | content: "\e65b"; 301 | } 302 | .ti-arrow-circle-up:before { 303 | content: "\e65c"; 304 | } 305 | .ti-arrow-circle-right:before { 306 | content: "\e65d"; 307 | } 308 | .ti-arrow-circle-left:before { 309 | content: "\e65e"; 310 | } 311 | .ti-arrow-circle-down:before { 312 | content: "\e65f"; 313 | } 314 | .ti-angle-double-up:before { 315 | content: "\e660"; 316 | } 317 | .ti-angle-double-right:before { 318 | content: "\e661"; 319 | } 320 | .ti-angle-double-left:before { 321 | content: "\e662"; 322 | } 323 | .ti-angle-double-down:before { 324 | content: "\e663"; 325 | } 326 | .ti-zip:before { 327 | content: "\e664"; 328 | } 329 | .ti-world:before { 330 | content: "\e665"; 331 | } 332 | .ti-wheelchair:before { 333 | content: "\e666"; 334 | } 335 | .ti-view-list:before { 336 | content: "\e667"; 337 | } 338 | .ti-view-list-alt:before { 339 | content: "\e668"; 340 | } 341 | .ti-view-grid:before { 342 | content: "\e669"; 343 | } 344 | .ti-uppercase:before { 345 | content: "\e66a"; 346 | } 347 | .ti-upload:before { 348 | content: "\e66b"; 349 | } 350 | .ti-underline:before { 351 | content: "\e66c"; 352 | } 353 | .ti-truck:before { 354 | content: "\e66d"; 355 | } 356 | .ti-timer:before { 357 | content: "\e66e"; 358 | } 359 | .ti-ticket:before { 360 | content: "\e66f"; 361 | } 362 | .ti-thumb-up:before { 363 | content: "\e670"; 364 | } 365 | .ti-thumb-down:before { 366 | content: "\e671"; 367 | } 368 | .ti-text:before { 369 | content: "\e672"; 370 | } 371 | .ti-stats-up:before { 372 | content: "\e673"; 373 | } 374 | .ti-stats-down:before { 375 | content: "\e674"; 376 | } 377 | .ti-split-v:before { 378 | content: "\e675"; 379 | } 380 | .ti-split-h:before { 381 | content: "\e676"; 382 | } 383 | .ti-smallcap:before { 384 | content: "\e677"; 385 | } 386 | .ti-shine:before { 387 | content: "\e678"; 388 | } 389 | .ti-shift-right:before { 390 | content: "\e679"; 391 | } 392 | .ti-shift-left:before { 393 | content: "\e67a"; 394 | } 395 | .ti-shield:before { 396 | content: "\e67b"; 397 | } 398 | .ti-notepad:before { 399 | content: "\e67c"; 400 | } 401 | .ti-server:before { 402 | content: "\e67d"; 403 | } 404 | .ti-quote-right:before { 405 | content: "\e67e"; 406 | } 407 | .ti-quote-left:before { 408 | content: "\e67f"; 409 | } 410 | .ti-pulse:before { 411 | content: "\e680"; 412 | } 413 | .ti-printer:before { 414 | content: "\e681"; 415 | } 416 | .ti-power-off:before { 417 | content: "\e682"; 418 | } 419 | .ti-plug:before { 420 | content: "\e683"; 421 | } 422 | .ti-pie-chart:before { 423 | content: "\e684"; 424 | } 425 | .ti-paragraph:before { 426 | content: "\e685"; 427 | } 428 | .ti-panel:before { 429 | content: "\e686"; 430 | } 431 | .ti-package:before { 432 | content: "\e687"; 433 | } 434 | .ti-music:before { 435 | content: "\e688"; 436 | } 437 | .ti-music-alt:before { 438 | content: "\e689"; 439 | } 440 | .ti-mouse:before { 441 | content: "\e68a"; 442 | } 443 | .ti-mouse-alt:before { 444 | content: "\e68b"; 445 | } 446 | .ti-money:before { 447 | content: "\e68c"; 448 | } 449 | .ti-microphone:before { 450 | content: "\e68d"; 451 | } 452 | .ti-menu:before { 453 | content: "\e68e"; 454 | } 455 | .ti-menu-alt:before { 456 | content: "\e68f"; 457 | } 458 | .ti-map:before { 459 | content: "\e690"; 460 | } 461 | .ti-map-alt:before { 462 | content: "\e691"; 463 | } 464 | .ti-loop:before { 465 | content: "\e692"; 466 | } 467 | .ti-location-pin:before { 468 | content: "\e693"; 469 | } 470 | .ti-list:before { 471 | content: "\e694"; 472 | } 473 | .ti-light-bulb:before { 474 | content: "\e695"; 475 | } 476 | .ti-Italic:before { 477 | content: "\e696"; 478 | } 479 | .ti-info:before { 480 | content: "\e697"; 481 | } 482 | .ti-infinite:before { 483 | content: "\e698"; 484 | } 485 | .ti-id-badge:before { 486 | content: "\e699"; 487 | } 488 | .ti-hummer:before { 489 | content: "\e69a"; 490 | } 491 | .ti-home:before { 492 | content: "\e69b"; 493 | } 494 | .ti-help:before { 495 | content: "\e69c"; 496 | } 497 | .ti-headphone:before { 498 | content: "\e69d"; 499 | } 500 | .ti-harddrives:before { 501 | content: "\e69e"; 502 | } 503 | .ti-harddrive:before { 504 | content: "\e69f"; 505 | } 506 | .ti-gift:before { 507 | content: "\e6a0"; 508 | } 509 | .ti-game:before { 510 | content: "\e6a1"; 511 | } 512 | .ti-filter:before { 513 | content: "\e6a2"; 514 | } 515 | .ti-files:before { 516 | content: "\e6a3"; 517 | } 518 | .ti-file:before { 519 | content: "\e6a4"; 520 | } 521 | .ti-eraser:before { 522 | content: "\e6a5"; 523 | } 524 | .ti-envelope:before { 525 | content: "\e6a6"; 526 | } 527 | .ti-download:before { 528 | content: "\e6a7"; 529 | } 530 | .ti-direction:before { 531 | content: "\e6a8"; 532 | } 533 | .ti-direction-alt:before { 534 | content: "\e6a9"; 535 | } 536 | .ti-dashboard:before { 537 | content: "\e6aa"; 538 | } 539 | .ti-control-stop:before { 540 | content: "\e6ab"; 541 | } 542 | .ti-control-shuffle:before { 543 | content: "\e6ac"; 544 | } 545 | .ti-control-play:before { 546 | content: "\e6ad"; 547 | } 548 | .ti-control-pause:before { 549 | content: "\e6ae"; 550 | } 551 | .ti-control-forward:before { 552 | content: "\e6af"; 553 | } 554 | .ti-control-backward:before { 555 | content: "\e6b0"; 556 | } 557 | .ti-cloud:before { 558 | content: "\e6b1"; 559 | } 560 | .ti-cloud-up:before { 561 | content: "\e6b2"; 562 | } 563 | .ti-cloud-down:before { 564 | content: "\e6b3"; 565 | } 566 | .ti-clipboard:before { 567 | content: "\e6b4"; 568 | } 569 | .ti-car:before { 570 | content: "\e6b5"; 571 | } 572 | .ti-calendar:before { 573 | content: "\e6b6"; 574 | } 575 | .ti-book:before { 576 | content: "\e6b7"; 577 | } 578 | .ti-bell:before { 579 | content: "\e6b8"; 580 | } 581 | .ti-basketball:before { 582 | content: "\e6b9"; 583 | } 584 | .ti-bar-chart:before { 585 | content: "\e6ba"; 586 | } 587 | .ti-bar-chart-alt:before { 588 | content: "\e6bb"; 589 | } 590 | .ti-back-right:before { 591 | content: "\e6bc"; 592 | } 593 | .ti-back-left:before { 594 | content: "\e6bd"; 595 | } 596 | .ti-arrows-corner:before { 597 | content: "\e6be"; 598 | } 599 | .ti-archive:before { 600 | content: "\e6bf"; 601 | } 602 | .ti-anchor:before { 603 | content: "\e6c0"; 604 | } 605 | .ti-align-right:before { 606 | content: "\e6c1"; 607 | } 608 | .ti-align-left:before { 609 | content: "\e6c2"; 610 | } 611 | .ti-align-justify:before { 612 | content: "\e6c3"; 613 | } 614 | .ti-align-center:before { 615 | content: "\e6c4"; 616 | } 617 | .ti-alert:before { 618 | content: "\e6c5"; 619 | } 620 | .ti-alarm-clock:before { 621 | content: "\e6c6"; 622 | } 623 | .ti-agenda:before { 624 | content: "\e6c7"; 625 | } 626 | .ti-write:before { 627 | content: "\e6c8"; 628 | } 629 | .ti-window:before { 630 | content: "\e6c9"; 631 | } 632 | .ti-widgetized:before { 633 | content: "\e6ca"; 634 | } 635 | .ti-widget:before { 636 | content: "\e6cb"; 637 | } 638 | .ti-widget-alt:before { 639 | content: "\e6cc"; 640 | } 641 | .ti-wallet:before { 642 | content: "\e6cd"; 643 | } 644 | .ti-video-clapper:before { 645 | content: "\e6ce"; 646 | } 647 | .ti-video-camera:before { 648 | content: "\e6cf"; 649 | } 650 | .ti-vector:before { 651 | content: "\e6d0"; 652 | } 653 | .ti-themify-logo:before { 654 | content: "\e6d1"; 655 | } 656 | .ti-themify-favicon:before { 657 | content: "\e6d2"; 658 | } 659 | .ti-themify-favicon-alt:before { 660 | content: "\e6d3"; 661 | } 662 | .ti-support:before { 663 | content: "\e6d4"; 664 | } 665 | .ti-stamp:before { 666 | content: "\e6d5"; 667 | } 668 | .ti-split-v-alt:before { 669 | content: "\e6d6"; 670 | } 671 | .ti-slice:before { 672 | content: "\e6d7"; 673 | } 674 | .ti-shortcode:before { 675 | content: "\e6d8"; 676 | } 677 | .ti-shift-right-alt:before { 678 | content: "\e6d9"; 679 | } 680 | .ti-shift-left-alt:before { 681 | content: "\e6da"; 682 | } 683 | .ti-ruler-alt-2:before { 684 | content: "\e6db"; 685 | } 686 | .ti-receipt:before { 687 | content: "\e6dc"; 688 | } 689 | .ti-pin2:before { 690 | content: "\e6dd"; 691 | } 692 | .ti-pin-alt:before { 693 | content: "\e6de"; 694 | } 695 | .ti-pencil-alt2:before { 696 | content: "\e6df"; 697 | } 698 | .ti-palette:before { 699 | content: "\e6e0"; 700 | } 701 | .ti-more:before { 702 | content: "\e6e1"; 703 | } 704 | .ti-more-alt:before { 705 | content: "\e6e2"; 706 | } 707 | .ti-microphone-alt:before { 708 | content: "\e6e3"; 709 | } 710 | .ti-magnet:before { 711 | content: "\e6e4"; 712 | } 713 | .ti-line-double:before { 714 | content: "\e6e5"; 715 | } 716 | .ti-line-dotted:before { 717 | content: "\e6e6"; 718 | } 719 | .ti-line-dashed:before { 720 | content: "\e6e7"; 721 | } 722 | .ti-layout-width-full:before { 723 | content: "\e6e8"; 724 | } 725 | .ti-layout-width-default:before { 726 | content: "\e6e9"; 727 | } 728 | .ti-layout-width-default-alt:before { 729 | content: "\e6ea"; 730 | } 731 | .ti-layout-tab:before { 732 | content: "\e6eb"; 733 | } 734 | .ti-layout-tab-window:before { 735 | content: "\e6ec"; 736 | } 737 | .ti-layout-tab-v:before { 738 | content: "\e6ed"; 739 | } 740 | .ti-layout-tab-min:before { 741 | content: "\e6ee"; 742 | } 743 | .ti-layout-slider:before { 744 | content: "\e6ef"; 745 | } 746 | .ti-layout-slider-alt:before { 747 | content: "\e6f0"; 748 | } 749 | .ti-layout-sidebar-right:before { 750 | content: "\e6f1"; 751 | } 752 | .ti-layout-sidebar-none:before { 753 | content: "\e6f2"; 754 | } 755 | .ti-layout-sidebar-left:before { 756 | content: "\e6f3"; 757 | } 758 | .ti-layout-placeholder:before { 759 | content: "\e6f4"; 760 | } 761 | .ti-layout-menu:before { 762 | content: "\e6f5"; 763 | } 764 | .ti-layout-menu-v:before { 765 | content: "\e6f6"; 766 | } 767 | .ti-layout-menu-separated:before { 768 | content: "\e6f7"; 769 | } 770 | .ti-layout-menu-full:before { 771 | content: "\e6f8"; 772 | } 773 | .ti-layout-media-right-alt:before { 774 | content: "\e6f9"; 775 | } 776 | .ti-layout-media-right:before { 777 | content: "\e6fa"; 778 | } 779 | .ti-layout-media-overlay:before { 780 | content: "\e6fb"; 781 | } 782 | .ti-layout-media-overlay-alt:before { 783 | content: "\e6fc"; 784 | } 785 | .ti-layout-media-overlay-alt-2:before { 786 | content: "\e6fd"; 787 | } 788 | .ti-layout-media-left-alt:before { 789 | content: "\e6fe"; 790 | } 791 | .ti-layout-media-left:before { 792 | content: "\e6ff"; 793 | } 794 | .ti-layout-media-center-alt:before { 795 | content: "\e700"; 796 | } 797 | .ti-layout-media-center:before { 798 | content: "\e701"; 799 | } 800 | .ti-layout-list-thumb:before { 801 | content: "\e702"; 802 | } 803 | .ti-layout-list-thumb-alt:before { 804 | content: "\e703"; 805 | } 806 | .ti-layout-list-post:before { 807 | content: "\e704"; 808 | } 809 | .ti-layout-list-large-image:before { 810 | content: "\e705"; 811 | } 812 | .ti-layout-line-solid:before { 813 | content: "\e706"; 814 | } 815 | .ti-layout-grid4:before { 816 | content: "\e707"; 817 | } 818 | .ti-layout-grid3:before { 819 | content: "\e708"; 820 | } 821 | .ti-layout-grid2:before { 822 | content: "\e709"; 823 | } 824 | .ti-layout-grid2-thumb:before { 825 | content: "\e70a"; 826 | } 827 | .ti-layout-cta-right:before { 828 | content: "\e70b"; 829 | } 830 | .ti-layout-cta-left:before { 831 | content: "\e70c"; 832 | } 833 | .ti-layout-cta-center:before { 834 | content: "\e70d"; 835 | } 836 | .ti-layout-cta-btn-right:before { 837 | content: "\e70e"; 838 | } 839 | .ti-layout-cta-btn-left:before { 840 | content: "\e70f"; 841 | } 842 | .ti-layout-column4:before { 843 | content: "\e710"; 844 | } 845 | .ti-layout-column3:before { 846 | content: "\e711"; 847 | } 848 | .ti-layout-column2:before { 849 | content: "\e712"; 850 | } 851 | .ti-layout-accordion-separated:before { 852 | content: "\e713"; 853 | } 854 | .ti-layout-accordion-merged:before { 855 | content: "\e714"; 856 | } 857 | .ti-layout-accordion-list:before { 858 | content: "\e715"; 859 | } 860 | .ti-ink-pen:before { 861 | content: "\e716"; 862 | } 863 | .ti-info-alt:before { 864 | content: "\e717"; 865 | } 866 | .ti-help-alt:before { 867 | content: "\e718"; 868 | } 869 | .ti-headphone-alt:before { 870 | content: "\e719"; 871 | } 872 | .ti-hand-point-up:before { 873 | content: "\e71a"; 874 | } 875 | .ti-hand-point-right:before { 876 | content: "\e71b"; 877 | } 878 | .ti-hand-point-left:before { 879 | content: "\e71c"; 880 | } 881 | .ti-hand-point-down:before { 882 | content: "\e71d"; 883 | } 884 | .ti-gallery:before { 885 | content: "\e71e"; 886 | } 887 | .ti-face-smile:before { 888 | content: "\e71f"; 889 | } 890 | .ti-face-sad:before { 891 | content: "\e720"; 892 | } 893 | .ti-credit-card:before { 894 | content: "\e721"; 895 | } 896 | .ti-control-skip-forward:before { 897 | content: "\e722"; 898 | } 899 | .ti-control-skip-backward:before { 900 | content: "\e723"; 901 | } 902 | .ti-control-record:before { 903 | content: "\e724"; 904 | } 905 | .ti-control-eject:before { 906 | content: "\e725"; 907 | } 908 | .ti-comments-smiley:before { 909 | content: "\e726"; 910 | } 911 | .ti-brush-alt:before { 912 | content: "\e727"; 913 | } 914 | .ti-youtube:before { 915 | content: "\e728"; 916 | } 917 | .ti-vimeo:before { 918 | content: "\e729"; 919 | } 920 | .ti-twitter:before { 921 | content: "\e72a"; 922 | } 923 | .ti-time:before { 924 | content: "\e72b"; 925 | } 926 | .ti-tumblr:before { 927 | content: "\e72c"; 928 | } 929 | .ti-skype:before { 930 | content: "\e72d"; 931 | } 932 | .ti-share:before { 933 | content: "\e72e"; 934 | } 935 | .ti-share-alt:before { 936 | content: "\e72f"; 937 | } 938 | .ti-rocket:before { 939 | content: "\e730"; 940 | } 941 | .ti-pinterest:before { 942 | content: "\e731"; 943 | } 944 | .ti-new-window:before { 945 | content: "\e732"; 946 | } 947 | .ti-microsoft:before { 948 | content: "\e733"; 949 | } 950 | .ti-list-ol:before { 951 | content: "\e734"; 952 | } 953 | .ti-linkedin:before { 954 | content: "\e735"; 955 | } 956 | .ti-layout-sidebar-2:before { 957 | content: "\e736"; 958 | } 959 | .ti-layout-grid4-alt:before { 960 | content: "\e737"; 961 | } 962 | .ti-layout-grid3-alt:before { 963 | content: "\e738"; 964 | } 965 | .ti-layout-grid2-alt:before { 966 | content: "\e739"; 967 | } 968 | .ti-layout-column4-alt:before { 969 | content: "\e73a"; 970 | } 971 | .ti-layout-column3-alt:before { 972 | content: "\e73b"; 973 | } 974 | .ti-layout-column2-alt:before { 975 | content: "\e73c"; 976 | } 977 | .ti-instagram:before { 978 | content: "\e73d"; 979 | } 980 | .ti-google:before { 981 | content: "\e73e"; 982 | } 983 | .ti-github:before { 984 | content: "\e73f"; 985 | } 986 | .ti-flickr:before { 987 | content: "\e740"; 988 | } 989 | .ti-facebook:before { 990 | content: "\e741"; 991 | } 992 | .ti-dropbox:before { 993 | content: "\e742"; 994 | } 995 | .ti-dribbble:before { 996 | content: "\e743"; 997 | } 998 | .ti-apple:before { 999 | content: "\e744"; 1000 | } 1001 | .ti-android:before { 1002 | content: "\e745"; 1003 | } 1004 | .ti-save:before { 1005 | content: "\e746"; 1006 | } 1007 | .ti-save-alt:before { 1008 | content: "\e747"; 1009 | } 1010 | .ti-yahoo:before { 1011 | content: "\e748"; 1012 | } 1013 | .ti-wordpress:before { 1014 | content: "\e749"; 1015 | } 1016 | .ti-vimeo-alt:before { 1017 | content: "\e74a"; 1018 | } 1019 | .ti-twitter-alt:before { 1020 | content: "\e74b"; 1021 | } 1022 | .ti-tumblr-alt:before { 1023 | content: "\e74c"; 1024 | } 1025 | .ti-trello:before { 1026 | content: "\e74d"; 1027 | } 1028 | .ti-stack-overflow:before { 1029 | content: "\e74e"; 1030 | } 1031 | .ti-soundcloud:before { 1032 | content: "\e74f"; 1033 | } 1034 | .ti-sharethis:before { 1035 | content: "\e750"; 1036 | } 1037 | .ti-sharethis-alt:before { 1038 | content: "\e751"; 1039 | } 1040 | .ti-reddit:before { 1041 | content: "\e752"; 1042 | } 1043 | .ti-pinterest-alt:before { 1044 | content: "\e753"; 1045 | } 1046 | .ti-microsoft-alt:before { 1047 | content: "\e754"; 1048 | } 1049 | .ti-linux:before { 1050 | content: "\e755"; 1051 | } 1052 | .ti-jsfiddle:before { 1053 | content: "\e756"; 1054 | } 1055 | .ti-joomla:before { 1056 | content: "\e757"; 1057 | } 1058 | .ti-html5:before { 1059 | content: "\e758"; 1060 | } 1061 | .ti-flickr-alt:before { 1062 | content: "\e759"; 1063 | } 1064 | .ti-email:before { 1065 | content: "\e75a"; 1066 | } 1067 | .ti-drupal:before { 1068 | content: "\e75b"; 1069 | } 1070 | .ti-dropbox-alt:before { 1071 | content: "\e75c"; 1072 | } 1073 | .ti-css3:before { 1074 | content: "\e75d"; 1075 | } 1076 | .ti-rss:before { 1077 | content: "\e75e"; 1078 | } 1079 | .ti-rss-alt:before { 1080 | content: "\e75f"; 1081 | } 1082 | -------------------------------------------------------------------------------- /static/vlcss.css: -------------------------------------------------------------------------------- 1 | #__next > div > div > div > div:nth-child(2) > div:nth-child(2) > img 2 | { 3 | position: relative; 4 | margin: auto; 5 | top: 10; 6 | } 7 | #__next > div > div > div > div:nth-child(2) > div.sixteen.wide.column > div.column 8 | { 9 | position: relative; 10 | margin: auto; 11 | height: 70vh; 12 | width: 85%; 13 | padding-left: 15%; 14 | padding-top: 150px; 15 | } --------------------------------------------------------------------------------