├── .gitignore
├── LICENSE
├── OCN.pdf
├── README.md
├── package-lock.json
├── package.json
├── public
├── favicon.ico
├── img
│ └── logo.svg
├── index.html
└── manifest.json
└── src
├── App.css
├── App.js
├── App.test.js
├── Components
├── HeaderComponents
│ ├── header.css
│ ├── header.js
│ └── logo.svg
└── Pages
│ ├── Accounts
│ ├── accounts.css
│ └── accounts.js
│ ├── Register
│ ├── register.css
│ └── register.js
│ └── View
│ ├── view.css
│ └── view.js
├── OpenComplainNetwork.json
├── img
└── logo.svg
├── index.css
├── index.js
├── registerServiceWorker.js
└── truffle-contract
├── contracts
├── Migrations.sol
└── OpenComplainNetwork.sol
├── migrations
├── 1_initial_migration.js
└── 2_deploy_contracts.js
├── package-lock.json
├── truffle-config.js
└── truffle.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Abhishek Upperwal
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 |
--------------------------------------------------------------------------------
/OCN.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upperwal/OpenComplaintNetwork/1fd7317b3948fa710fdbd6f2936b82ae761ceb4a/OCN.pdf
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Open Complain Network (OCN)
2 |
3 |
4 | [](https://youtu.be/Rw6KoLND9tc)
5 |
6 |
7 | Platform used:
8 | 1. Nodejs
9 | 2. Truffle for development
10 |
11 | How to Run:
12 | 1. Starting Truffle Develop
13 | - cd src/truffle-contract
14 | - truffle develop
15 | - compile
16 | - migrate
17 |
18 | 2. Starting lite server : in project root
19 | - npm start
20 |
21 | ### Introduction
22 |
23 | The Open Complaint Network is a decentralized system for lodging complaints, both civil and criminal onto a network that uses block chain, engaging citizens and police personnel.
24 |
25 | In case of a compaint, the citizen ought to register the complaint online that will reach all police accounts and the citizen shall not have to worry about jurisdictional issues, and neither will the policemen. The network will also help solve problems that transcend jurisdictional territories faster and with easy communication. The network is devised such that the citizens hold accounts through which they can file complaints, each police station has an account across the country and the administrator holds access and control.
26 |
27 | The network allows for all complaints to be lodged, major or minor. A complaint automatically generates a registration, which the citizen can track over time and check the progress.
28 |
29 | The access to all citizens allows for peer-to-peer helping network to file complaints and help each other solve problems. For eg. If A looses her Voter ID Card, and B reads the complaint on the blockchain and finds the card near him. A may choose to offer a reward for the same which in case of successful finding and transfer f lost items, shall be transferred to B's account through the same network. This is an innovative way to engage the citizens in helping one another and also helps take the pressure off the police by de-centralizing the process and allowing for greater vigilantism among the people themselves. This in the long run, shall help people be more aware of their surroundings, help each other and participate better in their societies.
30 |
31 | [Block Diagram](https://github.com/upperwal/OpenComplainNetwork/blob/master/OCN.pdf)
32 |
33 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "network-ui",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "bootstrap": "^3.3.7",
7 | "jquery": "^3.2.1",
8 | "react": "^16.1.0",
9 | "react-dom": "^16.1.0",
10 | "react-router-dom": "^4.2.2",
11 | "react-scripts": "1.0.17",
12 | "web3": "^1.2.9"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test --env=jsdom",
18 | "eject": "react-scripts eject"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upperwal/OpenComplaintNetwork/1fd7317b3948fa710fdbd6f2936b82ae761ceb4a/public/favicon.ico
--------------------------------------------------------------------------------
/public/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
26 |
27 |
28 |
29 | You need to enable JavaScript to run this app.
30 |
31 |
32 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/upperwal/OpenComplaintNetwork/1fd7317b3948fa710fdbd6f2936b82ae761ceb4a/src/App.css
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import {
3 | BrowserRouter as Router,
4 | Route,
5 | Link
6 | } from 'react-router-dom'
7 |
8 |
9 | import './App.css';
10 |
11 | import Header from './Components/HeaderComponents/header'
12 | import Register from './Components/Pages/Register/register'
13 | import View from './Components/Pages/View/view'
14 | import Accounts from './Components/Pages/Accounts/accounts'
15 |
16 | import Web3 from 'web3'
17 |
18 | import ContractsABIJSON from './truffle-contract/build/contracts/OpenComplainNetwork.json'
19 |
20 | console.log(ContractsABIJSON)
21 |
22 | window.abi = ContractsABIJSON.abi
23 | window.add = ContractsABIJSON.networks['5777'].address
24 |
25 | class App extends Component {
26 |
27 | constructor(props) {
28 | super(props)
29 | this.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:9545"));
30 | window._web3 = this.web3;
31 |
32 | this.complainContract = new this.web3.eth.Contract(window.abi, window.add, {
33 | from: '0x627306090abab3a6e1400e9345bc60c78a8bef57',
34 | gasPrice: '20000000000',
35 | gas: 2000000
36 | })
37 |
38 | console.log(JSON)
39 |
40 | window._contact = this.complainContract
41 | }
42 |
43 | render() {
44 | return (
45 |
46 |
47 |
48 |
49 |
( )} />
50 | ( )} />
51 |
52 | ( )} />
53 |
54 |
55 |
56 | );
57 | }
58 | }
59 |
60 | export default App;
61 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render( , div);
8 | });
9 |
--------------------------------------------------------------------------------
/src/Components/HeaderComponents/header.css:
--------------------------------------------------------------------------------
1 | .App {
2 |
3 | }
4 |
5 | .App-header {
6 | background-color: #2b2b2b;
7 | color: white;
8 | padding: 6px 40px;
9 | width: 100%;
10 | }
11 |
12 | .small-header {
13 | width: 90%;
14 | margin: auto;
15 | }
16 |
17 | .small-header > h1 {
18 | display: inline;
19 | margin-left: 30px;
20 | }
21 |
22 | .small-header > .links {
23 | margin-left: 90px;
24 | display: inline-block;
25 | }
26 |
27 | .small-header > .links > a {
28 | color: white;
29 | background-color: #444;
30 | padding: 20px 80px;
31 | margin: 0px 10px;
32 | border-radius: 8px;
33 | font-size: 1.3em;
34 | }
35 |
36 | .small-header > .links > a:hover {
37 | background-color: #333;
38 | }
39 |
40 | .App-title {
41 | font-size: 2.3em;
42 | }
43 |
44 | .App-intro {
45 | font-size: large;
46 | }
47 |
48 | @keyframes App-logo-spin {
49 | from { transform: rotate(0deg); }
50 | to { transform: rotate(360deg); }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Components/HeaderComponents/header.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import {
3 | Link
4 | } from 'react-router-dom'
5 |
6 | import './header.css'
7 |
8 | import logo from './logo.svg';
9 | import logo2 from '../../img/logo.svg'
10 |
11 | class Header extends Component {
12 | render() {
13 | return (
14 |
15 |
16 |
17 |
27 |
28 |
29 |
30 | );
31 | }
32 | }
33 |
34 | export default Header;
35 |
36 |
--------------------------------------------------------------------------------
/src/Components/HeaderComponents/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/Components/Pages/Accounts/accounts.css:
--------------------------------------------------------------------------------
1 | .accounts-class {
2 | text-align: left;
3 | width: 80%;
4 | margin: auto;
5 | margin-top: 40px;
6 | }
--------------------------------------------------------------------------------
/src/Components/Pages/Accounts/accounts.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import './accounts.css'
4 |
5 | class Accounts extends Component {
6 |
7 | constructor(props) {
8 | super(props)
9 | this.complainContract = props.contractObject
10 | this.web3 = props.web3Obj
11 |
12 | this.state = {
13 | table: ''
14 | }
15 |
16 | this.globalPromise = []
17 | this.accounts = []
18 | this.balances = []
19 | }
20 |
21 | componentWillMount() {
22 | this.getAllAccounts()
23 | console.log('Got Accounts')
24 | this.getBalances()
25 |
26 | }
27 | getAllAccounts() {
28 | var context = this
29 | this.web3.eth.getAccounts().then(function(res) {
30 | context.accounts = res
31 | console.log(context.accounts)
32 | })
33 | }
34 |
35 | getBalances() {
36 | console.log('Inside')
37 | console.log(this.accounts)
38 | var context = this
39 | new Promise(function(resolve, reject) {
40 | var pro = []
41 | for(var i = 0; i {resolve(e)}).catch((e) => {reject(e)})
51 | }).then(console.log)
52 | }
53 |
54 |
55 |
56 | render() {
57 | return(
58 |
59 |
60 |
61 |
All accounts currently in your wallet
62 |
63 |
64 |
65 | #
66 | Name
67 | Location
68 | Description
69 | Type
70 | Reward
71 | Status
72 | Action
73 |
74 |
75 |
76 | {this.state.table}
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | );
86 | }
87 |
88 | }
89 |
90 | export default Accounts
--------------------------------------------------------------------------------
/src/Components/Pages/Register/register.css:
--------------------------------------------------------------------------------
1 | #register-class {
2 | width: 70%;
3 | margin: auto;
4 | margin-top: 40px;
5 | }
6 |
7 | .notify {
8 | position: fixed;
9 | bottom: 10px;
10 | left: 10px;
11 | }
12 |
13 | #complain-submit {
14 | background-color: #f7f7f7;
15 | }
--------------------------------------------------------------------------------
/src/Components/Pages/Register/register.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import $ from 'jquery';
4 |
5 | import './register.css'
6 |
7 | class Register extends Component {
8 | constructor(props) {
9 | super(props)
10 | this.complainContract = props.contractObject
11 | this.web3 = props.web3Obj
12 | console.log('Class: Register')
13 | console.log(this.complainContract)
14 |
15 | this.formPreventDefault = this.formPreventDefault.bind(this);
16 | this.updateUser = this.updateUser.bind(this);
17 | this.register = this.register.bind(this);
18 |
19 | this.state = {
20 | notify: '',
21 | notiClass: 'success'
22 | }
23 |
24 | this.accounts = []
25 |
26 | this.getAccounts()
27 |
28 | this.selectUser = 0;
29 |
30 | }
31 |
32 | getAccounts() {
33 | var context = this
34 | this.web3.eth.getAccounts().then(function(res) {
35 | context.accounts = res
36 | console.log(context.accounts)
37 | })
38 | }
39 |
40 | formPreventDefault(e) {
41 | alert('here');
42 | e.preventDefault();
43 | }
44 |
45 | register(e) {
46 |
47 | var latdata = 0, longdata = 0
48 | function getLocation() {
49 | if (navigator.geolocation) {
50 | navigator.geolocation.getCurrentPosition(showPosition);
51 | } else {
52 | console.log("Geolocation is not supported by this browser.");
53 | }
54 | }
55 | function showPosition(position) {
56 | latdata = parseInt(position.coords.latitude * 1e12)
57 | longdata = parseInt(position.coords.longitude * 1e12)
58 | }
59 |
60 | getLocation()
61 |
62 |
63 | e.preventDefault();
64 |
65 | var data = []
66 | data.push($('#input-name').val().replace(new RegExp(',', 'g'), '#'))
67 | data.push($('#input-address').val().replace(new RegExp(',', 'g'), '#'))
68 | data.push($('#input-desc').val().replace(new RegExp(',', 'g'), '#'))
69 | console.log(data)
70 | data = data.toString().replace(new RegExp(',', 'g'), '?').replace(new RegExp('#', 'g'), ',');
71 | console.log(data)
72 |
73 | var catdata = $('#type').val()
74 |
75 | var reward = parseInt($('#input-reward').val()) * 1e9
76 |
77 | /*let objJsonStr = JSON.stringify(data);
78 | let objJsonB64 = new Buffer(objJsonStr).toString("base64");*/
79 |
80 | var part = btoa(data)
81 |
82 | var context = this
83 |
84 | this.complainContract.methods.registerComplain(part, longdata, latdata, catdata).send({from: this.accounts[this.selectUser], value: reward})
85 | .then(function(response) {
86 | context.complainContract.methods.registerComplain(part, longdata, latdata, catdata).call().then(function(cid) {
87 | console.log('CID: ' + cid)
88 | context.setState({notify: 'Complain Registered.', notiClass: 'success'})
89 | //$('#notify').html("Complain Registered with ID: " + cid)
90 | });
91 |
92 | console.log(response)
93 | console.log('End of Response')
94 | }).catch(function(err) {
95 | context.setState({notify: 'Error: Complain not Registered.', notiClass: 'danger'})
96 | console.log('Error: Message: ' + err.message);
97 | });
98 |
99 |
100 | }
101 |
102 | /*componentWillMount() {
103 |
104 |
105 |
106 |
107 | console.log(this.complainContract)
108 |
109 |
110 | }*/
111 |
112 |
113 |
114 | updateUser(e) {
115 | this.selectUser = e.target.value
116 |
117 | this.setState({gg: 'some'})
118 |
119 | /*if(this.selectUser == 0) {
120 |
121 | this.setState({secondBtn: 'invisible', isSuperUser: 'visible',isCitizen: 'invisible', classFirst: 'glyphicon glyphicon-plus', classSecond: 'hidden', tipFirst: 'Assign new Police accounts', tipSecond: 'Empty'}, function() {
122 | this.setState({table: this.renderTable()})
123 | })
124 | }
125 | else if(this.selectUser == 1) {
126 | this.setState({secondBtn: 'visible', isSuperUser: 'invisible',isCitizen: 'invisible', classFirst: 'glyphicon glyphicon-arrow-up', classSecond: 'glyphicon glyphicon-arrow-down', tipFirst: 'Upgrade complain status', tipSecond: 'Downgrade complain status'}, function() {
127 | this.setState({table: this.renderTable()})
128 | })
129 | }
130 | else if(this.selectUser == 2 || this.selectUser == 3) {
131 | this.setState({secondBtn: 'visible', isSuperUser: 'invisible',isCitizen: 'visible', classFirst: 'glyphicon glyphicon-flash', classSecond: 'glyphicon glyphicon-send', tipFirst: 'Fund a complain', tipSecond: 'Report a Solution'}, function() {
132 | this.setState({table: this.renderTable()})
133 | })
134 | }*/
135 |
136 |
137 | //console.log(this.state.classFirst)
138 | }
139 |
140 | render() {
141 | return (
142 |
143 |
Select a User to perform the following action.
144 |
145 | Super User
146 | Police
147 | Citizen 1
148 | Citizen 2
149 |
150 |
Account No: {this.accounts[this.selectUser]}
151 |
152 |
153 |
154 |
155 | To register a complain please fill the following form.
156 |
157 |
200 |
201 | );
202 | }
203 | }
204 |
205 | export default Register;
206 |
207 |
--------------------------------------------------------------------------------
/src/Components/Pages/View/view.css:
--------------------------------------------------------------------------------
1 | .view-class {
2 | text-align: left;
3 | width: 80%;
4 | margin: auto;
5 | margin-top: 40px;
6 | }
7 |
8 | .label {
9 | cursor: pointer;
10 | margin-bottom: 5px;
11 | }
12 |
13 | h5 {
14 | display: inline;
15 | margin-left: 6px;
16 | margin-right: 20px;
17 | }
18 |
19 | .notify {
20 | position: fixed;
21 | bottom: 10px;
22 | left: 10px;
23 | }
24 |
25 | .police-accounts {
26 | margin-top: 30px;
27 | }
28 | h3 {
29 | margin: 20px 0px;
30 | }
31 | .police-accounts input {
32 | margin: 20px 0px;
33 | }
34 | .police-accounts button {
35 | background-color: #f7f7f7;
36 | margin-bottom: 20px;
37 | }
38 | .police-accounts .label {
39 | font-size: 0.6em;
40 | }
41 | .label {
42 | margin: 0px 2px;
43 | }
44 | .invisible {
45 | display: none;
46 | }
47 | .visible {
48 | display: block-inherit;
49 | }
50 | .Accepted {
51 | text-align: center;
52 | border-radius: 6px;
53 | padding: 3px;
54 | color: #fff;
55 | background-color: #3337f7;
56 | }
57 | .Resolved {
58 | text-align: center;
59 | border-radius: 6px;
60 | padding: 3px;
61 | color: #fff;
62 | background-color: #139019;
63 | }
64 | .Pending {
65 | text-align: center;
66 | border-radius: 6px;
67 | padding: 3px;
68 | color: #fff;
69 | background-color: #a91343;
70 | }
71 |
72 | .Proposed {
73 | text-align: center;
74 | border-radius: 6px;
75 | padding: 3px;
76 | color: #fff;
77 | background-color: #cf2f10;
78 | }
--------------------------------------------------------------------------------
/src/Components/Pages/View/view.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import './view.css'
4 |
5 |
6 | import $ from 'jquery'
7 |
8 | class View extends Component {
9 |
10 | constructor(props) {
11 | super(props)
12 | this.complainContract = props.contractObject
13 | this.web3 = props.web3Obj
14 | console.log('Class: View')
15 |
16 | this.updateUser = this.updateUser.bind(this);
17 | this.renderTable = this.renderTable.bind(this);
18 |
19 | this.actionFirstButton = this.actionFirstButton.bind(this);
20 | this.actionSecondButton = this.actionSecondButton.bind(this);
21 | this.actionThirdButton = this.actionThirdButton.bind(this);
22 | this.actionFourthButton = this.actionFourthButton.bind(this);
23 | this.sendTransPolList = this.sendTransPolList.bind(this);
24 | this.updatePoliceList = this.updatePoliceList.bind(this);
25 | this.actionPolFund = this.actionPolFund.bind(this);
26 |
27 | this.state = {
28 | table: [],
29 | classFirst: 'glyphicon glyphicon-plus',
30 | classSecond: 'hidden',
31 | tipFirst: 'Assign new Police accounts',
32 | tipSecond: 'Empty',
33 | isSuperUser: 'visible',
34 | isCitizen: 'invisible',
35 | secondBtn: 'invisible',
36 | polFund: 'invisible',
37 | polTip: 'Fund this Complain',
38 | notification: '',
39 | notiClass: 'success',
40 | polAcc: []
41 | }
42 |
43 | this.fetchedComplains = []
44 | this.promiseEachComplain = []
45 | this.selectUser = 0
46 |
47 | this.accounts = []
48 | this.polList = ''
49 |
50 | this.getAccounts()
51 | }
52 |
53 | catType(a) {
54 | console.log('dfdsfsdf'+ a)
55 | if(a==0)
56 | return 'Lost'
57 | else if(a==1)
58 | return 'Theft'
59 | }
60 |
61 | statusType(a) {
62 | if(a == 0)
63 | return 'Pending'
64 | else if(a == 1)
65 | return 'Accepted'
66 | else if(a == 2)
67 | return 'Resolved'
68 | else if(a == 3)
69 | return 'Proposed'
70 | }
71 |
72 | actionFirstButton(e) {
73 | var complain = this.fetchedComplains[e.target.getAttribute('data-index')]
74 | var context = this;
75 |
76 | if(this.selectUser == 1) {
77 | console.log('Complain Status: '+complain.status)
78 | if(complain.status < 2) {
79 | this.complainContract.methods.changeStatus(complain.cid, parseInt(complain.status) + 1).send({from: this.accounts[this.selectUser]})
80 | .then(function(res) {
81 | console.log(res)
82 | context.setState({notification: 'Complain Status Changed.', notiClass: 'success'})
83 | context.componentWillMount()
84 | }).catch(function(res) {
85 | context.setState({notification: 'Error: This might not be added as a Police Account', notiClass: 'danger'})
86 | console.log(res)
87 | })
88 | }
89 | else {
90 | this.setState({notification: 'Complain Status cant go above "Resolved" or "Proposed"', notiClass: 'danger'})
91 | }
92 |
93 | }
94 | else if(this.selectUser == 2 || this.selectUser == 3) {
95 | console.log("Fund : "+complain.cid)
96 | if($('#input-reward').val() == '') {
97 | context.setState({notification: 'No Fund Specified. Please enter some amount.', notiClass: 'danger'})
98 | return
99 | }
100 | var fundValue = parseInt($('#input-reward').val()) * 1e9
101 | this.complainContract.methods.fundComplain(complain.cid).send({from: this.accounts[this.selectUser], value: fundValue})
102 | .then(function(res) {
103 | console.log(res)
104 | context.setState({notification: 'Complain Funded', notiClass: 'success'})
105 | context.componentWillMount()
106 | }).catch(() => {context.setState({notification: 'Error Occured: Complain should be Accepted or Proposed', notiClass: 'danger'})})
107 | }
108 | }
109 |
110 | actionSecondButton(e) {
111 | var complain = this.fetchedComplains[e.target.getAttribute('data-index')]
112 | var context = this;
113 | if(this.selectUser == 1) {
114 | if(complain.status > 0) {
115 | this.complainContract.methods.changeStatus(complain.cid, parseInt(complain.status) - 1).send({from: this.accounts[this.selectUser]})
116 | .then(function(res) {
117 | console.log(res)
118 | context.setState({notification: 'Status Changed', notiClass: 'success'})
119 | context.componentWillMount()
120 | }).catch(() => {context.setState({notification: 'Error Dec: This might not be added as a Police Account', notiClass: 'danger'})})
121 | }
122 | else {
123 | this.setState({notification: 'Complain Status cant go below "Pending"', notiClass: 'danger'})
124 | }
125 |
126 | }
127 | else if(this.selectUser == 2 || this.selectUser == 3) {
128 | this.complainContract.methods.claimSolution(complain.cid).send({from: this.accounts[this.selectUser]})
129 | .then(function(res) {
130 | console.log(res)
131 | context.setState({notification: 'Solution Claimed', notiClass: 'success'})
132 | context.componentWillMount()
133 | }).catch(() => {context.setState({notification: 'Error Occured: You cant propose on your complain or a solution is already proposed.', notiClass: 'danger'})})
134 | }
135 | }
136 |
137 | actionThirdButton(e) {
138 | var complain = this.fetchedComplains[e.target.getAttribute('data-index')]
139 | var context = this;
140 | this.complainContract.methods.resolve(complain.cid).send({from: this.accounts[this.selectUser]})
141 | .then(function(res) {
142 | console.log(res)
143 | context.setState({notification: 'Complain resolved and closed. Fund Transfered.', notiClass: 'success'})
144 | context.componentWillMount()
145 | }).catch(() => {context.setState({notification: 'Error Occured: This might not be your complain.', notiClass: 'danger'})})
146 | }
147 |
148 | actionFourthButton(e) {
149 | var complain = this.fetchedComplains[e.target.getAttribute('data-index')]
150 | var context = this;
151 | this.complainContract.methods.declineProposal(complain.cid).send({from: this.accounts[this.selectUser]})
152 | .then(function(res) {
153 | console.log(res)
154 | context.setState({notification: 'Complain Solution declined. Set to Accept Status.', notiClass: 'success'})
155 | context.componentWillMount()
156 | }).catch(() => {context.setState({notification: 'Error Occured: You might not be the owner of this complain.', notiClass: 'danger'})})
157 | }
158 |
159 | actionPolFund(e) {
160 | var complain = this.fetchedComplains[e.target.getAttribute('data-index')]
161 | var context = this;
162 |
163 | var fundValue = parseInt($('#input-reward').val()) * 1e9
164 |
165 | this.complainContract.methods.fundComplain(complain.cid).send({from: this.accounts[this.selectUser], value: fundValue})
166 | .then(function(res) {
167 | console.log(res)
168 | context.setState({notification: 'Complain Funded'})
169 | context.componentWillMount()
170 | }).catch(() => {context.setState({notification: 'Error Occured', notiClass: 'danger'})})
171 | }
172 |
173 | getAccounts() {
174 | var context = this
175 | this.web3.eth.getAccounts().then(function(res) {
176 | context.accounts = res
177 | console.log(context.accounts)
178 | })
179 | }
180 |
181 |
182 |
183 | componentWillMount() {
184 | this.fetchedComplains = []
185 | this.promiseEachComplain = []
186 | this.fetchFreshData()
187 |
188 | var context = this
189 |
190 | Promise.all(this.promiseEachComplain).then(function() {
191 | context.setState({table: context.renderTable()})
192 | })
193 |
194 | }
195 |
196 | fetchFreshData() {
197 | var noOfComplainsFetch = 20
198 |
199 | var context = this
200 |
201 | var majorPromise = new Promise(function(resolve, reject) {
202 | for(var i=0; i{fetchData.cid}
274 | var _td1 = {details[0]}
275 | var _td2 = {details[1]}
276 | var _td3 = {details[2]}
277 | var _td4 = {context.catType(fetchData.cat)}
278 | var _td5 = ₹ {(fetchData.reward/1e9).toFixed(2)}
279 | var _td6 = {context.statusType(fetchData.status)}
280 | var _td7 =
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 | //var t =
300 |
301 | //var u = React.cloneElement(t)
302 | //var _td = Hello
303 | var _tr = {_th}{_td1}{_td2}{_td3}{_td4}{_td5}{_td6}{_td7}
304 |
305 | reactTableRows.push(_tr)
306 |
307 |
308 | }
309 | var reactTBody = React.createElement('tbody', {'id': 'table-body'}, reactTableRows)
310 |
311 | console.log(reactTBody)
312 | return reactTBody
313 | //context.setState({table: pp})
314 | //p.push(_tr)
315 | }
316 |
317 | updatePoliceList(e) {
318 | this.polList = e.target.value;
319 | console.log(this.polList)
320 | }
321 |
322 | sendTransPolList() {
323 | var accList = this.polList.split(',')
324 | console.log(accList)
325 | var context = this;
326 | this.complainContract.methods.modifyPoliceAccounts(accList).send({from: this.accounts[this.selectUser]})
327 | .then(function(res) {
328 | console.log(res)
329 | context.setState({notification: 'Police Acoounts Modified', notiClass: 'success'})
330 | //context.checkPolAccount()
331 |
332 |
333 | }).catch(() => {context.setState({notification: 'Error Occured while modifying Police Accounts', notiClass: 'danger'})})
334 | }
335 |
336 | checkPolAccount() {
337 | var context = this
338 | var yy = []
339 | var dep = []
340 | for(var i =0; i
364 |
365 | Super User
366 | Police
367 | Citizen 1
368 | Citizen 2
369 |
370 |
371 |
372 |
373 |
374 |
Complain fetched from Blockchain
375 |
376 |
377 |
378 | #
379 | Name
380 | Location
381 | Description
382 | Type
383 | Reward
384 | Status
385 | Action
386 |
387 |
388 |
389 | {this.state.table}
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
{this.state.tipFirst}
402 |
403 |
404 |
405 | {this.state.tipSecond}
406 |
407 |
408 |
409 |
410 | Close/Resolve Complain [Funds will be awarded or sent back]
411 |
412 |
413 |
414 | Decline Proposal
415 |
416 |
417 |
418 | {this.state.polTip}
419 |
420 |
421 |
422 |
423 |
424 |
425 |
Update Police Accounts
426 |
427 |
Submit
428 |
Police account is not added to the list by default. Complain status change will fail if not added.
429 |
430 |
431 |
432 |
Account Addresses
433 |
434 |
435 |
436 | SuperUser : {this.accounts[0]}
437 | Police : {this.accounts[1]}
438 | Citizen1 : {this.accounts[2]}
439 | Citizen2 : {this.accounts[3]}
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 | ×
452 | {this.state.notification}
453 |
454 |
455 | );
456 | }
457 |
458 |
459 | }
460 |
461 | export default View;
462 |
463 |
--------------------------------------------------------------------------------
/src/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | padding-bottom: 20px;
6 | }
7 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
5 | import './index.css';
6 |
7 | import App from './App';
8 | import registerServiceWorker from './registerServiceWorker';
9 |
10 | ReactDOM.render( , document.getElementById('root'));
11 | registerServiceWorker();
12 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (isLocalhost) {
36 | // This is running on localhost. Lets check if a service worker still exists or not.
37 | checkValidServiceWorker(swUrl);
38 | } else {
39 | // Is not local host. Just register service worker
40 | registerValidSW(swUrl);
41 | }
42 | });
43 | }
44 | }
45 |
46 | function registerValidSW(swUrl) {
47 | navigator.serviceWorker
48 | .register(swUrl)
49 | .then(registration => {
50 | registration.onupdatefound = () => {
51 | const installingWorker = registration.installing;
52 | installingWorker.onstatechange = () => {
53 | if (installingWorker.state === 'installed') {
54 | if (navigator.serviceWorker.controller) {
55 | // At this point, the old content will have been purged and
56 | // the fresh content will have been added to the cache.
57 | // It's the perfect time to display a "New content is
58 | // available; please refresh." message in your web app.
59 | console.log('New content is available; please refresh.');
60 | } else {
61 | // At this point, everything has been precached.
62 | // It's the perfect time to display a
63 | // "Content is cached for offline use." message.
64 | console.log('Content is cached for offline use.');
65 | }
66 | }
67 | };
68 | };
69 | })
70 | .catch(error => {
71 | console.error('Error during service worker registration:', error);
72 | });
73 | }
74 |
75 | function checkValidServiceWorker(swUrl) {
76 | // Check if the service worker can be found. If it can't reload the page.
77 | fetch(swUrl)
78 | .then(response => {
79 | // Ensure service worker exists, and that we really are getting a JS file.
80 | if (
81 | response.status === 404 ||
82 | response.headers.get('content-type').indexOf('javascript') === -1
83 | ) {
84 | // No service worker found. Probably a different app. Reload the page.
85 | navigator.serviceWorker.ready.then(registration => {
86 | registration.unregister().then(() => {
87 | window.location.reload();
88 | });
89 | });
90 | } else {
91 | // Service worker found. Proceed as normal.
92 | registerValidSW(swUrl);
93 | }
94 | })
95 | .catch(() => {
96 | console.log(
97 | 'No internet connection found. App is running in offline mode.'
98 | );
99 | });
100 | }
101 |
102 | export function unregister() {
103 | if ('serviceWorker' in navigator) {
104 | navigator.serviceWorker.ready.then(registration => {
105 | registration.unregister();
106 | });
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/truffle-contract/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
2 |
3 | contract Migrations {
4 | address public owner;
5 | uint public last_completed_migration;
6 |
7 | modifier restricted() {
8 | if (msg.sender == owner) _;
9 | }
10 |
11 | function Migrations() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/truffle-contract/contracts/OpenComplainNetwork.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
2 |
3 | contract OpenComplainNetwork {
4 | enum Status { Pending, Accepted, Resolved, Proposed }
5 |
6 | struct Complain {
7 | /*bytes[50] _name;
8 | bytes[50] _address;
9 | bytes[50] _desc;
10 | bytes[50] _location;
11 | bytes[50] _category;*/
12 | uint _lat;
13 | uint _long;
14 | uint _category;
15 | string _data;
16 | address _personID;
17 | Status _status;
18 | uint _reward;
19 | address _policeAssigned;
20 | address[] _contributors;
21 | uint[] _contAmount;
22 | }
23 |
24 | uint private complainCounter;
25 | mapping(uint => Complain) private complainMap;
26 | mapping(address => bool) private policeAccounts;
27 | address private superuser;
28 | mapping(uint => address) private complainSolver;
29 |
30 | function OpenComplainNetwork() public {
31 | superuser = msg.sender;
32 | complainCounter = 0;
33 | }
34 |
35 | modifier superuserAccess() {
36 | require(msg.sender == superuser);
37 | _;
38 | }
39 |
40 | modifier policeAccess {
41 | require(policeAccounts[msg.sender] == true);
42 | _;
43 | }
44 |
45 | modifier complainOwnerAccess(uint cid) {
46 | require(msg.sender == complainMap[cid]._personID);
47 | _;
48 | }
49 |
50 | modifier complainOwnOrPoliceAccess(uint cid) {
51 | require(policeAccounts[msg.sender] == true || msg.sender == complainMap[cid]._personID);
52 | _;
53 | }
54 |
55 | function registerComplain(string data, uint long, uint lat, uint cat) public payable returns(uint) {
56 | complainMap[complainCounter]._long = long;
57 | complainMap[complainCounter]._lat = lat;
58 | complainMap[complainCounter]._category = cat;
59 | complainMap[complainCounter]._data = data;
60 | complainMap[complainCounter]._personID = msg.sender;
61 | complainMap[complainCounter]._status = Status.Pending;
62 | complainMap[complainCounter]._reward = msg.value;
63 |
64 | if(msg.value > 0) {
65 | complainMap[complainCounter]._contributors.push(msg.sender);
66 | complainMap[complainCounter]._contAmount.push(msg.value);
67 | }
68 | /*for(uint i=0; i= Status.Pending));
82 | complainMap[cid]._status = sta;
83 |
84 | // What if a person solves the problem and then the police
85 | // updates the status to resolved. complainSolver[cid] = 'Police'
86 | // no funds to the Original Solver.
87 | if(sta == Status.Resolved) {
88 | complainSolver[cid] = msg.sender;
89 | }
90 | }
91 |
92 | // Even though Police can resolve and close the complain.
93 | // Complainee would be responsible for transfering the funds, if any.
94 | function resolve(uint cid) public complainOwnerAccess(cid) {
95 | complainMap[cid]._status = Status.Resolved;
96 |
97 | transferFundOnResolve(cid);
98 | }
99 |
100 | function declineProposal(uint cid) public complainOwnerAccess(cid) {
101 | require( complainMap[cid]._status == Status.Proposed );
102 | complainMap[cid]._status = Status.Accepted;
103 |
104 | complainSolver[cid] = 0;
105 | }
106 |
107 | // If someone other than police solved the complain transfer funds to solver.
108 | // Otherwise send them back to the contributors.
109 | function transferFundOnResolve(uint cid) private {
110 | // Could also be used: complainMap[cid]._status == Status.Resolved &&
111 | if(complainMap[cid]._reward > 0) {
112 | if(policeAccounts[complainSolver[cid]] != true) {
113 | complainSolver[cid].transfer( complainMap[cid]._reward );
114 | complainMap[cid]._reward = 0;
115 | }
116 | else {
117 | for(uint i=0; i
3 | // to customize your Truffle configuration!
4 | compilers: {
5 | solc: {
6 | version: "0.4.17"
7 | }
8 | }
9 | };
10 |
--------------------------------------------------------------------------------
/src/truffle-contract/truffle.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // See
3 | networks: {
4 | development: {
5 | host: "localhost",
6 | port: 8545,
7 | network_id: "*" // Match any network id
8 | }
9 | }
10 | };
11 |
--------------------------------------------------------------------------------