mirror of https://gitlab.com/ecentrics/concordia
Apostolos Fanakis
4 years ago
28 changed files with 748 additions and 707 deletions
@ -1,34 +1,33 @@ |
|||
import React from 'react' |
|||
import { Provider } from 'react-redux' |
|||
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom' |
|||
import LoadingContainer from './LoadingContainer' |
|||
import PropTypes from 'prop-types' |
|||
import React from 'react'; |
|||
import { Provider } from 'react-redux'; |
|||
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; |
|||
import PropTypes from 'prop-types'; |
|||
import LoadingContainer from './LoadingContainer'; |
|||
|
|||
// CSS |
|||
import '../assets/css/app.css'; |
|||
|
|||
import CoreLayoutContainer from './CoreLayoutContainer'; |
|||
import HomeContainer from './HomeContainer'; |
|||
import NotFound from '../components/NotFound'; |
|||
|
|||
import NotFound from './NotFound'; |
|||
|
|||
const App = ({ store }) => ( |
|||
<Provider store={store}> |
|||
<LoadingContainer> |
|||
<Router> |
|||
<CoreLayoutContainer> |
|||
<Switch> |
|||
<Route exact path="/" component={HomeContainer} /> |
|||
<Route component={NotFound} /> |
|||
</Switch> |
|||
</CoreLayoutContainer> |
|||
</Router> |
|||
<Router> |
|||
<CoreLayoutContainer> |
|||
<Switch> |
|||
<Route exact path="/" component={HomeContainer} /> |
|||
<Route component={NotFound} /> |
|||
</Switch> |
|||
</CoreLayoutContainer> |
|||
</Router> |
|||
</LoadingContainer> |
|||
</Provider> |
|||
) |
|||
); |
|||
|
|||
App.propTypes = { |
|||
store: PropTypes.object.isRequired |
|||
} |
|||
store: PropTypes.object.isRequired, |
|||
}; |
|||
|
|||
export default App |
|||
export default App; |
|||
|
@ -1,72 +0,0 @@ |
|||
// Modified version of https://github.com/trufflesuite/drizzle/blob/develop/packages/react-plugin/src/DrizzleContext.js
|
|||
import React from "react"; |
|||
|
|||
const Context = React.createContext(); |
|||
|
|||
class Provider extends React.Component { |
|||
state = { |
|||
drizzleState: null, |
|||
drizzleInitialized: false, |
|||
breezeState: null, |
|||
breezeInitialized: false |
|||
}; |
|||
|
|||
componentDidMount() { |
|||
const { drizzle, breeze } = this.props; |
|||
// subscribe to changes in the store, keep state up-to-date
|
|||
this.unsubscribe = drizzle.store.subscribe(() => { |
|||
const drizzleState = drizzle.store.getState(); |
|||
const breezeState = breeze.store.getState(); |
|||
|
|||
if (drizzleState.drizzleStatus.initialized) { |
|||
this.setState({ |
|||
drizzleState, |
|||
drizzleInitialized: true |
|||
}); |
|||
} |
|||
if (breezeState.breezeStatus.initialized) { |
|||
this.setState({ |
|||
breezeState: breezeState, |
|||
breezeInitialized: true |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
this.unsubscribe = breeze.store.subscribe(() => { |
|||
const breezeState = breeze.store.getState(); |
|||
if (breezeState.breezeStatus.initialized) { |
|||
this.setState({ |
|||
breezeState: breezeState, |
|||
breezeInitialized: true |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
this.unsubscribe(); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<Context.Provider |
|||
value={{ |
|||
drizzle: this.props.drizzle, |
|||
drizzleState: this.state.drizzleState, |
|||
drizzleInitialized: this.state.drizzleInitialized, |
|||
breeze: this.props.breeze, |
|||
breezeState: this.state.breezeState, |
|||
breezeInitialized: this.state.breezeInitialized |
|||
}} |
|||
> |
|||
{this.props.children} |
|||
</Context.Provider> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default { |
|||
Context: Context, |
|||
Consumer: Context.Consumer, |
|||
Provider |
|||
}; |
@ -0,0 +1,81 @@ |
|||
// Modified version of https://github.com/trufflesuite/drizzle/blob/develop/packages/react-plugin/src/DrizzleContext.js |
|||
import React from 'react'; |
|||
|
|||
const Context = React.createContext(); |
|||
|
|||
class Provider extends React.Component { |
|||
constructor(props) { |
|||
super(props); |
|||
|
|||
this.state = { |
|||
drizzleState: null, |
|||
drizzleInitialized: false, |
|||
breezeState: null, |
|||
breezeInitialized: false, |
|||
}; |
|||
} |
|||
|
|||
componentDidMount() { |
|||
const { drizzle, breeze } = this.props; |
|||
// subscribe to changes in the store, keep state up-to-date |
|||
this.unsubscribe = drizzle.store.subscribe(() => { |
|||
const drizzleState = drizzle.store.getState(); |
|||
const breezeState = breeze.store.getState(); |
|||
|
|||
if (drizzleState.drizzleStatus.initialized) { |
|||
this.setState({ |
|||
drizzleState, |
|||
drizzleInitialized: true, |
|||
}); |
|||
} |
|||
if (breezeState.breezeStatus.initialized) { |
|||
this.setState({ |
|||
breezeState, |
|||
breezeInitialized: true, |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
this.unsubscribe = breeze.store.subscribe(() => { |
|||
const breezeState = breeze.store.getState(); |
|||
if (breezeState.breezeStatus.initialized) { |
|||
this.setState({ |
|||
breezeState, |
|||
breezeInitialized: true, |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
this.unsubscribe(); |
|||
} |
|||
|
|||
render() { |
|||
const { |
|||
drizzleState, drizzleInitialized, breezeState, breezeInitialized, |
|||
} = this.state; |
|||
const { drizzle, breeze, children } = this.props; |
|||
|
|||
return ( |
|||
<Context.Provider |
|||
value={{ |
|||
drizzle, |
|||
drizzleState, |
|||
drizzleInitialized, |
|||
breeze, |
|||
breezeState, |
|||
breezeInitialized, |
|||
}} |
|||
> |
|||
{children} |
|||
</Context.Provider> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default { |
|||
Context, |
|||
Consumer: Context.Consumer, |
|||
Provider, |
|||
}; |
@ -1,19 +1,21 @@ |
|||
import React, { Component } from 'react'; |
|||
import React from 'react'; |
|||
import PropTypes from 'prop-types'; |
|||
|
|||
import MenuComponent from './MenuComponent'; |
|||
|
|||
export default class CoreLayout extends Component { |
|||
render() { |
|||
return ( |
|||
<div> |
|||
<MenuComponent/> |
|||
{this.props.children} |
|||
</div> |
|||
) |
|||
} |
|||
} |
|||
const CoreLayout = (props) => { |
|||
const { children } = props; |
|||
|
|||
return ( |
|||
<div> |
|||
<MenuComponent /> |
|||
{children} |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
CoreLayout.propTypes = { |
|||
children: PropTypes.element.isRequired |
|||
children: PropTypes.element.isRequired, |
|||
}; |
|||
|
|||
export default CoreLayout; |
|||
|
@ -1,9 +1,5 @@ |
|||
import React, { Component } from 'react'; |
|||
import React from 'react'; |
|||
|
|||
class HomeContainer extends Component { |
|||
render() { |
|||
return(<p>TODO: Home Container</p>); |
|||
} |
|||
} |
|||
const HomeContainer = () => (<p>TODO: Home Container</p>); |
|||
|
|||
export default HomeContainer; |
|||
|
@ -1,38 +1,35 @@ |
|||
import React, { Component } from 'react'; |
|||
import { withRouter } from "react-router"; |
|||
import React from 'react'; |
|||
import { withRouter } from 'react-router'; |
|||
import { Menu } from 'semantic-ui-react'; |
|||
|
|||
import AppContext from "./AppContext"; |
|||
import AppContext from './AppContext'; |
|||
|
|||
import app_logo from '../assets/images/app_logo.png'; |
|||
import appLogo from '../assets/images/app_logo.png'; |
|||
import SignUpForm from './SignUpForm'; |
|||
|
|||
class MenuComponent extends Component { |
|||
render() { |
|||
return ( |
|||
<AppContext.Consumer> |
|||
{context => { |
|||
return( |
|||
<div> |
|||
<Menu color='black' inverted> |
|||
<Menu.Item |
|||
link |
|||
name='home' |
|||
onClick={() => { this.props.history.push("/"); }} |
|||
> |
|||
<img src={app_logo} alt="app_logo"/> |
|||
</Menu.Item> |
|||
const MenuComponent = (props) => { |
|||
const { history: { push } } = props; |
|||
|
|||
<SignUpForm/> |
|||
return ( |
|||
<AppContext.Consumer> |
|||
{() => ( |
|||
<div> |
|||
<Menu color="black" inverted> |
|||
<Menu.Item |
|||
link |
|||
name="home" |
|||
onClick={() => { push('/'); }} |
|||
> |
|||
<img src={appLogo} alt="app_logo" /> |
|||
</Menu.Item> |
|||
|
|||
</Menu> |
|||
</div> |
|||
) |
|||
} |
|||
} |
|||
</AppContext.Consumer> |
|||
) |
|||
} |
|||
} |
|||
<SignUpForm /> |
|||
|
|||
</Menu> |
|||
</div> |
|||
)} |
|||
</AppContext.Consumer> |
|||
); |
|||
}; |
|||
|
|||
export default withRouter(MenuComponent); |
|||
|
@ -1,139 +1,144 @@ |
|||
import React, { Component } from 'react'; |
|||
import { Button, Form, Menu, Message, Modal } from 'semantic-ui-react'; |
|||
import { |
|||
Button, Form, Menu, Message, Modal, |
|||
} from 'semantic-ui-react'; |
|||
|
|||
import AppContext from "./AppContext"; |
|||
import { connect } from 'react-redux'; |
|||
import AppContext from './AppContext'; |
|||
|
|||
const contractName = 'Forum'; |
|||
const checkUsernameTakenMethod = 'isUserNameTaken'; |
|||
const signUpMethod = 'signUp'; |
|||
|
|||
class SignUpForm extends Component { |
|||
constructor(props, context) { |
|||
super(props, context); |
|||
|
|||
// For quick access |
|||
this.contract = this.context.drizzle.contracts[contractName]; |
|||
|
|||
this.handleInputChange = this.handleInputChange.bind(this); |
|||
this.handleSubmit = this.handleSubmit.bind(this); |
|||
this.completeAction = this.completeAction.bind(this); |
|||
|
|||
this.checkedUsernames = []; |
|||
|
|||
this.state = { |
|||
usernameInput: '', |
|||
error: false, |
|||
errorHeader: '', |
|||
errorMessage: '', |
|||
signingUp: false, |
|||
}; |
|||
constructor(props, context) { |
|||
super(props, context); |
|||
|
|||
// For quick access |
|||
this.contract = this.context.drizzle.contracts[contractName]; |
|||
|
|||
this.handleInputChange = this.handleInputChange.bind(this); |
|||
this.handleSubmit = this.handleSubmit.bind(this); |
|||
this.completeAction = this.completeAction.bind(this); |
|||
|
|||
this.checkedUsernames = []; |
|||
|
|||
this.state = { |
|||
usernameInput: '', |
|||
error: false, |
|||
errorHeader: '', |
|||
errorMessage: '', |
|||
signingUp: false, |
|||
}; |
|||
} |
|||
|
|||
componentDidUpdate() { |
|||
// TODO |
|||
} |
|||
|
|||
handleSubmit() { |
|||
const { usernameInput, error } = this.state; |
|||
|
|||
if (usernameInput === '') { |
|||
this.setState({ |
|||
error: true, |
|||
errorHeader: 'Data Incomplete', |
|||
errorMessage: 'You need to provide a username', |
|||
}); |
|||
} else if (!error) { |
|||
// TODO |
|||
// // Makes sure current input username has been checked for availability |
|||
// if (this.checkedUsernames.some((e) => e.usernameChecked === usernameInput)) { |
|||
// this.completeAction(); |
|||
// } |
|||
this.completeAction(); |
|||
} |
|||
|
|||
handleInputChange(e, { name, value }) { |
|||
this.setState({ |
|||
[name]: value, |
|||
error: false, |
|||
}); |
|||
if (value !== '') { |
|||
if (this.checkedUsernames.length > 0) { |
|||
if (this.checkedUsernames.some((e) => e.usernameChecked === value)) { |
|||
return; |
|||
} |
|||
} |
|||
|
|||
this.contract.methods[checkUsernameTakenMethod].cacheCall( |
|||
value, |
|||
); |
|||
} |
|||
} |
|||
|
|||
handleSubmit() { |
|||
const { usernameInput, error } = this.state; |
|||
|
|||
if (usernameInput === '') { |
|||
this.setState({ |
|||
error: true, |
|||
errorHeader: 'Data Incomplete', |
|||
errorMessage: 'You need to provide a username', |
|||
}); |
|||
} else if (!error) { |
|||
// TODO |
|||
// // Makes sure current input username has been checked for availability |
|||
// if (this.checkedUsernames.some((e) => e.usernameChecked === usernameInput)) { |
|||
// this.completeAction(); |
|||
// } |
|||
this.completeAction(); |
|||
} |
|||
|
|||
handleInputChange(e, { name, value }) { |
|||
this.setState({ |
|||
[name]: value, |
|||
error: false, |
|||
}); |
|||
if (value !== '') { |
|||
if (this.checkedUsernames.length > 0) { |
|||
if (this.checkedUsernames.some((e) => e.usernameChecked === value)) { |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
componentDidUpdate() { |
|||
// TODO |
|||
this.contract.methods[checkUsernameTakenMethod].cacheCall( |
|||
value, |
|||
); |
|||
} |
|||
|
|||
completeAction() { |
|||
const { usernameInput } = this.state; |
|||
const { user, account } = this.props; |
|||
|
|||
if (user.hasSignedUp) { |
|||
console.log('Signing up..') |
|||
this.contract.methods['signUp'].cacheSend(usernameInput); |
|||
} else { |
|||
this.setState({ |
|||
signingUp: true, |
|||
}); |
|||
this.contract.methods[signUpMethod].cacheSend( |
|||
...[usernameInput], { from: account }, |
|||
); |
|||
} |
|||
this.setState({ |
|||
usernameInput: '', |
|||
}); |
|||
} |
|||
|
|||
completeAction() { |
|||
const { usernameInput } = this.state; |
|||
const { user, account } = this.props; |
|||
|
|||
if (user.hasSignedUp) { |
|||
console.log('Signing up..'); |
|||
this.contract.methods.signUp.cacheSend(usernameInput); |
|||
} else { |
|||
this.setState({ |
|||
signingUp: true, |
|||
}); |
|||
this.contract.methods[signUpMethod].cacheSend( |
|||
...[usernameInput], { from: account }, |
|||
); |
|||
} |
|||
|
|||
render() { |
|||
const { |
|||
error, usernameInput, errorHeader, errorMessage, signingUp, |
|||
} = this.state; |
|||
|
|||
return( |
|||
<Modal as={Form} onSubmit={e => this.handleSubmit(e)} trigger={ |
|||
<Menu.Item |
|||
name='signup' |
|||
position='right' |
|||
content='Sign Up' |
|||
/> |
|||
}> |
|||
<Modal.Header>Sign Up</Modal.Header> |
|||
<Modal.Content> |
|||
|
|||
<Form.Field required> |
|||
<label>Username</label> |
|||
<Form.Input |
|||
placeholder='Username' |
|||
name="usernameInput" |
|||
value={usernameInput} |
|||
onChange={this.handleInputChange} |
|||
/> |
|||
</Form.Field> |
|||
<Message |
|||
error |
|||
header={errorHeader} |
|||
content={errorMessage} |
|||
this.setState({ |
|||
usernameInput: '', |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
const { |
|||
error, usernameInput, errorHeader, errorMessage, signingUp, |
|||
} = this.state; |
|||
|
|||
return ( |
|||
<Modal |
|||
as={Form} |
|||
onSubmit={(e) => this.handleSubmit(e)} |
|||
trigger={( |
|||
<Menu.Item |
|||
name="signup" |
|||
position="right" |
|||
content="Sign Up" |
|||
/> |
|||
)} |
|||
> |
|||
<Modal.Header>Sign Up</Modal.Header> |
|||
<Modal.Content> |
|||
|
|||
<Form.Field required> |
|||
<label>Username</label> |
|||
<Form.Input |
|||
placeholder="Username" |
|||
name="usernameInput" |
|||
value={usernameInput} |
|||
onChange={this.handleInputChange} |
|||
/> |
|||
<Button type="submit" color="black" content="Sign Up" /> |
|||
|
|||
</Modal.Content> |
|||
</Modal> |
|||
) |
|||
</Form.Field> |
|||
<Message |
|||
error |
|||
header={errorHeader} |
|||
content={errorMessage} |
|||
/> |
|||
<Button type="submit" color="black" content="Sign Up" /> |
|||
|
|||
} |
|||
</Modal.Content> |
|||
</Modal> |
|||
); |
|||
} |
|||
} |
|||
|
|||
SignUpForm.contextType = AppContext.Context; |
|||
|
|||
const mapStateToProps = (state) => ({ |
|||
user: state.user |
|||
user: state.user, |
|||
}); |
|||
|
|||
export default connect(mapStateToProps)(SignUpForm); |
|||
|
@ -1,45 +1,45 @@ |
|||
import { orbitConstants } from '@ezerous/breeze'; |
|||
import web3Options from './web3Options'; |
|||
import EthereumIdentityProvider from '../orbit/ΕthereumIdentityProvider'; |
|||
import { orbitConstants } from '@ezerous/breeze' |
|||
|
|||
const { web3 } = web3Options; |
|||
EthereumIdentityProvider.setWeb3(web3); |
|||
|
|||
const breezeOptions = { |
|||
ipfs: { |
|||
config: { |
|||
Addresses: { |
|||
Swarm: [ |
|||
// Use local signaling server (see also rendezvous script in package.json)
|
|||
// For more information: https://github.com/libp2p/js-libp2p-webrtc-star
|
|||
'/ip4/127.0.0.1/tcp/9090/wss/p2p-webrtc-star' |
|||
ipfs: { |
|||
config: { |
|||
Addresses: { |
|||
Swarm: [ |
|||
// Use local signaling server (see also rendezvous script in package.json)
|
|||
// For more information: https://github.com/libp2p/js-libp2p-webrtc-star
|
|||
'/ip4/127.0.0.1/tcp/9090/wss/p2p-webrtc-star', |
|||
|
|||
// Use the following public servers if needed
|
|||
// '/dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star',
|
|||
// '/dns4/ wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star'
|
|||
] |
|||
}, |
|||
}, |
|||
preload: { |
|||
enabled: false |
|||
}, |
|||
init: { |
|||
emptyRepo: true |
|||
} |
|||
// Use the following public servers if needed
|
|||
// '/dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star',
|
|||
// '/dns4/ wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star'
|
|||
], |
|||
}, |
|||
}, |
|||
orbit: { |
|||
identityProvider: EthereumIdentityProvider, |
|||
databases: [ |
|||
{ |
|||
name: 'topics', |
|||
type: orbitConstants.ORBIT_TYPE_KEYVALUE |
|||
}, |
|||
{ |
|||
name: 'posts', |
|||
type: orbitConstants.ORBIT_TYPE_KEYVALUE |
|||
} |
|||
] |
|||
} |
|||
preload: { |
|||
enabled: false, |
|||
}, |
|||
init: { |
|||
emptyRepo: true, |
|||
}, |
|||
}, |
|||
orbit: { |
|||
identityProvider: EthereumIdentityProvider, |
|||
databases: [ |
|||
{ |
|||
name: 'topics', |
|||
type: orbitConstants.ORBIT_TYPE_KEYVALUE, |
|||
}, |
|||
{ |
|||
name: 'posts', |
|||
type: orbitConstants.ORBIT_TYPE_KEYVALUE, |
|||
}, |
|||
], |
|||
}, |
|||
}; |
|||
|
|||
export default breezeOptions; |
|||
|
@ -1,7 +1,11 @@ |
|||
// https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md#address
|
|||
export async function determineDBAddress({orbit, dbName, type, identityId}) { |
|||
const ipfsMultihash = (await orbit.determineAddress(dbName, type, { |
|||
accessController: { write: [identityId] }, |
|||
})).root; |
|||
return `/orbitdb/${ipfsMultihash}/${dbName}`; |
|||
async function determineDBAddress({ |
|||
orbit, dbName, type, identityId, |
|||
}) { |
|||
const ipfsMultihash = (await orbit.determineAddress(dbName, type, { |
|||
accessController: { write: [identityId] }, |
|||
})).root; |
|||
return `/orbitdb/${ipfsMultihash}/${dbName}`; |
|||
} |
|||
|
|||
export default determineDBAddress; |
|||
|
@ -1,31 +1,31 @@ |
|||
import { USER_DATA_UPDATED } from '../actions/userActions'; |
|||
|
|||
const initialState = { |
|||
username: '', |
|||
address: null, |
|||
hasSignedUp: false, |
|||
username: '', |
|||
address: null, |
|||
hasSignedUp: false, |
|||
}; |
|||
|
|||
const userReducer = (state = initialState, action) => { |
|||
const { type } = action; |
|||
const { type } = action; |
|||
|
|||
if(type === USER_DATA_UPDATED) { |
|||
const { address, username } = action; |
|||
if(username){ |
|||
return { |
|||
username: username, |
|||
address: address, |
|||
hasSignedUp: true, |
|||
}; |
|||
} |
|||
return { |
|||
username: '', |
|||
address, |
|||
hasSignedUp: false, |
|||
}; |
|||
if (type === USER_DATA_UPDATED) { |
|||
const { address, username } = action; |
|||
if (username) { |
|||
return { |
|||
username, |
|||
address, |
|||
hasSignedUp: true, |
|||
}; |
|||
} |
|||
return { |
|||
username: '', |
|||
address, |
|||
hasSignedUp: false, |
|||
}; |
|||
} |
|||
|
|||
return state; |
|||
return state; |
|||
}; |
|||
|
|||
export default userReducer; |
|||
|
@ -1,22 +1,21 @@ |
|||
import { put, all, take } from 'redux-saga/effects' |
|||
import { put, all, take } from 'redux-saga/effects'; |
|||
|
|||
import { breezeActions } from '@ezerous/breeze' |
|||
import { drizzleActions } from '@ezerous/drizzle' |
|||
import { breezeActions } from '@ezerous/breeze'; |
|||
import { drizzleActions } from '@ezerous/drizzle'; |
|||
|
|||
function * initOrbitDatabases (action) { |
|||
const { account, breeze} = action; |
|||
yield put(breezeActions.orbit.orbitInit(breeze, account)); //same as breeze.initOrbit(account);
|
|||
function* initOrbitDatabases(action) { |
|||
const { account, breeze } = action; |
|||
yield put(breezeActions.orbit.orbitInit(breeze, account)); // same as breeze.initOrbit(account);
|
|||
} |
|||
|
|||
function * orbitSaga () { |
|||
const res = yield all([ |
|||
take(drizzleActions.drizzle.DRIZZLE_INITIALIZED), |
|||
take(breezeActions.breeze.BREEZE_INITIALIZED), |
|||
take(drizzleActions.account.ACCOUNTS_FETCHED) |
|||
]); |
|||
function* orbitSaga() { |
|||
const res = yield all([ |
|||
take(drizzleActions.drizzle.DRIZZLE_INITIALIZED), |
|||
take(breezeActions.breeze.BREEZE_INITIALIZED), |
|||
take(drizzleActions.account.ACCOUNTS_FETCHED), |
|||
]); |
|||
|
|||
yield initOrbitDatabases({breeze:res[1].breeze, account: res[2].accounts[0]}); |
|||
yield initOrbitDatabases({ breeze: res[1].breeze, account: res[2].accounts[0] }); |
|||
} |
|||
|
|||
export default orbitSaga |
|||
|
|||
export default orbitSaga; |
|||
|
@ -1,17 +1,17 @@ |
|||
import { all, fork } from 'redux-saga/effects'; |
|||
import { drizzleSagas } from '@ezerous/drizzle'; |
|||
import { breezeSagas } from '@ezerous/breeze' |
|||
import orbitSaga from './orbitSaga' |
|||
import userSaga from './userSaga' |
|||
import { breezeSagas } from '@ezerous/breeze'; |
|||
import orbitSaga from './orbitSaga'; |
|||
import userSaga from './userSaga'; |
|||
|
|||
export default function* root() { |
|||
const sagas = [ |
|||
...drizzleSagas, |
|||
...breezeSagas, |
|||
orbitSaga, |
|||
userSaga |
|||
]; |
|||
yield all( |
|||
sagas.map((saga) => fork(saga)), |
|||
); |
|||
const sagas = [ |
|||
...drizzleSagas, |
|||
...breezeSagas, |
|||
orbitSaga, |
|||
userSaga, |
|||
]; |
|||
yield all( |
|||
sagas.map((saga) => fork(saga)), |
|||
); |
|||
} |
|||
|
@ -1,42 +1,43 @@ |
|||
import { all, call, put, take } from 'redux-saga/effects'; |
|||
/* eslint-disable no-console */ |
|||
import { |
|||
all, call, put, take, |
|||
} from 'redux-saga/effects'; |
|||
|
|||
import { drizzleActions } from '@ezerous/drizzle'; |
|||
import { USER_DATA_UPDATED, USER_DATA_ERROR } from '../actions/userActions'; |
|||
|
|||
function * fetchUserData ({drizzle, account}) { |
|||
const contract = drizzle.contracts['Forum']; |
|||
const transaction = yield call(contract.methods.hasUserSignedUp, account); |
|||
|
|||
try { |
|||
const dispatchArgs = { address: account }; |
|||
const callResult = yield call(transaction.call, { address: account }); |
|||
|
|||
// User has signed up, fetch his username
|
|||
if (callResult) { |
|||
const txObj2 = yield call(contract.methods.getUsername, account); |
|||
dispatchArgs.username = yield call(txObj2.call, { |
|||
address: account |
|||
}); |
|||
} |
|||
|
|||
yield put({ |
|||
type: USER_DATA_UPDATED, ...dispatchArgs |
|||
}); |
|||
|
|||
} catch (error) { |
|||
console.error(error); |
|||
yield put({ type: USER_DATA_ERROR }); |
|||
function* fetchUserData({ drizzle, account }) { |
|||
const contract = drizzle.contracts.Forum; |
|||
const transaction = yield call(contract.methods.hasUserSignedUp, account); |
|||
|
|||
try { |
|||
const dispatchArgs = { address: account }; |
|||
const callResult = yield call(transaction.call, { address: account }); |
|||
|
|||
// User has signed up, fetch his username
|
|||
if (callResult) { |
|||
const txObj2 = yield call(contract.methods.getUsername, account); |
|||
dispatchArgs.username = yield call(txObj2.call, { |
|||
address: account, |
|||
}); |
|||
} |
|||
} |
|||
|
|||
yield put({ |
|||
type: USER_DATA_UPDATED, ...dispatchArgs, |
|||
}); |
|||
} catch (error) { |
|||
console.error(error); |
|||
yield put({ type: USER_DATA_ERROR }); |
|||
} |
|||
} |
|||
|
|||
function * userSaga () { |
|||
const res = yield all([ |
|||
take(drizzleActions.drizzle.DRIZZLE_INITIALIZED), |
|||
take(drizzleActions.account.ACCOUNTS_FETCHED) |
|||
]); |
|||
function* userSaga() { |
|||
const res = yield all([ |
|||
take(drizzleActions.drizzle.DRIZZLE_INITIALIZED), |
|||
take(drizzleActions.account.ACCOUNTS_FETCHED), |
|||
]); |
|||
|
|||
yield fetchUserData({drizzle:res[0].drizzle, account: res[1].accounts[0]}); |
|||
yield fetchUserData({ drizzle: res[0].drizzle, account: res[1].accounts[0] }); |
|||
} |
|||
|
|||
export default userSaga |
|||
export default userSaga; |
|||
|
@ -1,24 +1,25 @@ |
|||
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'; |
|||
import { drizzleReducers, drizzleMiddlewares, generateContractsInitialState } from '@ezerous/drizzle'; |
|||
import { breezeReducers } from '@ezerous/breeze' |
|||
import userReducer from './reducers/userReducer' |
|||
import { breezeReducers } from '@ezerous/breeze'; |
|||
import createSagaMiddleware from 'redux-saga'; |
|||
import userReducer from './reducers/userReducer'; |
|||
import rootSaga from './sagas/rootSaga'; |
|||
import drizzleOptions from '../options/drizzleOptions'; |
|||
|
|||
const initialState = { |
|||
contracts: generateContractsInitialState(drizzleOptions), |
|||
contracts: generateContractsInitialState(drizzleOptions), |
|||
}; |
|||
|
|||
const sagaMiddleware = createSagaMiddleware(); |
|||
|
|||
const store = configureStore({ |
|||
reducer: {...drizzleReducers, ...breezeReducers, user: userReducer }, |
|||
middleware: getDefaultMiddleware({ |
|||
serializableCheck: false, //https://redux.js.org/style-guide/style-guide/#do-not-put-non-serializable-values-in-state-or-actions
|
|||
}).concat(drizzleMiddlewares).concat(sagaMiddleware), |
|||
preloadedState: initialState |
|||
}) |
|||
reducer: { ...drizzleReducers, ...breezeReducers, user: userReducer }, |
|||
middleware: getDefaultMiddleware({ |
|||
// https://redux.js.org/style-guide/style-guide/#do-not-put-non-serializable-values-in-state-or-actions
|
|||
serializableCheck: false, |
|||
}).concat(drizzleMiddlewares).concat(sagaMiddleware), |
|||
preloadedState: initialState, |
|||
}); |
|||
|
|||
sagaMiddleware.run(rootSaga); |
|||
export default store; |
|||
|
@ -1,13 +1,13 @@ |
|||
let Forum; |
|||
|
|||
try { |
|||
// eslint-disable-next-line global-require
|
|||
Forum = require('./build/Forum.json'); |
|||
// eslint-disable-next-line global-require
|
|||
Forum = require('./build/Forum.json'); |
|||
} catch (e) { |
|||
// eslint-disable-next-line no-console
|
|||
console.error("Could not require contract artifacts. Haven't you run compile yet?"); |
|||
// eslint-disable-next-line no-console
|
|||
console.error("Could not require contract artifacts. Haven't you run compile yet?"); |
|||
} |
|||
|
|||
module.exports = { |
|||
contracts: [Forum], |
|||
contracts: [Forum], |
|||
}; |
|||
|
Loading…
Reference in new issue