mirror of https://gitlab.com/ecentrics/concordia
				
				
			
				 35 changed files with 346 additions and 787 deletions
			
			
		@ -1,15 +0,0 @@ | 
				
			|||||
{ | 
					 | 
				
			||||
  "short_name": "Apella", | 
					 | 
				
			||||
  "name": "Apella", | 
					 | 
				
			||||
  "icons": [ | 
					 | 
				
			||||
    { | 
					 | 
				
			||||
      "src": "favicon.ico", | 
					 | 
				
			||||
      "sizes": "64x64 32x32 24x24 16x16", | 
					 | 
				
			||||
      "type": "image/x-icon" | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  ], | 
					 | 
				
			||||
  "start_url": "./index.html", | 
					 | 
				
			||||
  "display": "standalone", | 
					 | 
				
			||||
  "theme_color": "#000000", | 
					 | 
				
			||||
  "background_color": "#ffffff" | 
					 | 
				
			||||
} | 
					 | 
				
			||||
@ -1,52 +1,19 @@ | 
				
			|||||
import React, { Component } from 'react' | 
					import React, { Component } from 'react' | 
				
			||||
import { Link } from 'react-router' | 
					 | 
				
			||||
import { HiddenOnlyAuth, VisibleOnlyAuth } from './util/wrappers.js' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
// UI Components
 | 
					 | 
				
			||||
import LoginButtonContainer from './user/ui/loginbutton/LoginButtonContainer' | 
					 | 
				
			||||
 | 
					
 | 
				
			||||
// Styles
 | 
					// Styles
 | 
				
			||||
import './css/oswald.css' | 
					import './css/oswald.css' | 
				
			||||
import './css/open-sans.css' | 
					import './css/open-sans.css' | 
				
			||||
import './css/pure-min.css' | 
					import './css/pure-min.css' | 
				
			||||
import './App.css' | 
					import './css/App.css' | 
				
			||||
 | 
					
 | 
				
			||||
class App extends Component { | 
					class App extends Component { | 
				
			||||
    render() { | 
					  render() { | 
				
			||||
        const OnlyAuthLinks = VisibleOnlyAuth(() => | 
					    return ( | 
				
			||||
                <span> | 
					      <div className="App"> | 
				
			||||
        <li className="pure-menu-item"> | 
					        {this.props.children} | 
				
			||||
          <Link to="/dashboard" className="pure-menu-link">Dashboard</Link> | 
					      </div> | 
				
			||||
        </li> | 
					    ); | 
				
			||||
        <li className="pure-menu-item"> | 
					  } | 
				
			||||
          <Link to="/profile" className="pure-menu-link">Profile</Link> | 
					 | 
				
			||||
        </li> | 
					 | 
				
			||||
      </span> | 
					 | 
				
			||||
        ); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        const OnlyGuestLinks = HiddenOnlyAuth(() => | 
					 | 
				
			||||
                <span> | 
					 | 
				
			||||
        <li className="pure-menu-item"> | 
					 | 
				
			||||
          <Link to="/signup" className="pure-menu-link">Sign Up</Link> | 
					 | 
				
			||||
        </li> | 
					 | 
				
			||||
        <LoginButtonContainer /> | 
					 | 
				
			||||
      </span> | 
					 | 
				
			||||
        ); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        return ( | 
					 | 
				
			||||
            <div className="App"> | 
					 | 
				
			||||
                <nav className="navbar pure-menu pure-menu-horizontal"> | 
					 | 
				
			||||
                    <ul className="pure-menu-list navbar-right"> | 
					 | 
				
			||||
                        <OnlyGuestLinks /> | 
					 | 
				
			||||
                        <OnlyAuthLinks /> | 
					 | 
				
			||||
                    </ul> | 
					 | 
				
			||||
                    <Link to="/" className="pure-menu-heading pure-menu-link">Apella</Link> | 
					 | 
				
			||||
                </nav> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                {this.props.children} | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        ); | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
} | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
export default App | 
					export default App | 
				
			||||
 | 
				
			|||||
@ -0,0 +1,48 @@ | 
				
			|||||
 | 
					import { drizzleConnect } from 'drizzle-react' | 
				
			||||
 | 
					import React, { Component } from 'react' | 
				
			||||
 | 
					import PropTypes from 'prop-types' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const contract = "Forum"; | 
				
			||||
 | 
					const method = "hasUserSignedUp"; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class AuthWrapperContainer extends Component { | 
				
			||||
 | 
					    constructor(props, context) { | 
				
			||||
 | 
					        super(props); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        this.contracts = context.drizzle.contracts; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        this.dataKey = this.contracts[contract].methods[method].cacheCall(...[this.props.accounts[0]]); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    render() { | 
				
			||||
 | 
					        // Contract is not yet intialized.
 | 
				
			||||
 | 
					        if(!this.props.contracts[contract].initialized) | 
				
			||||
 | 
					            return (null); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        // If the cache key we received earlier isn't in the store yet; the initial value is still being fetched.
 | 
				
			||||
 | 
					        if(!(this.dataKey in this.props.contracts[contract][method])) | 
				
			||||
 | 
					            return (null); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        let userHasSignedUp = this.props.contracts[contract][method][this.dataKey].value; | 
				
			||||
 | 
					        const authRender = this.props.authRender; | 
				
			||||
 | 
					        const guestRender = this.props.guestRender; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        if (userHasSignedUp) | 
				
			||||
 | 
					            return(<div>{authRender}</div>); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        return(<div>{guestRender}</div>); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					AuthWrapperContainer.contextTypes = { | 
				
			||||
 | 
					    drizzle: PropTypes.object | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const mapStateToProps = state => { | 
				
			||||
 | 
					    return { | 
				
			||||
 | 
					        accounts: state.accounts, | 
				
			||||
 | 
					        contracts: state.contracts, | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					export default drizzleConnect(AuthWrapperContainer, mapStateToProps) | 
				
			||||
@ -0,0 +1,103 @@ | 
				
			|||||
 | 
					import { drizzleConnect } from 'drizzle-react' | 
				
			||||
 | 
					import React, { Component } from 'react' | 
				
			||||
 | 
					import PropTypes from 'prop-types' | 
				
			||||
 | 
					import AuthWrapperContainer from './AuthWrapperContainer' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const contract = "Forum"; | 
				
			||||
 | 
					const signUpMethod = "signUp"; | 
				
			||||
 | 
					const updateUsernameMethod ="updateUsername"; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class UsernameFormContainer extends Component { | 
				
			||||
 | 
					    constructor(props, context) { | 
				
			||||
 | 
					        super(props); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        this.handleSignUp = this.handleSignUp.bind(this); | 
				
			||||
 | 
					        this.handleSignUpInputChange = this.handleSignUpInputChange.bind(this); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        this.handleUsernameUpdate = this.handleUsernameUpdate.bind(this); | 
				
			||||
 | 
					        this.handleUpdateUsernameInputChange = this.handleUpdateUsernameInputChange.bind(this); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        this.contracts = context.drizzle.contracts; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        // Get the contract ABI
 | 
				
			||||
 | 
					        const abi = this.contracts[contract].abi; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        this.inputs = {signUp:[], updateUsername:[]}; | 
				
			||||
 | 
					        let initialState = {signUp:{}, updateUsername:{}}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        // Iterate over abi for correct function.
 | 
				
			||||
 | 
					        for (let i = 0; i < abi.length; i++) { | 
				
			||||
 | 
					            if ((abi[i].name === signUpMethod)) { | 
				
			||||
 | 
					                this.inputs.signUp = abi[i].inputs; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                for (let i = 0; i < this.inputs.signUp.length; i++) { | 
				
			||||
 | 
					                    initialState.signUp[this.inputs.signUp[i].name] = ''; | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            else if ((abi[i].name === updateUsernameMethod)) { | 
				
			||||
 | 
					                this.inputs.updateUsername = abi[i].inputs; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                for (let i = 0; i < this.inputs.updateUsername.length; i++) { | 
				
			||||
 | 
					                    initialState.updateUsername[this.inputs.updateUsername[i].name] = ''; | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					        console.dir(initialState); | 
				
			||||
 | 
					        this.state = initialState; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    handleSignUp() { | 
				
			||||
 | 
					        this.contracts[contract].methods[signUpMethod].cacheSend(...Object.values(this.state.signUp)); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    handleUsernameUpdate() { | 
				
			||||
 | 
					        this.contracts[contract].methods[updateUsernameMethod].cacheSend(...Object.values(this.state.updateUsername)); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    handleSignUpInputChange(event) { | 
				
			||||
 | 
					        this.setState({ signUp: { ...this.state.signUp, [event.target.name]: event.target.value} }); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    handleUpdateUsernameInputChange(event) { | 
				
			||||
 | 
					        this.setState({ updateUsername: { ...this.state.updateUsername, [event.target.name]: event.target.value} }); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    render() { | 
				
			||||
 | 
					        let signUp = this.inputs.signUp[0].name;    //username
 | 
				
			||||
 | 
					        let updateUsername = this.inputs.updateUsername[0].name;    //newUsername
 | 
				
			||||
 | 
					        return ( | 
				
			||||
 | 
					            <AuthWrapperContainer | 
				
			||||
 | 
					                authRender={ | 
				
			||||
 | 
					                    <form className="pure-form pure-form-stacked"> | 
				
			||||
 | 
					                        <input key={updateUsername} name={updateUsername} type="text" value={this.state.updateUsername.newUsername} placeholder="Username" onChange={this.handleUpdateUsernameInputChange} /> | 
				
			||||
 | 
					                        <button key="submit" className="pure-button" type="button" onClick={this.handleUsernameUpdate}>Update</button> | 
				
			||||
 | 
					                    </form> | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					                guestRender={ | 
				
			||||
 | 
					                    <form className="pure-form pure-form-stacked"> | 
				
			||||
 | 
					                        <input key={signUp} name={signUp} type="text" value={this.state.signUp.username} placeholder="Username" onChange={this.handleSignUpInputChange} /> | 
				
			||||
 | 
					                        <button key="submit" className="pure-button" type="button" onClick={this.handleSignUp}>Sign Up</button> | 
				
			||||
 | 
					                    </form> | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					            /> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        ) | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					UsernameFormContainer.contextTypes = { | 
				
			||||
 | 
					    drizzle: PropTypes.object | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const mapStateToProps = state => { | 
				
			||||
 | 
					    return { | 
				
			||||
 | 
					        contracts: state.contracts | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					export default drizzleConnect(UsernameFormContainer, mapStateToProps) | 
				
			||||
@ -0,0 +1,18 @@ | 
				
			|||||
 | 
					import Forum from './build/contracts/Forum.json' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const drizzleOptions = { | 
				
			||||
 | 
					    web3: { | 
				
			||||
 | 
					        fallback: { | 
				
			||||
 | 
					            type: 'ws', | 
				
			||||
 | 
					            url: 'ws://127.0.0.1:8545' | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    }, | 
				
			||||
 | 
					    contracts: [ | 
				
			||||
 | 
					        Forum | 
				
			||||
 | 
					    ], | 
				
			||||
 | 
					    events: { | 
				
			||||
 | 
					        Forum: ['UserSignedUp'] | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					export default drizzleOptions | 
				
			||||
@ -1,23 +0,0 @@ | 
				
			|||||
import React, { Component } from 'react' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
class Dashboard extends Component { | 
					 | 
				
			||||
  constructor(props, { authData }) { | 
					 | 
				
			||||
    super(props); | 
					 | 
				
			||||
    authData = this.props | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  render() { | 
					 | 
				
			||||
    return( | 
					 | 
				
			||||
      <main className="container"> | 
					 | 
				
			||||
        <div className="pure-g"> | 
					 | 
				
			||||
          <div className="pure-u-1-1"> | 
					 | 
				
			||||
            <h1>Dashboard</h1> | 
					 | 
				
			||||
            <p><strong>Congratulations {this.props.authData.name}!</strong> If you're seeing this page, you've logged in with your own smart contract successfully.</p> | 
					 | 
				
			||||
          </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
      </main> | 
					 | 
				
			||||
    ) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default Dashboard | 
					 | 
				
			||||
@ -0,0 +1,15 @@ | 
				
			|||||
 | 
					import Home from './Home' | 
				
			||||
 | 
					import { drizzleConnect } from 'drizzle-react' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// May still need this even with data function to refresh component on updates for this contract.
 | 
				
			||||
 | 
					const mapStateToProps = state => { | 
				
			||||
 | 
					  return { | 
				
			||||
 | 
					    accounts: state.accounts, | 
				
			||||
 | 
					    Forum: state.contracts.Forum, | 
				
			||||
 | 
					    drizzleStatus: state.drizzleStatus | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const HomeContainer = drizzleConnect(Home, mapStateToProps); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					export default HomeContainer | 
				
			||||
@ -1,12 +1,10 @@ | 
				
			|||||
import { combineReducers } from 'redux' | 
					import { combineReducers } from 'redux' | 
				
			||||
import { routerReducer } from 'react-router-redux' | 
					import { routerReducer } from 'react-router-redux' | 
				
			||||
import userReducer from './user/userReducer' | 
					import { drizzleReducers } from 'drizzle' | 
				
			||||
import web3Reducer from './util/web3/web3Reducer' | 
					 | 
				
			||||
 | 
					
 | 
				
			||||
const reducer = combineReducers({ | 
					const reducer = combineReducers({ | 
				
			||||
  routing: routerReducer, | 
					  routing: routerReducer, | 
				
			||||
  user: userReducer, | 
					  ...drizzleReducers | 
				
			||||
  web3: web3Reducer | 
					 | 
				
			||||
}); | 
					}); | 
				
			||||
 | 
					
 | 
				
			||||
export default reducer | 
					export default reducer | 
				
			||||
 | 
				
			|||||
@ -1,117 +0,0 @@ | 
				
			|||||
// In production, we register a service worker to serve assets from local cache.
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
// This lets the app load faster on subsequent visits in production, and gives
 | 
					 | 
				
			||||
// it offline capabilities. However, it also means that developers (and users)
 | 
					 | 
				
			||||
// will only see deployed updates on the "N+1" visit to a page, since previously
 | 
					 | 
				
			||||
// cached resources are updated in the background.
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
 | 
					 | 
				
			||||
// This link also includes instructions on opting out of this behavior.
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const isLocalhost = Boolean( | 
					 | 
				
			||||
  window.location.hostname === 'localhost' || | 
					 | 
				
			||||
    // [::1] is the IPv6 localhost address.
 | 
					 | 
				
			||||
    window.location.hostname === '[::1]' || | 
					 | 
				
			||||
    // 127.0.0.1/8 is considered localhost for IPv4.
 | 
					 | 
				
			||||
    window.location.hostname.match( | 
					 | 
				
			||||
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ | 
					 | 
				
			||||
    ) | 
					 | 
				
			||||
); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default function register() { | 
					 | 
				
			||||
  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { | 
					 | 
				
			||||
    // The URL constructor is available in all browsers that support SW.
 | 
					 | 
				
			||||
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location); | 
					 | 
				
			||||
    if (publicUrl.origin !== window.location.origin) { | 
					 | 
				
			||||
      // Our service worker won't work if PUBLIC_URL is on a different origin
 | 
					 | 
				
			||||
      // from what our page is served on. This might happen if a CDN is used to
 | 
					 | 
				
			||||
      // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
 | 
					 | 
				
			||||
      return; | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    window.addEventListener('load', () => { | 
					 | 
				
			||||
      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
      if (isLocalhost) { | 
					 | 
				
			||||
        // This is running on localhost. Lets check if a service worker still exists or not.
 | 
					 | 
				
			||||
        checkValidServiceWorker(swUrl); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        // Add some additional logging to localhost, pointing developers to the
 | 
					 | 
				
			||||
        // service worker/PWA documentation.
 | 
					 | 
				
			||||
        navigator.serviceWorker.ready.then(() => { | 
					 | 
				
			||||
          console.log( | 
					 | 
				
			||||
            'This web app is being served cache-first by a service ' + | 
					 | 
				
			||||
              'worker. To learn more, visit https://goo.gl/SC7cgQ' | 
					 | 
				
			||||
          ); | 
					 | 
				
			||||
        }); | 
					 | 
				
			||||
      } else { | 
					 | 
				
			||||
        // Is not local host. Just register service worker
 | 
					 | 
				
			||||
        registerValidSW(swUrl); | 
					 | 
				
			||||
      } | 
					 | 
				
			||||
    }); | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
function registerValidSW(swUrl) { | 
					 | 
				
			||||
  navigator.serviceWorker | 
					 | 
				
			||||
    .register(swUrl) | 
					 | 
				
			||||
    .then(registration => { | 
					 | 
				
			||||
      registration.onupdatefound = () => { | 
					 | 
				
			||||
        const installingWorker = registration.installing; | 
					 | 
				
			||||
        installingWorker.onstatechange = () => { | 
					 | 
				
			||||
          if (installingWorker.state === 'installed') { | 
					 | 
				
			||||
            if (navigator.serviceWorker.controller) { | 
					 | 
				
			||||
              // At this point, the old content will have been purged and
 | 
					 | 
				
			||||
              // the fresh content will have been added to the cache.
 | 
					 | 
				
			||||
              // It's the perfect time to display a "New content is
 | 
					 | 
				
			||||
              // available; please refresh." message in your web app.
 | 
					 | 
				
			||||
              console.log('New content is available; please refresh.'); | 
					 | 
				
			||||
            } else { | 
					 | 
				
			||||
              // At this point, everything has been precached.
 | 
					 | 
				
			||||
              // It's the perfect time to display a
 | 
					 | 
				
			||||
              // "Content is cached for offline use." message.
 | 
					 | 
				
			||||
              console.log('Content is cached for offline use.'); | 
					 | 
				
			||||
            } | 
					 | 
				
			||||
          } | 
					 | 
				
			||||
        }; | 
					 | 
				
			||||
      }; | 
					 | 
				
			||||
    }) | 
					 | 
				
			||||
    .catch(error => { | 
					 | 
				
			||||
      console.error('Error during service worker registration:', error); | 
					 | 
				
			||||
    }); | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
function checkValidServiceWorker(swUrl) { | 
					 | 
				
			||||
  // Check if the service worker can be found. If it can't reload the page.
 | 
					 | 
				
			||||
  fetch(swUrl) | 
					 | 
				
			||||
    .then(response => { | 
					 | 
				
			||||
      // Ensure service worker exists, and that we really are getting a JS file.
 | 
					 | 
				
			||||
      if ( | 
					 | 
				
			||||
        response.status === 404 || | 
					 | 
				
			||||
        response.headers.get('content-type').indexOf('javascript') === -1 | 
					 | 
				
			||||
      ) { | 
					 | 
				
			||||
        // No service worker found. Probably a different app. Reload the page.
 | 
					 | 
				
			||||
        navigator.serviceWorker.ready.then(registration => { | 
					 | 
				
			||||
          registration.unregister().then(() => { | 
					 | 
				
			||||
            window.location.reload(); | 
					 | 
				
			||||
          }); | 
					 | 
				
			||||
        }); | 
					 | 
				
			||||
      } else { | 
					 | 
				
			||||
        // Service worker found. Proceed as normal.
 | 
					 | 
				
			||||
        registerValidSW(swUrl); | 
					 | 
				
			||||
      } | 
					 | 
				
			||||
    }) | 
					 | 
				
			||||
    .catch(() => { | 
					 | 
				
			||||
      console.log( | 
					 | 
				
			||||
        'No internet connection found. App is running in offline mode.' | 
					 | 
				
			||||
      ); | 
					 | 
				
			||||
    }); | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export function unregister() { | 
					 | 
				
			||||
  if ('serviceWorker' in navigator) { | 
					 | 
				
			||||
    navigator.serviceWorker.ready.then(registration => { | 
					 | 
				
			||||
      registration.unregister(); | 
					 | 
				
			||||
    }); | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
@ -0,0 +1,8 @@ | 
				
			|||||
 | 
					import { all, fork } from 'redux-saga/effects' | 
				
			||||
 | 
					import { drizzleSagas } from 'drizzle' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					export default function* root() { | 
				
			||||
 | 
					  yield all( | 
				
			||||
 | 
					    drizzleSagas.map(saga => fork(saga)) | 
				
			||||
 | 
					  ) | 
				
			||||
 | 
					} | 
				
			||||
@ -1,22 +1,33 @@ | 
				
			|||||
import { browserHistory } from 'react-router' | 
					import { browserHistory } from 'react-router' | 
				
			||||
import { createStore, applyMiddleware, compose } from 'redux' | 
					import { createStore, applyMiddleware, compose } from 'redux' | 
				
			||||
import thunkMiddleware from 'redux-thunk' | 
					 | 
				
			||||
import { routerMiddleware } from 'react-router-redux' | 
					import { routerMiddleware } from 'react-router-redux' | 
				
			||||
import reducer from './reducer' | 
					import reducer from './reducer' | 
				
			||||
 | 
					import rootSaga from './rootSaga' | 
				
			||||
 | 
					import createSagaMiddleware from 'redux-saga' | 
				
			||||
 | 
					import { generateContractsInitialState } from 'drizzle' | 
				
			||||
 | 
					import drizzleOptions from './drizzleOptions' | 
				
			||||
 | 
					
 | 
				
			||||
// Redux DevTools (see also https://github.com/zalmoxisus/redux-devtools-extension#12-advanced-store-setup)
 | 
					// Redux DevTools
 | 
				
			||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; | 
					const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; | 
				
			||||
 | 
					
 | 
				
			||||
const routingMiddleware = routerMiddleware(browserHistory); | 
					const routingMiddleware = routerMiddleware(browserHistory); | 
				
			||||
 | 
					const sagaMiddleware = createSagaMiddleware(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const initialState = { | 
				
			||||
 | 
					  contracts: generateContractsInitialState(drizzleOptions) | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
const store = createStore( | 
					const store = createStore( | 
				
			||||
  reducer, | 
					  reducer, | 
				
			||||
 | 
					  initialState, | 
				
			||||
  composeEnhancers( | 
					  composeEnhancers( | 
				
			||||
    applyMiddleware( | 
					    applyMiddleware( | 
				
			||||
      thunkMiddleware, | 
					      routingMiddleware, | 
				
			||||
      routingMiddleware | 
					      sagaMiddleware | 
				
			||||
    ) | 
					    ) | 
				
			||||
  ) | 
					  ) | 
				
			||||
); | 
					); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					sagaMiddleware.run(rootSaga); | 
				
			||||
 | 
					
 | 
				
			||||
export default store | 
					export default store | 
				
			||||
@ -1,20 +0,0 @@ | 
				
			|||||
import React, { Component } from 'react' | 
					 | 
				
			||||
import ProfileFormContainer from '../../ui/profileform/ProfileFormContainer' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
class Profile extends Component { | 
					 | 
				
			||||
  render() { | 
					 | 
				
			||||
    return( | 
					 | 
				
			||||
      <main className="container"> | 
					 | 
				
			||||
        <div className="pure-g"> | 
					 | 
				
			||||
          <div className="pure-u-1-1"> | 
					 | 
				
			||||
            <h1>Profile</h1> | 
					 | 
				
			||||
            <p>Edit your account details here.</p> | 
					 | 
				
			||||
            <ProfileFormContainer /> | 
					 | 
				
			||||
          </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
      </main> | 
					 | 
				
			||||
    ) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default Profile | 
					 | 
				
			||||
@ -1,20 +0,0 @@ | 
				
			|||||
import React, { Component } from 'react' | 
					 | 
				
			||||
import SignUpFormContainer from '../../ui/signupform/SignUpFormContainer' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
class SignUp extends Component { | 
					 | 
				
			||||
  render() { | 
					 | 
				
			||||
    return( | 
					 | 
				
			||||
      <main className="container"> | 
					 | 
				
			||||
        <div className="pure-g"> | 
					 | 
				
			||||
          <div className="pure-u-1-1"> | 
					 | 
				
			||||
            <h1>Sign Up</h1> | 
					 | 
				
			||||
            <p>We've got your wallet information, simply input your name and your account is made!</p> | 
					 | 
				
			||||
            <SignUpFormContainer /> | 
					 | 
				
			||||
          </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
      </main> | 
					 | 
				
			||||
    ) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default SignUp | 
					 | 
				
			||||
@ -1,11 +0,0 @@ | 
				
			|||||
import React from 'react' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const LoginButton = ({ onLoginUserClick }) => { | 
					 | 
				
			||||
  return( | 
					 | 
				
			||||
    <li className="pure-menu-item"> | 
					 | 
				
			||||
      <a href="" className="pure-menu-link" onClick={(event) => onLoginUserClick(event)}>Login</a> | 
					 | 
				
			||||
    </li> | 
					 | 
				
			||||
  ) | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default LoginButton | 
					 | 
				
			||||
@ -1,69 +0,0 @@ | 
				
			|||||
import ForumContract from '../../../build/contracts/Forum.json' | 
					 | 
				
			||||
import { browserHistory } from 'react-router' | 
					 | 
				
			||||
import store from '../../../store' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const contract = require('truffle-contract'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export const USER_LOGGED_IN = 'USER_LOGGED_IN'; | 
					 | 
				
			||||
function userLoggedIn(user) { | 
					 | 
				
			||||
  return { | 
					 | 
				
			||||
    type: USER_LOGGED_IN, | 
					 | 
				
			||||
    payload: user | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export function loginUser() { | 
					 | 
				
			||||
  let web3 = store.getState().web3.web3Instance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  // Double-check web3's status.
 | 
					 | 
				
			||||
  if (typeof web3 !== 'undefined') { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    return function(dispatch) { | 
					 | 
				
			||||
      // Using truffle-contract we create the authentication object.
 | 
					 | 
				
			||||
      const authentication = contract(ForumContract); | 
					 | 
				
			||||
      authentication.setProvider(web3.currentProvider); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
      // Declaring this for later so we can chain functions on Authentication.
 | 
					 | 
				
			||||
      let authenticationInstance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
      // Get current ethereum wallet.
 | 
					 | 
				
			||||
      web3.eth.getCoinbase((error, coinbase) => { | 
					 | 
				
			||||
        // Log errors, if any.
 | 
					 | 
				
			||||
        if (error) { | 
					 | 
				
			||||
          console.error(error); | 
					 | 
				
			||||
        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        authentication.deployed().then(function(instance) { | 
					 | 
				
			||||
          authenticationInstance = instance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
          // Attempt to login user.
 | 
					 | 
				
			||||
          authenticationInstance.login({from: coinbase}) | 
					 | 
				
			||||
          .then(function(result) { | 
					 | 
				
			||||
            // If no error, login user.
 | 
					 | 
				
			||||
            console.log("Login successful: " + JSON.parse(result)); | 
					 | 
				
			||||
            dispatch(userLoggedIn({"name": JSON.parse(result)})); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            // Used a manual redirect here as opposed to a wrapper.
 | 
					 | 
				
			||||
            // This way, once logged in a user can still access the home page.
 | 
					 | 
				
			||||
            let currentLocation = browserHistory.getCurrentLocation(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            if ('redirect' in currentLocation.query) | 
					 | 
				
			||||
              return browserHistory.push(decodeURIComponent(currentLocation.query.redirect)); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            return browserHistory.push('/dashboard') | 
					 | 
				
			||||
          }) | 
					 | 
				
			||||
          .catch(function(result) { | 
					 | 
				
			||||
            // If error, go to signup page.
 | 
					 | 
				
			||||
            console.error('Wallet ' + coinbase + ' does not have an account!'); | 
					 | 
				
			||||
            console.error('Error: ' + result); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            return browserHistory.push('/signup') | 
					 | 
				
			||||
          }) | 
					 | 
				
			||||
        }) | 
					 | 
				
			||||
      }) | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  } else { | 
					 | 
				
			||||
    console.error('Web3 is not initialized.'); | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
@ -1,23 +0,0 @@ | 
				
			|||||
import { connect } from 'react-redux' | 
					 | 
				
			||||
import LoginButton from './LoginButton' | 
					 | 
				
			||||
import { loginUser } from './LoginButtonActions' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const mapStateToProps = (state, ownProps) => { | 
					 | 
				
			||||
  return {} | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const mapDispatchToProps = (dispatch) => { | 
					 | 
				
			||||
  return { | 
					 | 
				
			||||
    onLoginUserClick: (event) => { | 
					 | 
				
			||||
      event.preventDefault(); | 
					 | 
				
			||||
      dispatch(loginUser()); | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const LoginButtonContainer = connect( | 
					 | 
				
			||||
  mapStateToProps, | 
					 | 
				
			||||
  mapDispatchToProps | 
					 | 
				
			||||
)(LoginButton); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default LoginButtonContainer | 
					 | 
				
			||||
@ -1,42 +0,0 @@ | 
				
			|||||
import React, { Component } from 'react' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
class ProfileForm extends Component { | 
					 | 
				
			||||
  constructor(props) { | 
					 | 
				
			||||
    super(props); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    this.state = { | 
					 | 
				
			||||
      name: this.props.name | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  onInputChange(event) { | 
					 | 
				
			||||
    this.setState({ name: event.target.value }) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  handleSubmit(event) { | 
					 | 
				
			||||
    event.preventDefault(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    if (this.state.name.length < 2) | 
					 | 
				
			||||
      return alert('Please fill in your name.'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    this.props.onProfileFormSubmit(this.state.name, event) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  render() { | 
					 | 
				
			||||
    return( | 
					 | 
				
			||||
      <form className="pure-form pure-form-stacked" onSubmit={this.handleSubmit.bind(this)}> | 
					 | 
				
			||||
        <fieldset> | 
					 | 
				
			||||
          <label htmlFor="name">Name</label> | 
					 | 
				
			||||
          <input id="name" type="text" value={this.state.name} onChange={this.onInputChange.bind(this)} placeholder="Name" /> | 
					 | 
				
			||||
          <span className="pure-form-message">This is a required field.</span> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
          <br /> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
          <button type="submit" className="pure-button pure-button-primary">Update</button> | 
					 | 
				
			||||
        </fieldset> | 
					 | 
				
			||||
      </form> | 
					 | 
				
			||||
    ) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default ProfileForm | 
					 | 
				
			||||
@ -1,56 +0,0 @@ | 
				
			|||||
import ForumContract from '../../../build/contracts/Forum.json' | 
					 | 
				
			||||
import store from '../../../store' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const contract = require('truffle-contract'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export const USER_UPDATED = 'USER_UPDATED'; | 
					 | 
				
			||||
function userUpdated(user) { | 
					 | 
				
			||||
  return { | 
					 | 
				
			||||
    type: USER_UPDATED, | 
					 | 
				
			||||
    payload: user | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export function updateUser(name) { | 
					 | 
				
			||||
  let web3 = store.getState().web3.web3Instance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  // Double-check web3's status.
 | 
					 | 
				
			||||
  if (typeof web3 !== 'undefined') { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    return function(dispatch) { | 
					 | 
				
			||||
      // Using truffle-contract we create the authentication object.
 | 
					 | 
				
			||||
      const authentication = contract(ForumContract); | 
					 | 
				
			||||
      authentication.setProvider(web3.currentProvider); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
      // Declaring this for later so we can chain functions on Authentication.
 | 
					 | 
				
			||||
      let authenticationInstance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
      // Get current ethereum wallet.
 | 
					 | 
				
			||||
      web3.eth.getCoinbase((error, coinbase) => { | 
					 | 
				
			||||
        // Log errors, if any.
 | 
					 | 
				
			||||
        if (error) { | 
					 | 
				
			||||
          console.error(error); | 
					 | 
				
			||||
        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        authentication.deployed().then(function(instance) { | 
					 | 
				
			||||
          authenticationInstance = instance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
          // Attempt to login user.
 | 
					 | 
				
			||||
          authenticationInstance.signUp(JSON.stringify(name), {from: coinbase}) | 
					 | 
				
			||||
          .then(function(result) { | 
					 | 
				
			||||
            console.log("SignUp/name update successful: " + name); | 
					 | 
				
			||||
            // If no error, update user.
 | 
					 | 
				
			||||
            dispatch(userUpdated({"name": name})); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            return alert('Name updated!') | 
					 | 
				
			||||
          }) | 
					 | 
				
			||||
          .catch(function(result) { | 
					 | 
				
			||||
            // If error...
 | 
					 | 
				
			||||
          }) | 
					 | 
				
			||||
        }) | 
					 | 
				
			||||
      }) | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  } else { | 
					 | 
				
			||||
    console.error('Web3 is not initialized.'); | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
@ -1,25 +0,0 @@ | 
				
			|||||
import { connect } from 'react-redux' | 
					 | 
				
			||||
import ProfileForm from './ProfileForm' | 
					 | 
				
			||||
import { updateUser } from './ProfileFormActions' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const mapStateToProps = (state, ownProps) => { | 
					 | 
				
			||||
  return { | 
					 | 
				
			||||
    name: state.user.data.name | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const mapDispatchToProps = (dispatch) => { | 
					 | 
				
			||||
  return { | 
					 | 
				
			||||
    onProfileFormSubmit: (name, event) => { | 
					 | 
				
			||||
      event.preventDefault(); | 
					 | 
				
			||||
      dispatch(updateUser(name)) | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const ProfileFormContainer = connect( | 
					 | 
				
			||||
  mapStateToProps, | 
					 | 
				
			||||
  mapDispatchToProps | 
					 | 
				
			||||
)(ProfileForm); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default ProfileFormContainer | 
					 | 
				
			||||
@ -1,44 +0,0 @@ | 
				
			|||||
import React, { Component } from 'react' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
class SignUpForm extends Component { | 
					 | 
				
			||||
  constructor(props) { | 
					 | 
				
			||||
    super(props); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    this.state = { | 
					 | 
				
			||||
      name: '' | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  onInputChange(event) { | 
					 | 
				
			||||
    this.setState({ name: event.target.value }) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  handleSubmit(event) { | 
					 | 
				
			||||
    event.preventDefault(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    if (this.state.name.length < 2) | 
					 | 
				
			||||
    { | 
					 | 
				
			||||
      return alert('Please fill in your name.') | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    this.props.onSignUpFormSubmit(this.state.name) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  render() { | 
					 | 
				
			||||
    return( | 
					 | 
				
			||||
      <form className="pure-form pure-form-stacked" onSubmit={this.handleSubmit.bind(this)}> | 
					 | 
				
			||||
        <fieldset> | 
					 | 
				
			||||
          <label htmlFor="name">Name</label> | 
					 | 
				
			||||
          <input id="name" type="text" value={this.state.name} onChange={this.onInputChange.bind(this)} placeholder="Name" /> | 
					 | 
				
			||||
          <span className="pure-form-message">This is a required field.</span> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
          <br /> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
          <button type="submit" className="pure-button pure-button-primary">Sign Up</button> | 
					 | 
				
			||||
        </fieldset> | 
					 | 
				
			||||
      </form> | 
					 | 
				
			||||
    ) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default SignUpForm | 
					 | 
				
			||||
@ -1,45 +0,0 @@ | 
				
			|||||
import ForumContract from '../../../build/contracts/Forum.json' | 
					 | 
				
			||||
import { loginUser } from '../loginbutton/LoginButtonActions' | 
					 | 
				
			||||
import store from '../../../store' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const contract = require('truffle-contract'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export function signUpUser(name) { | 
					 | 
				
			||||
  let web3 = store.getState().web3.web3Instance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  // Double-check web3's status.
 | 
					 | 
				
			||||
  if (typeof web3 !== 'undefined') { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    return function(dispatch) { | 
					 | 
				
			||||
      // Using truffle-contract we create the authentication object.
 | 
					 | 
				
			||||
      const authentication = contract(ForumContract); | 
					 | 
				
			||||
      authentication.setProvider(web3.currentProvider); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
      // Declaring this for later so we can chain functions on Authentication.
 | 
					 | 
				
			||||
      let authenticationInstance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
      // Get current ethereum wallet.
 | 
					 | 
				
			||||
      web3.eth.getCoinbase((error, coinbase) => { | 
					 | 
				
			||||
        // Log errors, if any.
 | 
					 | 
				
			||||
        if (error) | 
					 | 
				
			||||
          console.error(error); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        authentication.deployed().then(function(instance) { | 
					 | 
				
			||||
          authenticationInstance = instance; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
          // Attempt to sign up user.
 | 
					 | 
				
			||||
          authenticationInstance.signUp(JSON.stringify(name), {from: coinbase}) | 
					 | 
				
			||||
          .then(function(result) { | 
					 | 
				
			||||
            // If no error, login user.
 | 
					 | 
				
			||||
            return dispatch(loginUser()) | 
					 | 
				
			||||
          }) | 
					 | 
				
			||||
          .catch(function(result) { | 
					 | 
				
			||||
            console.log("SignUp error: " + result); | 
					 | 
				
			||||
          }) | 
					 | 
				
			||||
        }) | 
					 | 
				
			||||
      }) | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  } else { | 
					 | 
				
			||||
    console.error('Web3 is not initialized.'); | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
@ -1,22 +0,0 @@ | 
				
			|||||
import { connect } from 'react-redux' | 
					 | 
				
			||||
import SignUpForm from './SignUpForm' | 
					 | 
				
			||||
import { signUpUser } from './SignUpFormActions' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const mapStateToProps = (state, ownProps) => { | 
					 | 
				
			||||
  return {} | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const mapDispatchToProps = (dispatch) => { | 
					 | 
				
			||||
  return { | 
					 | 
				
			||||
    onSignUpFormSubmit: (name) => { | 
					 | 
				
			||||
      dispatch(signUpUser(name)) | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const SignUpFormContainer = connect( | 
					 | 
				
			||||
  mapStateToProps, | 
					 | 
				
			||||
  mapDispatchToProps | 
					 | 
				
			||||
)(SignUpForm); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default SignUpFormContainer | 
					 | 
				
			||||
@ -1,22 +0,0 @@ | 
				
			|||||
const initialState = { | 
					 | 
				
			||||
    data: null | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const userReducer = (state = initialState, action) => { | 
					 | 
				
			||||
    if (action.type === 'USER_LOGGED_IN' || action.type === 'USER_UPDATED') | 
					 | 
				
			||||
    { | 
					 | 
				
			||||
        return Object.assign({}, state, { | 
					 | 
				
			||||
            data: action.payload | 
					 | 
				
			||||
        }) | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    if (action.type === 'USER_LOGGED_OUT') | 
					 | 
				
			||||
    { | 
					 | 
				
			||||
        return Object.assign({}, state, { | 
					 | 
				
			||||
            data: null | 
					 | 
				
			||||
        }) | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
    return state; | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default userReducer | 
					 | 
				
			||||
@ -1,51 +0,0 @@ | 
				
			|||||
import store from '../../store' | 
					 | 
				
			||||
import Web3 from 'web3' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export const WEB3_INITIALIZED = 'WEB3_INITIALIZED'; | 
					 | 
				
			||||
function web3Initialized(results) { | 
					 | 
				
			||||
    return { | 
					 | 
				
			||||
        type: WEB3_INITIALIZED, | 
					 | 
				
			||||
        payload: results | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
 | 
					 | 
				
			||||
let getWeb3 = new Promise(function(resolve, reject) { | 
					 | 
				
			||||
    // Wait for loading completion to avoid race conditions with web3 injection timing.
 | 
					 | 
				
			||||
    window.addEventListener('load', function(dispatch) { | 
					 | 
				
			||||
        var results; | 
					 | 
				
			||||
        var web3 = window.web3; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        // Checking if Web3 has been injected by the browser (Mist/MetaMask)
 | 
					 | 
				
			||||
        if (typeof web3 !== 'undefined') { | 
					 | 
				
			||||
            // Use Mist/MetaMask's provider.
 | 
					 | 
				
			||||
            web3 = new Web3(web3.currentProvider); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            results = { | 
					 | 
				
			||||
                web3Instance: web3 | 
					 | 
				
			||||
            }; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            console.log('Injected web3 detected.'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            resolve(store.dispatch(web3Initialized(results))) | 
					 | 
				
			||||
        } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            // Fallback to localhost if no web3 injection.
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            var provider = new Web3.providers.HttpProvider('http://localhost:8545'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            web3 = new Web3(provider); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            results = { | 
					 | 
				
			||||
                web3Instance: web3 | 
					 | 
				
			||||
            }; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            console.log('No web3 instance injected, using Local web3.'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            resolve(store.dispatch(web3Initialized(results))) | 
					 | 
				
			||||
        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        // TODO: Error checking.
 | 
					 | 
				
			||||
    }) | 
					 | 
				
			||||
}); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default getWeb3 | 
					 | 
				
			||||
@ -1,16 +0,0 @@ | 
				
			|||||
const initialState = { | 
					 | 
				
			||||
  web3Instance: null | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
const web3Reducer = (state = initialState, action) => { | 
					 | 
				
			||||
  if (action.type === 'WEB3_INITIALIZED') | 
					 | 
				
			||||
  { | 
					 | 
				
			||||
    return Object.assign({}, state, { | 
					 | 
				
			||||
      web3Instance: action.payload.web3Instance | 
					 | 
				
			||||
    }) | 
					 | 
				
			||||
  } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
  return state | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export default web3Reducer | 
					 | 
				
			||||
@ -1,34 +0,0 @@ | 
				
			|||||
import { UserAuthWrapper } from 'redux-auth-wrapper' | 
					 | 
				
			||||
import { routerActions } from 'react-router-redux' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
// Layout Component Wrappers
 | 
					 | 
				
			||||
export const UserIsAuthenticated = UserAuthWrapper({ | 
					 | 
				
			||||
  authSelector: state => state.user.data, | 
					 | 
				
			||||
  redirectAction: routerActions.replace, | 
					 | 
				
			||||
  failureRedirectPath: '/', // '/login' by default.
 | 
					 | 
				
			||||
  wrapperDisplayName: 'UserIsAuthenticated' | 
					 | 
				
			||||
}); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export const UserIsNotAuthenticated = UserAuthWrapper({ | 
					 | 
				
			||||
  authSelector: state => state.user, | 
					 | 
				
			||||
  redirectAction: routerActions.replace, | 
					 | 
				
			||||
  failureRedirectPath: (state, ownProps) => ownProps.location.query.redirect || '/dashboard', | 
					 | 
				
			||||
  wrapperDisplayName: 'UserIsNotAuthenticated', | 
					 | 
				
			||||
  predicate: user => user.data === null, | 
					 | 
				
			||||
  allowRedirectBack: false | 
					 | 
				
			||||
}); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
// UI Component Wrappers
 | 
					 | 
				
			||||
export const VisibleOnlyAuth = UserAuthWrapper({ | 
					 | 
				
			||||
  authSelector: state => state.user, | 
					 | 
				
			||||
  wrapperDisplayName: 'VisibleOnlyAuth', | 
					 | 
				
			||||
  predicate: user => user.data, | 
					 | 
				
			||||
  FailureComponent: null | 
					 | 
				
			||||
}); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
export const HiddenOnlyAuth = UserAuthWrapper({ | 
					 | 
				
			||||
  authSelector: state => state.user, | 
					 | 
				
			||||
  wrapperDisplayName: 'HiddenOnlyAuth', | 
					 | 
				
			||||
  predicate: user => user.data === null, | 
					 | 
				
			||||
  FailureComponent: null | 
					 | 
				
			||||
}); | 
					 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue