diff --git a/app/src/components/LoadingSpinner.js b/app/src/components/LoadingSpinner.js
new file mode 100644
index 0000000..e863c6b
--- /dev/null
+++ b/app/src/components/LoadingSpinner.js
@@ -0,0 +1,16 @@
+import React from 'react';
+
+const LoadingSpinner = (props) => {
+ return(
+
+ );
+}
+
+export default LoadingSpinner;
\ No newline at end of file
diff --git a/app/src/components/ProfileInformation.js b/app/src/components/ProfileInformation.js
new file mode 100644
index 0000000..c50543b
--- /dev/null
+++ b/app/src/components/ProfileInformation.js
@@ -0,0 +1,153 @@
+import React, { Component } from 'react';
+import { connect } from 'react-redux';
+import { drizzle } from '../index';
+
+import UserAvatar from 'react-user-avatar';
+import epochTimeConverter from '../helpers/EpochTimeConverter';
+
+import UsernameFormContainer from '../containers/UsernameFormContainer';
+
+const callsInfo = [{
+ contract: 'Forum',
+ method: 'getUserDateOfRegister'
+ },{
+ contract: 'Forum',
+ method: 'getOrbitDBId'
+}]
+
+class ProfileInformation extends Component {
+ constructor(props) {
+ super(props);
+
+ this.dataKey = [];
+ var pageStatus = 'initialized';
+ if (this.props.drizzleStatus['initialized']) {
+ callsInfo.forEach((call, index) => {
+ this.dataKey[index] = drizzle.contracts[call.contract]
+ .methods[call.method].cacheCall(this.props.address);
+ })
+ pageStatus = 'loading';
+ }
+ if (this.dataKey.length !== 0) {
+ pageStatus = 'loaded';
+ callsInfo.forEach((call, index) => {
+ if (!this.props.contracts[call.contract][call.method][this.dataKey[index]]) {
+ pageStatus = 'loading';
+ return;
+ }
+ })
+ }
+ if (pageStatus === 'loaded'){
+ var dateOfRegister = '';
+ var orbitDBId = '';
+
+ let transaction = this.props.contracts[callsInfo[0].contract][callsInfo[0].method][this.dataKey[0]];
+ if (transaction){
+ dateOfRegister = transaction.value;
+ }
+ transaction = this.props.contracts[callsInfo[1].contract][callsInfo[1].method][this.dataKey[1]];
+ if (transaction){
+ orbitDBId = transaction.value;
+ }
+ }
+
+ this.state = {
+ pageStatus: pageStatus,
+ dateOfRegister: dateOfRegister ? dateOfRegister : '',
+ orbitDBId: orbitDBId ? orbitDBId : ''
+ };
+ }
+
+ componentDidUpdate(){
+ if (this.state.pageStatus === 'initialized' &&
+ this.props.drizzleStatus['initialized']) {
+ callsInfo.forEach((call, index) => {
+ this.dataKey[index] = drizzle.contracts[call.contract]
+ .methods[call.method].cacheCall(this.props.address);
+ })
+ this.setState({ pageStatus: 'loading' });
+ }
+
+ if (this.state.pageStatus === 'loading') {
+ var pageStatus = 'loaded';
+ callsInfo.forEach((call, index) => {
+ if (!this.props.contracts[call.contract][call.method][this.dataKey[index]]) {
+ pageStatus = 'loading';
+ return;
+ }
+ })
+
+ if (pageStatus === 'loaded') {
+ this.setState({ pageStatus: pageStatus });
+ }
+ }
+
+ if (this.state.pageStatus === 'loaded'){
+ if (this.state.dateOfRegister === ''){
+ let transaction = this.props.contracts[callsInfo[0].contract][callsInfo[0].method][this.dataKey[0]];
+ if (transaction){
+ this.setState({ dateOfRegister: transaction.value });
+ }
+ }
+ if (this.state.orbitDBId === ''){
+ let transaction = this.props.contracts[callsInfo[1].contract][callsInfo[1].method][this.dataKey[1]];
+ if (transaction){
+ this.setState({ orbitDBId: transaction.value });
+ }
+ }
+ }
+ }
+
+ render() {
+ return (
+
+ {this.props.avatarUrl &&
}
+
+
+
+ Username: |
+ {this.props.username} |
+
+
+ Account address: |
+ {this.props.address} |
+
+
+ OrbitDB: |
+ {this.state.orbitDBId} |
+
+
+ Number of topics created: |
+ {this.props.numberOfTopics} |
+
+
+ Number of posts: |
+ {this.props.numberOfPosts} |
+
+ {this.state.dateOfRegister &&
+
+ Member since: |
+ {epochTimeConverter(this.state.dateOfRegister)} |
+
+ }
+
+
+ {this.props.self && }
+
+ );
+ }
+};
+
+const mapStateToProps = state => {
+ return {
+ drizzleStatus: state.drizzleStatus,
+ contracts: state.contracts,
+ user: state.user
+ }
+};
+
+export default connect(mapStateToProps)(ProfileInformation);
diff --git a/app/src/containers/ProfileContainer.js b/app/src/containers/ProfileContainer.js
new file mode 100644
index 0000000..4cd0e4d
--- /dev/null
+++ b/app/src/containers/ProfileContainer.js
@@ -0,0 +1,217 @@
+import React, { Component } from 'react';
+import { bindActionCreators } from 'redux';
+import { push } from 'connected-react-router'
+import { connect } from 'react-redux';
+import { drizzle } from '../index';
+
+import { Tab } from 'semantic-ui-react'
+
+import ProfileInformation from '../components/ProfileInformation';
+import TopicList from '../components/TopicList';
+import PostList from '../components/PostList';
+import LoadingSpinner from '../components/LoadingSpinner';
+import { setNavBarTitle } from '../redux/actions/userInterfaceActions';
+
+const callsInfo = [{
+ contract: 'Forum',
+ method: 'getUsername'
+ },{
+ contract: 'Forum',
+ method: 'getUserTopics'
+ },{
+ contract: 'Forum',
+ method: 'getUserPosts'
+ }
+];
+
+class ProfileContainer extends Component {
+ constructor(props) {
+ super(props);
+
+ this.dataKey = [];
+ var address = this.props.match.params.address
+ ? this.props.match.params.address
+ : this.props.user.address;
+
+ var pageStatus = 'initialized';
+ if (this.props.drizzleStatus['initialized']) {
+ callsInfo.forEach((call, index) => {
+ this.dataKey[index] = drizzle.contracts[call.contract]
+ .methods[call.method].cacheCall(address);
+ })
+ pageStatus = 'loading';
+ }
+ if (this.dataKey.length !== 0) {
+ pageStatus = 'loaded';
+ callsInfo.forEach((call, index) => {
+ if (!this.props.contracts[call.contract][call.method][this.dataKey[index]]) {
+ pageStatus = 'loading';
+ return;
+ }
+ })
+ }
+ if (pageStatus === 'loaded'){
+ var username = '';
+ var topicIDs = null;
+ var postIDs = null;
+
+ let transaction = this.props.contracts[callsInfo[0].contract][callsInfo[0].method][this.dataKey[0]];
+ if (transaction){
+ username = transaction.value;
+ this.props.setNavBarTitle(username);
+ }
+ transaction = this.props.contracts[callsInfo[1].contract][callsInfo[1].method][this.dataKey[1]];
+ if (transaction){
+ topicIDs = transaction.value;
+ }
+ transaction = this.props.contracts[callsInfo[2].contract][callsInfo[2].method][this.dataKey[2]];
+ if (transaction){
+ postIDs = transaction.value;
+ }
+
+ /*this.props.store.dispatch(hideProgressBar());*/
+ }
+
+ this.state = {
+ pageStatus: pageStatus,
+ userAddress: address,
+ username: username ? username : '',
+ topicIDs: topicIDs ? topicIDs : null,
+ postIDs: postIDs ? postIDs : null
+ };
+ }
+
+ componentDidUpdate(){
+ if (this.state.pageStatus === 'initialized' &&
+ this.props.drizzleStatus['initialized']) {
+ callsInfo.forEach((call, index) => {
+ this.dataKey[index] = drizzle.contracts[call.contract]
+ .methods[call.method].cacheCall(this.props.match.params.address);
+ })
+ this.setState({ pageStatus: 'loading' });
+ }
+
+ if (this.state.pageStatus === 'loading') {
+ var pageStatus = 'loaded';
+ callsInfo.forEach((call, index) => {
+ if (!this.props.contracts[call.contract][call.method][this.dataKey[index]]) {
+ pageStatus = 'loading';
+ return;
+ }
+ })
+
+ if (pageStatus === 'loaded') {
+ this.setState({ pageStatus: pageStatus });
+ }
+ }
+
+ if (this.state.pageStatus === 'loaded'){
+ if (this.state.username === ''){
+ let transaction = this.props.contracts[callsInfo[0].contract][callsInfo[0].method][this.dataKey[0]];
+ if (transaction){
+ var username = transaction.value;
+ this.props.setNavBarTitle(username);
+ this.setState({ username: username });
+ }
+ }
+ if (this.state.topicIDs === null){
+ let transaction = this.props.contracts[callsInfo[1].contract][callsInfo[1].method][this.dataKey[1]];
+ if (transaction){
+ this.setState({ topicIDs: transaction.value });
+ }
+ }
+ if (this.state.postIDs === null){
+ let transaction = this.props.contracts[callsInfo[2].contract][callsInfo[2].method][this.dataKey[2]];
+ if (transaction){
+ this.setState({ postIDs: transaction.value });
+ }
+ }
+
+ /*this.props.store.dispatch(hideProgressBar());*/
+ }
+ }
+
+ render() {
+ if (!this.props.user.hasSignedUp) {
+ this.props.navigateTo("/signup");
+ return(null);
+ }
+
+ var infoTab =
+ ();
+ var topicsTab =
+ (
+ {this.state.topicIDs
+ ?
+ :
+ }
+
);
+ var postsTab =
+ (
+ {this.state.postIDs
+ ?
+ :
+ }
+
);
+
+ const profilePanes = [
+ {
+ menuItem: 'INFORMATION',
+ pane: {
+ key: 'INFORMATION',
+ content: (infoTab),
+ },
+ },
+ {
+ menuItem: 'TOPICS',
+ pane: {
+ key: 'TOPICS',
+ content: (topicsTab),
+ },
+ },
+ {
+ menuItem: 'POSTS',
+ pane: {
+ key: 'POSTS',
+ content: (postsTab),
+ },
+ },
+ ]
+
+ return (
+
+
+
+ );
+ }
+
+ componentWillUnmount() {
+ this.props.setNavBarTitle('');
+ }
+}
+
+const mapDispatchToProps = dispatch => bindActionCreators({
+ navigateTo: (location) => push(location),
+ setNavBarTitle: (navBarTitle) => setNavBarTitle(navBarTitle)
+}, dispatch);
+
+const mapStateToProps = state => {
+ return {
+ user: state.user,
+ drizzleStatus: state.drizzleStatus,
+ contracts: state.contracts,
+ orbitDB: state.orbitDB
+ }
+};
+
+export default connect(mapStateToProps, mapDispatchToProps)(ProfileContainer);
diff --git a/app/src/containers/TransactionsMonitorContainer.js b/app/src/containers/TransactionsMonitorContainer.js
index 100b5e5..f8152f8 100644
--- a/app/src/containers/TransactionsMonitorContainer.js
+++ b/app/src/containers/TransactionsMonitorContainer.js
@@ -29,6 +29,10 @@ class RightSideBar extends Component {
this.props.history.push("/profile");
this.handleMessageDismiss(null, index);
break;
+ case 'UsernameUpdated':
+ this.props.history.push("/profile");
+ this.handleMessageDismiss(null, index);
+ break;
case 'TopicCreated':
this.props.history.push("/topic/" +
this.props.transactions[transactionHash].receipt.events.TopicCreated.returnValues.topicID
diff --git a/app/src/containers/UsernameFormContainer.js b/app/src/containers/UsernameFormContainer.js
index 833050a..2fb295d 100644
--- a/app/src/containers/UsernameFormContainer.js
+++ b/app/src/containers/UsernameFormContainer.js
@@ -5,7 +5,7 @@ import { Button, Message, Form, Dimmer, Loader, Header } from 'semantic-ui-react
import { drizzle } from '../index';
import { createDatabases } from '../orbit';
-/*import { updateUsername } from '../redux/actions/transactionsMonitorActions';*/
+import { updateUsername } from '../redux/actions/transactionsActions';
const contract = "Forum";
const checkUsernameTakenMethod = "isUserNameTaken";
@@ -62,8 +62,7 @@ class UsernameFormContainer extends Component {
async completeAction() {
if(this.props.user.hasSignedUp){
- //TODO
- /*this.props.store.dispatch(updateUsername(...[this.state.usernameInput], null));*/
+ this.props.dispatch(updateUsername(...[this.state.usernameInput], null));
} else {
this.setState({ signingUp: true });
const orbitdbInfo = await createDatabases();
@@ -79,13 +78,15 @@ class UsernameFormContainer extends Component {
orbitdbInfo.postsDB
], { from: this.props.account});
}
- /*this.setState({ usernameInput: '' });*/
+ this.setState({ usernameInput: '' });
}
componentDidUpdate() {
if (this.state.signingUp) {
const txHash = this.props.transactionStack[this.stackId];
- if (txHash && this.props.transactions[txHash].status === "error") {
+ if (txHash &&
+ this.props.transactions[txHash] &&
+ this.props.transactions[txHash].status === "error") {
this.setState({signingUp: false});
}
} else {
diff --git a/app/src/router/routes.js b/app/src/router/routes.js
index c15e9f6..f7ed24e 100644
--- a/app/src/router/routes.js
+++ b/app/src/router/routes.js
@@ -5,6 +5,7 @@ import HomeContainer from '../containers/HomeContainer'
import SignUpContainer from '../containers/SignUpContainer'
import StartTopicContainer from '../containers/StartTopicContainer'
import TopicContainer from '../containers/TopicContainer'
+import ProfileContainer from '../containers/ProfileContainer'
import NotFound from '../components/NotFound'
const routes = (
@@ -15,7 +16,8 @@ const routes = (
-
+
+