mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-03-11 21:38:38 +01:00
implemented writing comments
This commit is contained in:
parent
fb9e3db821
commit
047dad1c4c
@ -207,6 +207,48 @@ BoardsAPI.prototype.createPost = function (post, board, done) {
|
||||
}
|
||||
], done)
|
||||
}
|
||||
BoardsAPI.prototype.createComment = function (comment, parent, done) {
|
||||
try {
|
||||
comment.date = parseInt((new Date()).getTime() / 1000, 10)
|
||||
comment.op = this.id
|
||||
comment.parent = parent
|
||||
var comment_str = JSON.stringify(comment)
|
||||
} catch (e) {
|
||||
console.log('Error, invalid Post:', e)
|
||||
return done(e)
|
||||
}
|
||||
if (!comment.text) return done('empty comment')
|
||||
console.log('Commenting:', comment)
|
||||
var dest = '/ipfs-boards-profile/comments/' + parent + '/' + comment.date + '.json'
|
||||
var commenthash
|
||||
asyncjs.waterfall([
|
||||
// Create required directories
|
||||
cb => this.ipfs.files.mkdir('/ipfs-boards-profile/comments/' + parent + '/', { p: true }, cb),
|
||||
(e, cb) => {
|
||||
// Remove old comment file if present
|
||||
this.ipfs.files.rm(dest, { r: true }, res => cb())
|
||||
},
|
||||
(cb) => {
|
||||
// Serialize comment and add to IPFS
|
||||
this.ipfs.add(new Buffer(comment_str), cb)
|
||||
},
|
||||
(res, cb) => {
|
||||
// Move post into mfs
|
||||
console.log('added Comment to IPFS:', res.Hash)
|
||||
commenthash = res.Hash
|
||||
var spath = '/ipfs/' + res.Hash
|
||||
this.ipfs.files.cp([spath, dest], cb)
|
||||
},
|
||||
(e, cb) => this.ipfs.files.stat('/', cb),
|
||||
(res, cb) => {
|
||||
var profile_hash = res.Hash
|
||||
console.log('Publishing profile...')
|
||||
this.ipfs.name.publish(profile_hash, err => {
|
||||
done(err, commenthash)
|
||||
})
|
||||
}
|
||||
], done)
|
||||
}
|
||||
|
||||
BoardsAPI.prototype.delete = function (opts, done) {
|
||||
var url = '/ipfs-boards-profile/'
|
||||
|
@ -4,6 +4,62 @@ var Icon = require('icon.jsx')
|
||||
var Clock = require('clock.jsx')
|
||||
var Link = require('react-router').Link
|
||||
var UserID = require('userID.jsx')
|
||||
var { Error, Success } = require('status-components.jsx')
|
||||
|
||||
var CommentEditor = React.createClass({
|
||||
getInitialState () {
|
||||
return { }
|
||||
},
|
||||
componentDidMount () {
|
||||
this.init(this.props)
|
||||
},
|
||||
componentWillReceiveProps (props) {
|
||||
this.init(props)
|
||||
},
|
||||
init (props) {
|
||||
this.setState({ api: props.api })
|
||||
},
|
||||
handleChange (event) {
|
||||
var obj = {}
|
||||
obj[event.target.id] = event.target.value
|
||||
this.setState(obj)
|
||||
},
|
||||
save () {
|
||||
var boards = this.props.api
|
||||
var comment = { text: this.state.text }
|
||||
this.setState({ loading: true })
|
||||
boards.createComment(comment, this.props.parent, (err, hash) => {
|
||||
if (err) {
|
||||
this.setState({ loading: false, error: err })
|
||||
} else {
|
||||
this.setState({ loading: false, success: true, hash })
|
||||
}
|
||||
})
|
||||
},
|
||||
render () {
|
||||
if (this.state.error) {
|
||||
return <Error error={this.state.error} />
|
||||
} else if (this.state.loading) {
|
||||
return <div className="center-block text-center find-content">
|
||||
<Icon name="refresh" className="fa-3x center-block light fa-spin" />
|
||||
<h4>Publishing Comment</h4>
|
||||
</div>
|
||||
} else if (this.state.success) {
|
||||
var url = '/@' + this.props.adminID + '/' + this.props.board + '/' + (this.props.post || this.props.parent) + '/' + this.state.hash
|
||||
return <Success title="Comment Published">
|
||||
<Link className="button button-primary" to={url}>View</Link>
|
||||
</Success>
|
||||
} else {
|
||||
return <div>
|
||||
<textarea className="u-full-width" id="text" value={this.state.text} onChange={this.handleChange} placeholder="Speak your mind! Markdown is supported." />
|
||||
<p><b>Note</b>: this version of the app doesn't check wether you are allowed to post on this board, so there are no guarantees that your post will be visible.</p>
|
||||
<div className="buttons">
|
||||
<button className="button button-primary" onClick={this.save}>Send</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
var Comment = React.createClass({
|
||||
getInitialState () {
|
||||
@ -29,7 +85,10 @@ var Comment = React.createClass({
|
||||
}
|
||||
},
|
||||
getComments () {
|
||||
return <Comments className="shifted" parent={this.props.comment.hash} post={this.props.post} adminID={this.props.adminID} board={this.props.board} api={this.props.api} />
|
||||
return <Comments className="shifted" allowReply={this.props.allowReply} parent={this.props.comment.hash} post={this.props.post} adminID={this.props.adminID} board={this.props.board} api={this.props.api} />
|
||||
},
|
||||
toggleReply () {
|
||||
this.setState({ reply: !this.state.reply })
|
||||
},
|
||||
render () {
|
||||
if (this.props.comment) {
|
||||
@ -38,9 +97,15 @@ var Comment = React.createClass({
|
||||
<UserID id={this.props.comment.op} api={this.props.api} />
|
||||
<Clock date={this.props.comment.date} />
|
||||
{this.getPermalink()}
|
||||
{ this.props.allowReply
|
||||
? <a className="nounderline" onClick={this.toggleReply}><Icon className="not-first" name="reply" /> Reply</a>
|
||||
: <a/> }
|
||||
{this.getParentlink()}
|
||||
</div>
|
||||
<Markdown source={this.props.comment.text} />
|
||||
{ this.state.reply
|
||||
? <CommentEditor parent={this.props.comment.hash} post={this.props.post} api={this.props.api} adminID={this.props.adminID} board={this.props.board} />
|
||||
: <div/>}
|
||||
<hr/>{this.getComments()}</div>
|
||||
} else {
|
||||
return <div><hr/>Invalid Comment<hr/></div>
|
||||
@ -56,7 +121,7 @@ var Comments = React.createClass({
|
||||
if (this.props.api) this.init(this.props.api)
|
||||
},
|
||||
componentWillReceiveProps (props) {
|
||||
if (props.api) this.init(props.api)
|
||||
if (props.api !== this.props.api) this.init(props.api)
|
||||
},
|
||||
init (boards) {
|
||||
boards.getEventEmitter().on('comment for ' + this.props.parent, cmnt => {
|
||||
@ -76,7 +141,7 @@ var Comments = React.createClass({
|
||||
},
|
||||
getComments () {
|
||||
if (this.state.comments.length > 0) {
|
||||
return this.state.comments.map(cmnt => (<Comment key={cmnt.hash} comment={cmnt} post={this.props.post} adminID={this.props.adminID} board={this.props.board} api={this.props.api} />))
|
||||
return this.state.comments.map(cmnt => (<Comment allowReply={this.props.allowReply} key={cmnt.hash} comment={cmnt} post={this.props.post} adminID={this.props.adminID} board={this.props.board} api={this.props.api} />))
|
||||
} else return <div></div>
|
||||
},
|
||||
render () {
|
||||
@ -90,4 +155,4 @@ var Comments = React.createClass({
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = { Comment, Comments }
|
||||
module.exports = { Comment, Comments, CommentEditor }
|
||||
|
@ -5,7 +5,7 @@ var Link = require('react-router').Link
|
||||
var Clock = require('clock.jsx')
|
||||
var UserID = require('userID.jsx')
|
||||
var { Error } = require('status-components.jsx')
|
||||
var Comments = require('comment.jsx').Comments
|
||||
var { Comments, CommentEditor } = require('comment.jsx')
|
||||
|
||||
module.exports = React.createClass({
|
||||
getInitialState () {
|
||||
@ -54,6 +54,9 @@ module.exports = React.createClass({
|
||||
}
|
||||
} else return <span/>
|
||||
},
|
||||
toggleReply () {
|
||||
this.setState({ reply: !this.state.reply })
|
||||
},
|
||||
getContent () {
|
||||
if (this.state.error) {
|
||||
return <Error className="content" error={this.state.error} />
|
||||
@ -75,6 +78,9 @@ module.exports = React.createClass({
|
||||
<UserID id={this.state.post.op} api={this.props.api} ></UserID>
|
||||
<Clock className="not-first" date={this.state.post.date} />
|
||||
<Icon name="comments" className="not-first" /> <Link className="nounderline" to={this.postLink()}>View</Link>
|
||||
{ this.props.allowReply
|
||||
? <a className="nounderline" onClick={this.toggleReply}><Icon className="not-first" name="reply" /> Reply</a>
|
||||
: <span/>}
|
||||
{this.editorLink()}
|
||||
</div>
|
||||
</div>
|
||||
@ -83,7 +89,10 @@ module.exports = React.createClass({
|
||||
render () {
|
||||
return <div>
|
||||
<div className="post">{this.getContent()}</div>
|
||||
<Comments parent={this.props.hash} post={this.props.hash} api={this.props.api} adminID={this.props.adminID} board={this.props.board} />
|
||||
{ this.state.reply
|
||||
? <CommentEditor parent={this.props.hash} api={this.props.api} adminID={this.props.adminID} board={this.props.board} />
|
||||
: <div/>}
|
||||
<Comments allowReply={this.props.allowReply} parent={this.props.hash} post={this.props.hash} api={this.props.api} adminID={this.props.adminID} board={this.props.board} />
|
||||
</div>
|
||||
}
|
||||
})
|
||||
|
@ -12,7 +12,6 @@ module.exports = function (boardsAPI) {
|
||||
},
|
||||
componentDidMount: function () {
|
||||
boardsAPI.use(boards => {
|
||||
boards.init()
|
||||
boards.getEventEmitter().on('init', err => {
|
||||
if (!err && this.isMounted()) {
|
||||
this.init(boards)
|
||||
@ -24,7 +23,9 @@ module.exports = function (boardsAPI) {
|
||||
})
|
||||
},
|
||||
componentWillReceiveProps: function (nextProps) {
|
||||
boardsAPI.use(boards => this.downloadComment(boards, nextProps))
|
||||
if (this.props.params !== nextProps.params) {
|
||||
boardsAPI.use(boards => this.downloadComment(boards, nextProps))
|
||||
}
|
||||
},
|
||||
downloadComment: function (boards, props) {
|
||||
this.setState({ comment: false })
|
||||
@ -34,13 +35,18 @@ module.exports = function (boardsAPI) {
|
||||
comment: { title: 'Error', text: err.Message || err.Error }
|
||||
})
|
||||
} else {
|
||||
this.setState({ comment })
|
||||
if (!comment.parent && comment.text) {
|
||||
// Redirect to post page
|
||||
this.props.history.push('/@' + this.props.params.userid + '/' + this.props.params.boardname + '/' + this.props.params.commenthash)
|
||||
} else {
|
||||
this.setState({ comment })
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
init: function (boards) {
|
||||
if (this.state.init) return
|
||||
this.setState({ api: true, boards: boards })
|
||||
this.setState({ api: true, boards, canReply: boards.isInit && !boards.limited })
|
||||
this.downloadComment(boards, this.props)
|
||||
},
|
||||
getContext: function () {
|
||||
@ -54,7 +60,7 @@ module.exports = function (boardsAPI) {
|
||||
},
|
||||
showComment: function () {
|
||||
if (this.state.comment) {
|
||||
return <Comment comment={this.state.comment} post={this.props.params.posthash} adminID={this.props.params.userid} board={this.props.params.boardname} showParent={true} api={this.state.boards} />
|
||||
return <Comment canReply={this.state.canReply} comment={this.state.comment} post={this.props.params.posthash} adminID={this.props.params.userid} board={this.props.params.boardname} showParent={true} api={this.state.boards} />
|
||||
} else {
|
||||
return <div className="center-block text-center find-content">
|
||||
<Icon name="refresh" className="fa-3x center-block light fa-spin" />
|
||||
|
@ -11,7 +11,10 @@ module.exports = function (boardsAPI) {
|
||||
},
|
||||
componentDidMount: function () {
|
||||
boardsAPI.use(boards => {
|
||||
this.setState({ api: boards })
|
||||
this.setState({ api: boards, allowReply: boards.isInit && !boards.limited })
|
||||
boards.getEventEmitter().on('init', (err, limited) => {
|
||||
this.setState({ api: boards, allowReply: !err && !limited })
|
||||
})
|
||||
})
|
||||
},
|
||||
getContext: function () {
|
||||
@ -29,7 +32,7 @@ module.exports = function (boardsAPI) {
|
||||
<div className="text-center">
|
||||
{this.getContext()}
|
||||
</div>
|
||||
<Post hash={this.props.params.posthash} board={this.props.params.boardname} api={this.state.api} adminID={this.props.params.userid} />
|
||||
<Post allowReply={true} hash={this.props.params.posthash} board={this.props.params.boardname} api={this.state.api} adminID={this.props.params.userid} />
|
||||
</div>
|
||||
} else {
|
||||
return <GetIPFS api={this.state.boards} />
|
||||
|
@ -14,6 +14,7 @@ hr {
|
||||
a {
|
||||
text-decoration: underline;
|
||||
color: #ababab;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nounderline {
|
||||
|
Loading…
Reference in New Issue
Block a user