From 5a71c39bb9270ebfa607194f804f431d5fed8868 Mon Sep 17 00:00:00 2001 From: Enrico Fasoli Date: Sat, 14 Nov 2015 16:26:03 +0100 Subject: [PATCH] board viewing is ok now --- PROTOCOL.md | 15 +++++++++++++-- README.md | 21 ++++++++++++--------- lib/boards-api.js | 47 +++++++++++++++++++++++----------------------- webapp/app.jsx | 48 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 89 insertions(+), 42 deletions(-) diff --git a/PROTOCOL.md b/PROTOCOL.md index 2916c25..a172cb1 100644 --- a/PROTOCOL.md +++ b/PROTOCOL.md @@ -37,10 +37,21 @@ publication, containing: - votes - _board name(s)_ - _vote(s)_ - named with their parent object uri -- name - stores the user's screen name (maybe store it in profile?) -- profile.json - user's additional profile data +- profile.json - user's profile data, like name, email, etc - 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 { diff --git a/README.md b/README.md index 38ae72c..989a2d0 100644 --- a/README.md +++ b/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 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 - 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 architecture or, optionally, none of these! @@ -41,20 +43,21 @@ See `FAQ.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) - Advanced customization, control, user profile - Media support - Votes - -Maybe it will have: - -- No backend needed (for read only access) - 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 diff --git a/lib/boards-api.js b/lib/boards-api.js index c62c7d6..3279986 100644 --- a/lib/boards-api.js +++ b/lib/boards-api.js @@ -36,7 +36,7 @@ function replyAsObj(res,isJson,done){ } }) } else { - console.log('got string:',res) + //console.log('got string:',res) // Is a string if(isJson){ asObj(res,done) @@ -55,10 +55,13 @@ function BoardsAPI(ipfs){ } // 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){ var cached = this.users[n] + //console.log('Cached is',cached) if(cached){ - console.log('Returning cached',n,'is',this.users[n]) + //console.log('Returning cached',n,'is',this.users[n]) done(null,cached) } this.ipfs.name.resolve(n,(err,r) => { @@ -66,10 +69,13 @@ BoardsAPI.prototype.resolveIPNS = function(n,done){ if(err){ done(err) } else if(!cached){ + //console.log('oldcache',this.users) + //console.log('Setting cache for',n,'to',r.Path) this.users[n] = r.Path done(err,r.Path) } else if(cached !== r.Path){ // Update cache + //console.log('Setting cache for',n,'from',this.users[n],'to',r.Path) this.users[n] = r.Path } }) @@ -133,7 +139,6 @@ BoardsAPI.prototype.getProfile = function(userID,done){ } else { // Download actual profile this.ipfs.cat(url+'/profile.json',(err2,res) => { - console.log('got something') if(err2){ done(err2,null) } else { @@ -156,43 +161,36 @@ BoardsAPI.prototype.getProfile = function(userID,done){ 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){ - var url = userID+'/boards/'+board+'/settings.json' - console.log('Getting Board Settings:',url) - this.ipfs.cat(url,function(err,res){ - console.log('Done') - if(err){ - done(err,{}) + this.resolveIPNS(userID,(e,r) => { + if(e){ + done(e) } 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){ - var ee = new EventEmitter() /* this.getBoardSettings(administratorID,board,(err,res) => { // NEEDS: board settings structure definition // For now we only list admin's posts }) */ - this.getUserPostListInBoard(adminID,board,(err,res) =>{ + var ee = this.getUserPostListInBoard(adminID,board,(err,res) =>{ if(err){ console.log(err) } else res.forEach(item => { this.ipfs.cat(item.hash,(err2,r) => { - console.log('got something') if(err2){ console.log('Could not download post',item,'of',board+'@'+adminID) } else { @@ -206,6 +204,7 @@ BoardsAPI.prototype.getPostsInBoard = function(adminID,board){ } BoardsAPI.prototype.getUserPostListInBoard = function(user,board,done){ + var ee = new EventEmitter() this.resolveIPNS(user,(err,url) => { if(err){ done(err) @@ -214,6 +213,7 @@ BoardsAPI.prototype.getUserPostListInBoard = function(user,board,done){ done(e) } else if(r && !r.split){ 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 => { 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){ diff --git a/webapp/app.jsx b/webapp/app.jsx index b37f8c4..542945f 100644 --- a/webapp/app.jsx +++ b/webapp/app.jsx @@ -29,9 +29,10 @@ var Homepage = React.createClass({ render: function(){ return (
-

Hello

+

Welcome to the IPFS Boards Prototype

Not much is implemented...

-

You can try Opening a Profile though :)

+

You can try Opening my Profile though :)

+

More information about the project on GitHub

) } @@ -102,8 +103,8 @@ var PostList = React.createClass({ return (
{this.state.posts.map(post => { - return (
-
{post.title}
+ return (
+
{post.title}

{post.text}

) })} @@ -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(){ return (
-

{this.props.params.boardname}

- -
@{this.props.params.userid}
+ +
{this.state.name}
+
) + } +}) + +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 (
+

{this.state.name}

+
) }