mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-01-26 15:04:19 +01:00
board viewing is ok now
This commit is contained in:
parent
0f71407040
commit
5a71c39bb9
15
PROTOCOL.md
15
PROTOCOL.md
@ -37,10 +37,21 @@ publication, containing:
|
|||||||
- votes
|
- votes
|
||||||
- _board name(s)_
|
- _board name(s)_
|
||||||
- _vote(s)_ - named with their parent object uri
|
- _vote(s)_ - named with their parent object uri
|
||||||
- name - stores the user's screen name (maybe store it in profile?)
|
- profile.json - user's profile data, like name, email, etc
|
||||||
- profile.json - user's additional profile data
|
|
||||||
- ipfs-boards-version.txt - used to store compatibility information
|
- ipfs-boards-version.txt - used to store compatibility information
|
||||||
|
|
||||||
|
#### Board settings
|
||||||
|
|
||||||
|
{
|
||||||
|
"whitelist": true,
|
||||||
|
"blacklist": false,
|
||||||
|
"approval_required": true,
|
||||||
|
"fullname": "The Full Name Can Be Long With Spaces",
|
||||||
|
"description": "A very Long Full Description with Spaces"
|
||||||
|
}
|
||||||
|
|
||||||
|
The blacklist and whitelist should contain just IDs separated by spaces.
|
||||||
|
|
||||||
#### Post
|
#### Post
|
||||||
|
|
||||||
{
|
{
|
||||||
|
21
README.md
21
README.md
@ -25,10 +25,12 @@ Image and discussion boards, forums and the like have many problems:
|
|||||||
This project was conceived to solve that. With the help of modern web technologies, the IPFS and IPNS protocols
|
This project was conceived to solve that. With the help of modern web technologies, the IPFS and IPNS protocols
|
||||||
and some optional cache servers, we can solve these problems and create a true universal platform which can act as:
|
and some optional cache servers, we can solve these problems and create a true universal platform which can act as:
|
||||||
|
|
||||||
- Discussion board
|
- Discussion board, like reddit or 4chan
|
||||||
|
- Blog with dynamic comments
|
||||||
- Wiki
|
- Wiki
|
||||||
- File Sharing platform
|
- File Sharing platform
|
||||||
- E-Learning platform
|
- (Maybe) Forum (not sure because it would require some changes, but maybe)
|
||||||
|
- (Maybe) E-Learning platform
|
||||||
|
|
||||||
With security, control, reliability, rock solid stability, fully distributed
|
With security, control, reliability, rock solid stability, fully distributed
|
||||||
architecture or, optionally, none of these!
|
architecture or, optionally, none of these!
|
||||||
@ -41,20 +43,21 @@ See `FAQ.md`
|
|||||||
|
|
||||||
See `PROTOCOL.md`
|
See `PROTOCOL.md`
|
||||||
|
|
||||||
## Prototype
|
## Demo / Prototype
|
||||||
|
|
||||||
It's being worked on, but it doesn't have:
|
It's being worked on, but __it doesn't have__:
|
||||||
|
|
||||||
- Write ability in web app (only a small cli to validate and publish a folder)
|
- Read only web app (only a small cli to publish stuff, without a comfortable UI)
|
||||||
- Aggregation (only the admin can post)
|
- Aggregation (only the admin can post)
|
||||||
- Advanced customization, control, user profile
|
- Advanced customization, control, user profile
|
||||||
- Media support
|
- Media support
|
||||||
- Votes
|
- Votes
|
||||||
|
|
||||||
Maybe it will have:
|
|
||||||
|
|
||||||
- No backend needed (for read only access)
|
|
||||||
- Comments
|
- Comments
|
||||||
|
- Actually nice user interface
|
||||||
|
|
||||||
|
Ability to publish stuff in the browser won't be implemented until go-ipfs 0.4
|
||||||
|
is ready. It will probably be ready before the new year, but we're not sure.
|
||||||
|
You will be able to publish your blog/pages/profile using a CLI though
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ function replyAsObj(res,isJson,done){
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log('got string:',res)
|
//console.log('got string:',res)
|
||||||
// Is a string
|
// Is a string
|
||||||
if(isJson){
|
if(isJson){
|
||||||
asObj(res,done)
|
asObj(res,done)
|
||||||
@ -55,10 +55,13 @@ function BoardsAPI(ipfs){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This function works but needs a little rethinking.
|
// This function works but needs a little rethinking.
|
||||||
|
// TODO: convert it to emitters and periodically check. Emit events if the IPNS updates
|
||||||
|
// TODO: this SUCKS and is SLOW. NEEDS TO BE FIXED
|
||||||
BoardsAPI.prototype.resolveIPNS = function(n,done){
|
BoardsAPI.prototype.resolveIPNS = function(n,done){
|
||||||
var cached = this.users[n]
|
var cached = this.users[n]
|
||||||
|
//console.log('Cached is',cached)
|
||||||
if(cached){
|
if(cached){
|
||||||
console.log('Returning cached',n,'is',this.users[n])
|
//console.log('Returning cached',n,'is',this.users[n])
|
||||||
done(null,cached)
|
done(null,cached)
|
||||||
}
|
}
|
||||||
this.ipfs.name.resolve(n,(err,r) => {
|
this.ipfs.name.resolve(n,(err,r) => {
|
||||||
@ -66,10 +69,13 @@ BoardsAPI.prototype.resolveIPNS = function(n,done){
|
|||||||
if(err){
|
if(err){
|
||||||
done(err)
|
done(err)
|
||||||
} else if(!cached){
|
} else if(!cached){
|
||||||
|
//console.log('oldcache',this.users)
|
||||||
|
//console.log('Setting cache for',n,'to',r.Path)
|
||||||
this.users[n] = r.Path
|
this.users[n] = r.Path
|
||||||
done(err,r.Path)
|
done(err,r.Path)
|
||||||
} else if(cached !== r.Path){
|
} else if(cached !== r.Path){
|
||||||
// Update cache
|
// Update cache
|
||||||
|
//console.log('Setting cache for',n,'from',this.users[n],'to',r.Path)
|
||||||
this.users[n] = r.Path
|
this.users[n] = r.Path
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -133,7 +139,6 @@ BoardsAPI.prototype.getProfile = function(userID,done){
|
|||||||
} else {
|
} else {
|
||||||
// Download actual profile
|
// Download actual profile
|
||||||
this.ipfs.cat(url+'/profile.json',(err2,res) => {
|
this.ipfs.cat(url+'/profile.json',(err2,res) => {
|
||||||
console.log('got something')
|
|
||||||
if(err2){
|
if(err2){
|
||||||
done(err2,null)
|
done(err2,null)
|
||||||
} else {
|
} else {
|
||||||
@ -156,43 +161,36 @@ BoardsAPI.prototype.getProfile = function(userID,done){
|
|||||||
return ee
|
return ee
|
||||||
}
|
}
|
||||||
|
|
||||||
BoardsAPI.prototype.getName = function(userID,done){
|
|
||||||
this.ipfs.cat(userID+'/name',(err,res) => {
|
|
||||||
if(err){
|
|
||||||
done(err,null)
|
|
||||||
} else {
|
|
||||||
replyAsObj(res,false,done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
BoardsAPI.prototype.getBoardSettings = function(userID,board,done){
|
BoardsAPI.prototype.getBoardSettings = function(userID,board,done){
|
||||||
var url = userID+'/boards/'+board+'/settings.json'
|
this.resolveIPNS(userID,(e,r) => {
|
||||||
console.log('Getting Board Settings:',url)
|
if(e){
|
||||||
this.ipfs.cat(url,function(err,res){
|
done(e)
|
||||||
console.log('Done')
|
|
||||||
if(err){
|
|
||||||
done(err,{})
|
|
||||||
} else {
|
} else {
|
||||||
replyAsObj(res,true,done)
|
var url = r+'/boards/'+board+'/settings.json'
|
||||||
|
this.ipfs.cat(url,(err,res) => {
|
||||||
|
if(err){
|
||||||
|
done(err)
|
||||||
|
} else {
|
||||||
|
// It's already json...
|
||||||
|
done(err,res)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
BoardsAPI.prototype.getPostsInBoard = function(adminID,board){
|
BoardsAPI.prototype.getPostsInBoard = function(adminID,board){
|
||||||
var ee = new EventEmitter()
|
|
||||||
/*
|
/*
|
||||||
this.getBoardSettings(administratorID,board,(err,res) => {
|
this.getBoardSettings(administratorID,board,(err,res) => {
|
||||||
// NEEDS: board settings structure definition
|
// NEEDS: board settings structure definition
|
||||||
// For now we only list admin's posts
|
// For now we only list admin's posts
|
||||||
})
|
})
|
||||||
*/
|
*/
|
||||||
this.getUserPostListInBoard(adminID,board,(err,res) =>{
|
var ee = this.getUserPostListInBoard(adminID,board,(err,res) =>{
|
||||||
if(err){
|
if(err){
|
||||||
console.log(err)
|
console.log(err)
|
||||||
} else res.forEach(item => {
|
} else res.forEach(item => {
|
||||||
this.ipfs.cat(item.hash,(err2,r) => {
|
this.ipfs.cat(item.hash,(err2,r) => {
|
||||||
console.log('got something')
|
|
||||||
if(err2){
|
if(err2){
|
||||||
console.log('Could not download post',item,'of',board+'@'+adminID)
|
console.log('Could not download post',item,'of',board+'@'+adminID)
|
||||||
} else {
|
} else {
|
||||||
@ -206,6 +204,7 @@ BoardsAPI.prototype.getPostsInBoard = function(adminID,board){
|
|||||||
}
|
}
|
||||||
|
|
||||||
BoardsAPI.prototype.getUserPostListInBoard = function(user,board,done){
|
BoardsAPI.prototype.getUserPostListInBoard = function(user,board,done){
|
||||||
|
var ee = new EventEmitter()
|
||||||
this.resolveIPNS(user,(err,url) => {
|
this.resolveIPNS(user,(err,url) => {
|
||||||
if(err){
|
if(err){
|
||||||
done(err)
|
done(err)
|
||||||
@ -214,6 +213,7 @@ BoardsAPI.prototype.getUserPostListInBoard = function(user,board,done){
|
|||||||
done(e)
|
done(e)
|
||||||
} else if(r && !r.split){
|
} else if(r && !r.split){
|
||||||
console.log('Found',r.Objects[0].Links.length,'posts in',board,'at',user)
|
console.log('Found',r.Objects[0].Links.length,'posts in',board,'at',user)
|
||||||
|
ee.emit('post count',board,user,r.Objects[0].Links.length)
|
||||||
var l = r.Objects[0].Links.map(i => {
|
var l = r.Objects[0].Links.map(i => {
|
||||||
return { date: i.Name, hash: i.Hash }
|
return { date: i.Name, hash: i.Hash }
|
||||||
})
|
})
|
||||||
@ -221,6 +221,7 @@ BoardsAPI.prototype.getUserPostListInBoard = function(user,board,done){
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
return ee
|
||||||
}
|
}
|
||||||
|
|
||||||
BoardsAPI.prototype.getCommentsFor = function(parent,done){
|
BoardsAPI.prototype.getCommentsFor = function(parent,done){
|
||||||
|
@ -29,9 +29,10 @@ var Homepage = React.createClass({
|
|||||||
render: function(){
|
render: function(){
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3>Hello</h3>
|
<h3>Welcome to the IPFS Boards Prototype</h3>
|
||||||
<p>Not much is implemented...</p>
|
<p>Not much is implemented...</p>
|
||||||
<p>You can try <Link to="@QmXnfA41SXMX3tqFD4kjED7ehyvgTsuAho86TkEoTbZdpw">Opening a Profile</Link> though :)</p>
|
<p>You can try <Link to="@QmXnfA41SXMX3tqFD4kjED7ehyvgTsuAho86TkEoTbZdpw">Opening my Profile</Link> though :)</p>
|
||||||
|
<p>More information about the project on <a href="https://github.com/fazo96/ipfs-board">GitHub</a></p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -102,8 +103,8 @@ var PostList = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div className="postList">
|
<div className="postList">
|
||||||
{this.state.posts.map(post => {
|
{this.state.posts.map(post => {
|
||||||
return (<div className="post">
|
return (<div key={post.title} className="post">
|
||||||
<h5 key={post.title}>{post.title}</h5>
|
<h5>{post.title}</h5>
|
||||||
<p>{post.text}</p>
|
<p>{post.text}</p>
|
||||||
</div>)
|
</div>)
|
||||||
})}
|
})}
|
||||||
@ -112,13 +113,44 @@ var PostList = React.createClass({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
var Board = React.createClass({
|
var UserID = React.createClass({
|
||||||
|
getInitialState: function(){
|
||||||
|
return { name: '@'+this.props.id }
|
||||||
|
},
|
||||||
|
componentDidMount: function(){
|
||||||
|
boards.getProfile(this.props.id, (err,res) => {
|
||||||
|
if(!err) {
|
||||||
|
this.setState({ name: '@'+res.name.trim() })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
render: function(){
|
render: function(){
|
||||||
return (<div className="board">
|
return (<div className="board">
|
||||||
<h2>{this.props.params.boardname}</h2>
|
<Link to={'/@'+this.props.id}>
|
||||||
<Link to={'/@'+this.props.params.userid}>
|
<h5 className="light">{this.state.name}</h5>
|
||||||
<h5 className="light">@{this.props.params.userid}</h5>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var Board = React.createClass({
|
||||||
|
getInitialState: function(){
|
||||||
|
return { name: '# '+this.props.params.boardname }
|
||||||
|
},
|
||||||
|
componentDidMount: function(){
|
||||||
|
boards.getBoardSettings(this.props.params.userid,this.props.params.boardname, (err,res) => {
|
||||||
|
if(err) {
|
||||||
|
console.log('Huh? Invalid board settings?',err)
|
||||||
|
} else {
|
||||||
|
console.log('Found name:',res.fullname)
|
||||||
|
this.setState({ name: '# '+res.fullname.trim() })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
return (<div className="board">
|
||||||
|
<h2>{this.state.name}</h2>
|
||||||
|
<UserID id={this.props.params.userid} />
|
||||||
<PostList board={this.props.params.boardname} admin={this.props.params.userid}/>
|
<PostList board={this.props.params.boardname} admin={this.props.params.userid}/>
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user