var React = require('react') var ReactDOM = require('react-dom') var Router = require('react-router').Router var Route = require('react-router').Route var IndexRoute = require('react-router').IndexRoute var Redirect = require('react-router').Redirect var Link = require('react-router').Link var MarkdownLib = require('react-markdown') var moment = require('moment') var sortedIndex = require('lodash.sortedindex') var BoardsAPI = require('../lib/boards-api.js') var opt, s = localStorage.getItem('ipfs-boards-settings') try { opt = JSON.parse(s) } catch(e){ // Do nothing } if(opt === null || opt === undefined) opt = { addr: 'localhost', port: 5001 } var ipfs = require('ipfs-api')(opt.addr || 'localhost',opt.port || 5001) var boards = new BoardsAPI(ipfs) // Components var Markdown = React.createClass({ renderIfApplicable: function(){ if(this.props.source) return return

...

}, render: function(){ return this.renderIfApplicable() } }) var Icon = React.createClass({ class: function(){ return 'fa fa-'+this.props.name+' '+this.props.className }, render: function(){ return ( ) } }) var Container = React.createClass({ render: function(){ return (
{this.props.children}
) } }) var App = React.createClass({ render: function(){ return (
{this.props.children}
) } }) var Navbar = React.createClass({ render: function(){ return (
{this.props.children ||

Boards

}
) } }) var Post = React.createClass({ getDate: function(){ if(this.props.post.date){ return moment.unix(this.props.post.date).fromNow() } else { return 'Unknown Date' } }, render: function(){ return
{this.props.post.title}


{this.getDate()} Comments
} }) var PostList = React.createClass({ getInitialState: function(){ return { posts: [] } }, sortFn: function(a,b){ return (b.date || 0) - (a.date || 0) }, componentDidMount: function(){ console.log('Initial POSTS',this.state.posts.length) boards.getPostsInBoard(this.props.admin,this.props.board) .on('post in '+this.props.board+'@'+this.props.admin,(post,hash) => { if(!this.isMounted()) return true var now = moment().unix() var posts = this.state.posts if(post.date === undefined || post.date <= 0){ posts.push(post) } else if(post.date <= now){ var i = sortedIndex(posts,post,(p) => now-p.date || now) posts.splice(i,0,post) } else { console.log('Post discarded cause date in the future:',post) } this.setState({ posts }) }) }, render: function(){ return (
{this.state.posts.map(post => { return })}
) } }) var UserID = React.createClass({ getInitialState: function(){ return { } }, componentDidMount: function(){ if(this.props.id) boards.getProfile(this.props.id, (err,res) => { if(!this.isMounted()) return true if(!err) { this.setState({ name: res.name.trim() }) } }) }, getContent: function(){ if(this.state.name){ return () } else { return '@' } }, render: function(){ if(this.props.id) return (
{this.getContent()}{this.state.name || this.props.id}
) else return
Unknown User
} }) // Static pages var Homepage = React.createClass({ render: function(){ return (

Welcome to the IPFS Boards Prototype

Not much is implemented...

You can try Opening my Profile though :)

More information about the project on GitHub

) } }) var GetIPFS = React.createClass({ render: function(){ return (

Missing IPFS Node

You don't have an IPFS node running at {opt.addr}:{opt.port} or it is not reachable

The IPFS Boards prototype requires a full IPFS node running at localhost. Please start one by following the go-ipfs documentation.

Do you have a running node but the app won't work?

It's probably one of these issues:

  • Your IPFS node doesn't allow requests from the domain you're running the app from (CORS issue). See here for the fix.
  • Your IPFS node is not listening for API requests at {opt.addr}:{opt.port}. Go to the Settings page, provide the correct address for the node, then save and reload the page.
  • Some other networking issue is preventing the App from talking to your node.

Still can't fix it? File a issue on GitHub, we'll be happy to help!

) } }) var NotFound = React.createClass({ render: function(){ return (

Sorry, there's nothing here!

) } }) var NotImplemented = React.createClass({ render: function(){ return (

Not yet implemented

Sorry, working on it!

) } }) // Dynamic pages var Profile = React.createClass({ getInitialState: function(){ return { name: '...', boards: [] } }, componentDidMount: function(){ console.log('About to ask for profile for',this.props.params.userid) var ee = boards.getEventEmitter() ee.on('boards for '+this.props.params.userid,l => { if(!this.isMounted()) return true this.setState({ boards: l }) }) boards.getProfile(this.props.params.userid,(err,res) => { if(!this.isMounted()) return true if(err){ this.setState({ name: , description: err }) } else { this.setState({ name: res.name, description: res.description }) } }) }, linkToEditor: function(){ if(this.props.params.userid === boards.id){ return
This is your profile

} return '' }, render: function(){ return (
{this.linkToEditor()}

{this.state.name}


@{this.props.params.userid}
{this.state.boards.map(n => { return
# {n.name}
})}
) } }) var Board = React.createClass({ getInitialState: function(){ return { name: this.props.params.boardname } }, componentDidMount: function(){ var ee = boards.getBoardSettings(this.props.params.userid,this.props.params.boardname) ee.on('settings for '+this.props.params.boardname+'@'+this.props.params.userid, (res) => { if(!this.isMounted()) return true console.log('Found name:',res.fullname) this.setState({ name: res.fullname.trim(), description: res.description }) }) }, render: function(){ return (

{this.state.name}

) } }) var Users = React.createClass({ getInitialState: function(){ return { users: boards.getUsers() } }, componentDidMount: function(){ boards.searchUsers().on('user',(id) => { if(this.isMounted() && this.state.users.indexOf(id) < 0) this.setState({ users: this.state.users.concat(id) }) }) }, render: function(){ return

Users

Found {this.state.users.length} users

    {this.state.users.map(user => { return })}
} }) var Settings = React.createClass({ getDefaults: function(){ return { addr: 'localhost', port: 5001 } }, getInitialState: function(){ var s = localStorage.getItem('ipfs-boards-settings') var obj = this.getDefaults() try { obj = JSON.parse(s) } catch(e){ localStorage.removeItem('ipfs-boards-settings') } return obj || this.getDefaults() }, save: function(){ if(isNaN(this.state.port) || parseInt(this.state.port) > 65535 || parseInt(this.state.port) < 1){ alert('Port number invalid') } else { localStorage.setItem('ipfs-boards-settings',JSON.stringify({ addr: this.state.addr, port: parseInt(this.state.port) })) alert('Saved') } }, setDefaults: function(){ this.setState(this.getDefaults()) }, onChange: function(event){ if(event.target.id === 'nodeAddress'){ this.setState({ addr: event.target.value }) } else { this.setState({ port: event.target.value }) } }, render: function(){ return (

Settings

This page is still a little rough, but it works. Reload the page after saving to apply changes.

Use this page to customize the application's behavior. For now, you can change how it connects to IPFS.

All settings are saved in your browser.

) } }) // Start boards.init(err => { if(err){ console.log('FATAL: IPFS NODE NOT AVAILABLE') ReactDOM.render( , document.getElementById('root')) } else { ReactDOM.render( , document.getElementById('root') ) } })