Browse Source

Layout init

develop
Ezerous 4 years ago
parent
commit
bf743631c0
  1. 44
      packages/concordia-app/package.json
  2. 0
      packages/concordia-app/patches/web3-eth+1.3.0.patch
  3. 3
      packages/concordia-app/src/assets/css/app.css
  4. 1
      packages/concordia-app/src/assets/css/loading-component.css
  5. 19
      packages/concordia-app/src/components/App.jsx
  6. 19
      packages/concordia-app/src/components/CoreLayoutContainer.jsx
  7. 9
      packages/concordia-app/src/components/HomeContainer.jsx
  8. 15
      packages/concordia-app/src/components/LoadingContainer.jsx
  9. 38
      packages/concordia-app/src/components/MenuComponent.jsx
  10. 139
      packages/concordia-app/src/components/SignUpForm.jsx
  11. 10
      packages/concordia-app/src/options/breezeOptions.js
  12. 2
      packages/concordia-app/src/redux/actions/userActions.js
  13. 31
      packages/concordia-app/src/redux/reducers/userReducer.js
  14. 5
      packages/concordia-app/src/redux/sagas/orbitSaga.js
  15. 4
      packages/concordia-app/src/redux/sagas/rootSaga.js
  16. 42
      packages/concordia-app/src/redux/sagas/userSaga.js
  17. 7
      packages/concordia-app/src/redux/store.js
  18. 2
      packages/concordia-contracts/contracts/Forum.sol
  19. 6
      packages/concordia-contracts/package.json
  20. 12
      packages/concordia-rendezvous/package.json
  21. 4490
      yarn.lock

44
packages/concordia-app/package.json

@ -8,8 +8,7 @@
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"postinstall": "patch-package", "postinstall": "patch-package",
"analyze": "source-map-explorer 'build/static/js/*.js'", "analyze": "source-map-explorer 'build/static/js/*.js'"
"rendezvous": "star-signal --port=9090 --host=127.0.0.1"
}, },
"eslintConfig": { "eslintConfig": {
"extends": "react-app" "extends": "react-app"
@ -27,28 +26,27 @@
] ]
}, },
"dependencies": { "dependencies": {
"@ezerous/breeze": "0.1.1", "@ezerous/breeze": "~0.2.0",
"@ezerous/drizzle": "0.3.0", "@ezerous/drizzle": "~0.4.0",
"@reduxjs/toolkit": "1.4.0", "@reduxjs/toolkit": "~1.4.0",
"concordia-contracts": "0.1.0", "concordia-contracts": "~0.1.0",
"level": "6.0.1", "level": "~6.0.1",
"orbit-db-identity-provider": "0.3.1", "orbit-db-identity-provider": "~0.3.1",
"prop-types": "15.7.2", "prop-types": "~15.7.2",
"react": "16.13.1", "react": "~16.13.1",
"react-dom": "16.13.1", "react-dom": "~16.13.1",
"react-redux": "7.2.1", "react-redux": "~7.2.1",
"react-router": "5.2.0", "react-router": "~5.2.0",
"react-router-dom": "5.2.0", "react-router-dom": "~5.2.0",
"react-scripts": "3.4.3", "react-scripts": "~3.4.3",
"redux-saga": "1.1.3", "redux-saga": "~1.1.3",
"semantic-ui-css": "^2.4.1", "semantic-ui-css": "~2.4.1",
"semantic-ui-react": "^1.2.1", "semantic-ui-react": "~1.2.1",
"web3": "1.2.11" "web3": "1.3.0"
}, },
"devDependencies": { "devDependencies": {
"libp2p-webrtc-star": "0.20.0", "patch-package": "~6.2.2",
"patch-package": "6.2.2", "postinstall-postinstall": "~2.1.0",
"postinstall-postinstall": "2.1.0", "source-map-explorer": "~2.5.0"
"source-map-explorer": "2.5.0"
} }
} }

0
packages/concordia-app/patches/web3-eth+1.2.11.patch → packages/concordia-app/patches/web3-eth+1.3.0.patch

3
packages/concordia-app/src/assets/css/app.css

@ -0,0 +1,3 @@
body {
margin: 1em !important;
}

1
packages/concordia-app/src/assets/css/loading-component.css

@ -7,6 +7,7 @@ ul {
} }
.loading-screen { .loading-screen {
margin-top: 10em;
text-align: center; text-align: center;
font-size: large; font-size: large;
} }

19
packages/concordia-app/src/components/App.jsx

@ -4,18 +4,25 @@ import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import LoadingContainer from './LoadingContainer' import LoadingContainer from './LoadingContainer'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import 'semantic-ui-css/semantic.min.css' // CSS
import '../assets/css/app.css';
import CoreLayoutContainer from './CoreLayoutContainer';
import HomeContainer from './HomeContainer';
import NotFound from '../components/NotFound'; import NotFound from '../components/NotFound';
const App = ({ store }) => ( const App = ({ store }) => (
<Provider store={store}> <Provider store={store}>
<LoadingContainer> <LoadingContainer>
<Router> <Router>
<Switch> <CoreLayoutContainer>
<Route component={NotFound} /> <Switch>
</Switch> <Route exact path="/" component={HomeContainer} />
</Router> <Route component={NotFound} />
</Switch>
</CoreLayoutContainer>
</Router>
</LoadingContainer> </LoadingContainer>
</Provider> </Provider>
) )

19
packages/concordia-app/src/components/CoreLayoutContainer.jsx

@ -0,0 +1,19 @@
import React, { Component } 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>
)
}
}
CoreLayout.propTypes = {
children: PropTypes.element.isRequired
};

9
packages/concordia-app/src/components/HomeContainer.jsx

@ -0,0 +1,9 @@
import React, { Component } from 'react';
class HomeContainer extends Component {
render() {
return(<p>TODO: Home Container</p>);
}
}
export default HomeContainer;

15
packages/concordia-app/src/components/LoadingContainer.jsx

@ -1,6 +1,5 @@
import React, { Children, Component } from 'react'; import React, { Children, Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Container, Progress } from 'semantic-ui-react'
import { breezeConstants } from '@ezerous/breeze' import { breezeConstants } from '@ezerous/breeze'
@ -9,19 +8,13 @@ import LoadingComponent from './LoadingComponent';
// CSS // CSS
import '../assets/css/loading-component.css'; import '../assets/css/loading-component.css';
// Images
import ethereum_logo from '../assets/images/ethereum_logo.svg';
import ipfs_logo from '../assets/images/ipfs_logo.svg';
import orbitdb_logo from '../assets/images/orbitdb_logo.png';
import logo from '../assets/images/app_logo.png';
class LoadingContainer extends Component { class LoadingContainer extends Component {
render() { render() {
if ((this.props.web3.status === 'initializing' || !this.props.web3.networkId) if ((this.props.web3.status === 'initializing' || !this.props.web3.networkId)
&& !this.props.web3.networkFailed) { && !this.props.web3.networkFailed) {
return <LoadingComponent return <LoadingComponent
title="Connecting to the Ethereum network..." title="Connecting to the Ethereum network..."
message="Please make sure to unlock MetaMask." message="Please make sure to unlock MetaMask and grant the app the right to connect to your account."
image_type="ethereum" image_type="ethereum"
progress={20} progress={20}
progress_type="indicating" progress_type="indicating"
@ -114,14 +107,13 @@ class LoadingContainer extends Component {
/> />
} }
// Just in case our redux logic changes in the future if (!this.props.userFetched){
if (!this.props.drizzleStatus.initialized){
return <LoadingComponent return <LoadingComponent
title="Loading dapp..." title="Loading dapp..."
message="" message=""
image_type="app" image_type="app"
progress={90} progress={90}
progress_type="error" progress_type="indicating"
/> />
} }
@ -138,6 +130,7 @@ const mapStateToProps = (state) => ({
accounts: state.accounts, accounts: state.accounts,
contractInitialized: state.contracts.Forum.initialized, contractInitialized: state.contracts.Forum.initialized,
contractDeployed: state.contracts.Forum.deployed, contractDeployed: state.contracts.Forum.deployed,
userFetched: state.user.address
}); });
export default connect(mapStateToProps)(LoadingContainer); export default connect(mapStateToProps)(LoadingContainer);

38
packages/concordia-app/src/components/MenuComponent.jsx

@ -0,0 +1,38 @@
import React, { Component } from 'react';
import { withRouter } from "react-router";
import { Menu } from 'semantic-ui-react';
import AppContext from "./AppContext";
import app_logo 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>
<SignUpForm/>
</Menu>
</div>
)
}
}
</AppContext.Consumer>
)
}
}
export default withRouter(MenuComponent);

139
packages/concordia-app/src/components/SignUpForm.jsx

@ -0,0 +1,139 @@
import React, { Component } from 'react';
import { Button, Form, Menu, Message, Modal } from 'semantic-ui-react';
import AppContext from "./AppContext";
import { connect } from 'react-redux';
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,
};
}
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();
}
}
componentDidUpdate() {
// TODO
}
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: '',
});
}
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}
/>
<Button type="submit" color="black" content="Sign Up" />
</Modal.Content>
</Modal>
)
}
}
SignUpForm.contextType = AppContext.Context;
const mapStateToProps = (state) => ({
user: state.user
});
export default connect(mapStateToProps)(SignUpForm);

10
packages/concordia-app/src/options/breezeOptions.js

@ -1,6 +1,6 @@
import web3Options from './web3Options'; import web3Options from './web3Options';
import EthereumIdentityProvider from '../orbit/ΕthereumIdentityProvider'; import EthereumIdentityProvider from '../orbit/ΕthereumIdentityProvider';
import {orbitTypes} from '@ezerous/breeze' import { orbitConstants } from '@ezerous/breeze'
const { web3 } = web3Options; const { web3 } = web3Options;
EthereumIdentityProvider.setWeb3(web3); EthereumIdentityProvider.setWeb3(web3);
@ -13,6 +13,10 @@ const breezeOptions = {
// Use local signaling server (see also rendezvous script in package.json) // Use local signaling server (see also rendezvous script in package.json)
// For more information: https://github.com/libp2p/js-libp2p-webrtc-star // For more information: https://github.com/libp2p/js-libp2p-webrtc-star
'/ip4/127.0.0.1/tcp/9090/wss/p2p-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'
] ]
}, },
}, },
@ -28,11 +32,11 @@ const breezeOptions = {
databases: [ databases: [
{ {
name: 'topics', name: 'topics',
type: orbitTypes.ORBIT_TYPE_KEYVALUE type: orbitConstants.ORBIT_TYPE_KEYVALUE
}, },
{ {
name: 'posts', name: 'posts',
type: orbitTypes.ORBIT_TYPE_KEYVALUE type: orbitConstants.ORBIT_TYPE_KEYVALUE
} }
] ]
} }

2
packages/concordia-app/src/redux/actions/userActions.js

@ -0,0 +1,2 @@
export const USER_DATA_UPDATED = 'USER_DATA_UPDATED';
export const USER_DATA_ERROR = 'USER_DATA_ERROR';

31
packages/concordia-app/src/redux/reducers/userReducer.js

@ -0,0 +1,31 @@
import { USER_DATA_UPDATED } from '../actions/userActions';
const initialState = {
username: '',
address: null,
hasSignedUp: false,
};
const userReducer = (state = initialState, 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,
};
}
return state;
};
export default userReducer;

5
packages/concordia-app/src/redux/sagas/orbitSaga.js

@ -3,17 +3,16 @@ import { put, all, take } from 'redux-saga/effects'
import { breezeActions } from '@ezerous/breeze' import { breezeActions } from '@ezerous/breeze'
import { drizzleActions } from '@ezerous/drizzle' import { drizzleActions } from '@ezerous/drizzle'
export function * initOrbitDatabases (action) { function * initOrbitDatabases (action) {
const { account, breeze} = action; const { account, breeze} = action;
yield put(breezeActions.orbit.orbitInit(breeze, account)); //same as breeze.initOrbit(account); yield put(breezeActions.orbit.orbitInit(breeze, account)); //same as breeze.initOrbit(account);
} }
function * orbitSaga () { function * orbitSaga () {
// Not sure which will come first
const res = yield all([ const res = yield all([
take(drizzleActions.drizzle.DRIZZLE_INITIALIZED), take(drizzleActions.drizzle.DRIZZLE_INITIALIZED),
take(breezeActions.breeze.BREEZE_INITIALIZED), take(breezeActions.breeze.BREEZE_INITIALIZED),
take(action => action.type === drizzleActions.account.ACCOUNTS_FETCHED) 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]});

4
packages/concordia-app/src/redux/sagas/rootSaga.js

@ -2,12 +2,14 @@ import { all, fork } from 'redux-saga/effects';
import { drizzleSagas } from '@ezerous/drizzle'; import { drizzleSagas } from '@ezerous/drizzle';
import { breezeSagas } from '@ezerous/breeze' import { breezeSagas } from '@ezerous/breeze'
import orbitSaga from './orbitSaga' import orbitSaga from './orbitSaga'
import userSaga from './userSaga'
export default function* root() { export default function* root() {
const sagas = [ const sagas = [
...drizzleSagas, ...drizzleSagas,
...breezeSagas, ...breezeSagas,
orbitSaga orbitSaga,
userSaga
]; ];
yield all( yield all(
sagas.map((saga) => fork(saga)), sagas.map((saga) => fork(saga)),

42
packages/concordia-app/src/redux/sagas/userSaga.js

@ -0,0 +1,42 @@
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 * 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]});
}
export default userSaga

7
packages/concordia-app/src/redux/store.js

@ -1,6 +1,7 @@
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'; import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import { drizzleReducers, drizzleMiddlewares, generateContractsInitialState } from '@ezerous/drizzle'; import { drizzleReducers, drizzleMiddlewares, generateContractsInitialState } from '@ezerous/drizzle';
import { breezeReducers, breezeMiddlewares } from '@ezerous/breeze' import { breezeReducers } from '@ezerous/breeze'
import userReducer from './reducers/userReducer'
import createSagaMiddleware from 'redux-saga'; import createSagaMiddleware from 'redux-saga';
import rootSaga from './sagas/rootSaga'; import rootSaga from './sagas/rootSaga';
import drizzleOptions from '../options/drizzleOptions'; import drizzleOptions from '../options/drizzleOptions';
@ -12,10 +13,10 @@ const initialState = {
const sagaMiddleware = createSagaMiddleware(); const sagaMiddleware = createSagaMiddleware();
const store = configureStore({ const store = configureStore({
reducer: {...drizzleReducers, ...breezeReducers }, reducer: {...drizzleReducers, ...breezeReducers, user: userReducer },
middleware: getDefaultMiddleware({ middleware: getDefaultMiddleware({
serializableCheck: false, //https://redux.js.org/style-guide/style-guide/#do-not-put-non-serializable-values-in-state-or-actions serializableCheck: false, //https://redux.js.org/style-guide/style-guide/#do-not-put-non-serializable-values-in-state-or-actions
}).concat(drizzleMiddlewares).concat(breezeMiddlewares).concat(sagaMiddleware), }).concat(drizzleMiddlewares).concat(sagaMiddleware),
preloadedState: initialState preloadedState: initialState
}) })

2
packages/concordia-contracts/contracts/Forum.sol

@ -131,7 +131,6 @@ contract Forum {
} }
function getTopic(uint topicID) public view returns (address, string memory, uint, uint[] memory) { function getTopic(uint topicID) public view returns (address, string memory, uint, uint[] memory) {
//TODO: require(hasUserSignedUp(msg.sender)); needed?
require(topicID<numTopics); require(topicID<numTopics);
return ( return (
topics[topicID].author, topics[topicID].author,
@ -147,7 +146,6 @@ contract Forum {
} }
function getPost(uint postID) public view returns (address, string memory, uint, uint) { function getPost(uint postID) public view returns (address, string memory, uint, uint) {
//TODO: require(hasUserSignedUp(msg.sender)); needed?
require(postID<numPosts); require(postID<numPosts);
return ( return (
posts[postID].author, posts[postID].author,

6
packages/concordia-contracts/package.json

@ -13,10 +13,10 @@
"migrate": "yarn truffle migrate --network develop" "migrate": "yarn truffle migrate --network develop"
}, },
"dependencies": { "dependencies": {
"@openzeppelin/contracts": "3.1.0", "@openzeppelin/contracts": "~3.2.0",
"truffle": "5.1.43" "truffle": "~5.1.45"
}, },
"devDependencies": { "devDependencies": {
"solhint": "3.2.0" "solhint": "~3.2.0"
} }
} }

12
packages/concordia-rendezvous/package.json

@ -0,0 +1,12 @@
{
"name": "concordia-rendezvous",
"version": "0.1.0",
"private": true,
"description": "Rendezvous server for Concordia",
"scripts": {
"rendezvous": "star-signal --port=9090 --host=127.0.0.1"
},
"devDependencies": {
"libp2p-webrtc-star": "~0.20.1"
}
}

4490
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save