diff --git a/contracts/Forum.sol b/contracts/Forum.sol index acea856..e96b908 100644 --- a/contracts/Forum.sol +++ b/contracts/Forum.sol @@ -55,6 +55,16 @@ contract Forum { return false; } + function getUserTopics(address userAddress) public view returns (uint[]) { + require (hasUserSignedUp(msg.sender), "User hasn't signed up yet."); + return users[userAddress].topicIDs; + } + + function getUserPosts(address userAddress) public view returns (uint[]) { + require (hasUserSignedUp(msg.sender), "User hasn't signed up yet."); + return users[userAddress].postIDs; + } + //----------------------------------------OrbitDB---------------------------------------- struct OrbitDB { string id; // TODO: set an upper bound instead of arbitrary string @@ -115,6 +125,7 @@ contract Forum { uint postID; address author; uint timestamp; + uint topicID; } uint numTopics; // Total number of topics @@ -123,25 +134,33 @@ contract Forum { mapping (uint => Topic) topics; mapping (uint => Post) posts; - event TopicCreated(uint topicID); + event TopicCreated(uint topicID, uint postID); event PostCreated(uint postID, uint topicID); - event NumberOfTopicsReceived(uint numTopics); - event TopicReceived(string orbitTopicsDB, address author, string username, uint timestamp, uint[] postIDs); + /* event NumberOfTopicsReceived(uint numTopics); + event TopicReceived(string orbitTopicsDB, address author, string username, uint timestamp, uint[] postIDs); */ - function createTopic() public returns (uint) { + function createTopic() public returns (uint, uint) { require(hasUserSignedUp(msg.sender)); // Only registered users can create topics + //Creates topic uint topicID = numTopics++; topics[topicID] = Topic(topicID, msg.sender, block.timestamp, new uint[](0)); users[msg.sender].topicIDs.push(topicID); - emit TopicCreated(topicID); - return topicID; + + //Adds first post to topic + uint postID = numPosts++; + posts[postID] = Post(postID, msg.sender, block.timestamp, topicID); + topics[topicID].postIDs.push(postID); + users[msg.sender].postIDs.push(postID); + + emit TopicCreated(topicID, postID); + return (topicID, postID); } function createPost(uint topicID) public returns (uint) { require(hasUserSignedUp(msg.sender)); // Only registered users can create posts require(topicIDdiv { + width: 100%; +} + /* FORMS */ .pure-form { @@ -348,6 +382,12 @@ a { text-align: center; } +.vertical-center-children { + display: flex; + flex-flow: row nowrap; + align-items: flex-start; +} + #overlay { position: fixed; display: block; diff --git a/src/components/LoadingSpinner.js b/src/components/LoadingSpinner.js new file mode 100644 index 0000000..44c035d --- /dev/null +++ b/src/components/LoadingSpinner.js @@ -0,0 +1,14 @@ +import React from 'react'; + +const LoadingSpinner = (props) => { + return( +
+

+ +

+
+ ); +} + +export default LoadingSpinner; \ No newline at end of file diff --git a/src/components/NewPost.js b/src/components/NewPost.js index f5baf3c..77f17fd 100644 --- a/src/components/NewPost.js +++ b/src/components/NewPost.js @@ -1,39 +1,98 @@ -import React, { Component } from 'react'; import { drizzleConnect } from 'drizzle-react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import uuidv4 from 'uuid/v4'; + import UserAvatar from 'react-user-avatar'; import ReactMarkdown from 'react-markdown'; +const contract = "Forum"; +const contractMethod = "createPost"; + class NewPost extends Component { constructor(props, context) { super(props); this.handleInputChange = this.handleInputChange.bind(this); this.handlePreviewToggle = this.handlePreviewToggle.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); + this.validateAndPost = this.validateAndPost.bind(this); + this.pushToDatabase = this.pushToDatabase.bind(this); + + this.transactionProgressText = []; + this.drizzle = context.drizzle; this.state = { - postContent: '', - previewEnabled: false + postSubjectInput: this.props.subject, + postContentInput: '', + postSubjectInputEmptySubmit: false, + postContentInputEmptySubmit: false, + previewEnabled: false, + previewDate: "", + creatingPost: false, + transactionState: null, + savingToOrbitDB: null, + transactionOutputTimerActive: false }; } - async handleSubmit() { - /*this.stackId = this.contracts[contract].methods[startTopicMethod].cacheSend();*/ + async validateAndPost() { + if (this.state.postSubjectInput === '' || this.state.postContentInput === ''){ + this.setState({ + postSubjectInputEmptySubmit: this.state.postSubjectInput === '', + postContentInputEmptySubmit: this.state.postContentInput === '' + }); + return; + } + + this.stackId = this.drizzle.contracts[contract].methods[contractMethod].cacheSend(this.props.topicID); + this.transactionProgressText.push(
); + this.transactionProgressText.push("Waiting for transaction acceptance..."); + this.setState({ + 'creatingPost': true, + 'transactionState': "ACCEPTANCE_PENDING" + }); + } + + async pushToDatabase() { + await this.props.orbitDB.postsDB.put(this.postIDFetched, { + subject: this.state.postSubjectInput, + content: this.state.postContentInput + }); + this.setState({'savingToOrbitDB': "SUCCESS"}); } handleInputChange(event) { this.setState({[event.target.name]: event.target.value}); } - handlePreviewToggle(){ + handlePreviewToggle() { this.setState((prevState, props) => ({ - previewEnabled: !prevState.previewEnabled + previewEnabled: !prevState.previewEnabled, + previewDate: this.getDate() })); } + getDate() { + const currentdate = new Date(); + return ((currentdate.getMonth() + 1) + " " + + currentdate.getDate() + ", " + + currentdate.getFullYear() + ", " + + currentdate.getHours() + ":" + + currentdate.getMinutes() + ":" + + currentdate.getSeconds()); + } + render() { return (
+ {this.state.creatingPost &&
+
+

+
+ {this.transactionProgressText} +
+
+ }

- {this.props.user.username}
Subject: {this.props.subject}
+ {this.props.user.username}
Subject: {this.state.postSubjectInput}

@@ -52,17 +111,27 @@ class NewPost extends Component {
{this.state.previewEnabled - ? - :