mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-03-29 00:08:39 +01:00
split app into components
This commit is contained in:
parent
fecd9af666
commit
d77c13f544
278
webapp/app.jsx
278
webapp/app.jsx
@ -5,10 +5,6 @@ var Route = require('react-router').Route
|
|||||||
var IndexRoute = require('react-router').IndexRoute
|
var IndexRoute = require('react-router').IndexRoute
|
||||||
var Redirect = require('react-router').Redirect
|
var Redirect = require('react-router').Redirect
|
||||||
var Link = require('react-router').Link
|
var Link = require('react-router').Link
|
||||||
|
|
||||||
var MarkdownLib = require('react-markdown')
|
|
||||||
var moment = require('moment')
|
|
||||||
var sortedIndex = require('lodash.sortedindex')
|
|
||||||
var BoardsAPI = require('boards-api.js')
|
var BoardsAPI = require('boards-api.js')
|
||||||
|
|
||||||
// Load CSS
|
// Load CSS
|
||||||
@ -30,26 +26,6 @@ var boards = new BoardsAPI(ipfs)
|
|||||||
|
|
||||||
// Components
|
// Components
|
||||||
|
|
||||||
var Markdown = React.createClass({
|
|
||||||
renderIfApplicable: function(){
|
|
||||||
if(this.props.source)
|
|
||||||
return <MarkdownLib source={this.props.source} skipHtml={true} />
|
|
||||||
return <p>...</p>
|
|
||||||
},
|
|
||||||
render: function(){
|
|
||||||
return this.renderIfApplicable()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var Icon = React.createClass({
|
|
||||||
class: function(){
|
|
||||||
return 'fa fa-'+this.props.name+' '+this.props.className
|
|
||||||
},
|
|
||||||
render: function(){
|
|
||||||
return ( <i className={this.class()}></i> )
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var Container = React.createClass({
|
var Container = React.createClass({
|
||||||
render: function(){
|
render: function(){
|
||||||
return ( <div className="container app">{this.props.children}</div> )
|
return ( <div className="container app">{this.props.children}</div> )
|
||||||
@ -79,97 +55,6 @@ var Navbar = React.createClass({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
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 <div key={this.props.post.title} className="post">
|
|
||||||
<div className="content">
|
|
||||||
<h5>{this.props.post.title}</h5><hr/>
|
|
||||||
<Markdown source={this.props.post.text} skipHtml={true} /><hr/>
|
|
||||||
<div className="icons">
|
|
||||||
<UserID id={this.props.post.op}></UserID>
|
|
||||||
<Icon name="clock-o" className="not-first"/> {this.getDate()}
|
|
||||||
<Icon name="comments" className="not-first" /> Comments
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<div className="postList">
|
|
||||||
{this.state.posts.map(post => {
|
|
||||||
return <Post key={post.title+post.text} post={post} />
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
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 (<Icon name="user" />)
|
|
||||||
} else {
|
|
||||||
return '@'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
render: function(){
|
|
||||||
if(this.props.id)
|
|
||||||
return (<div className="user-id">
|
|
||||||
<Link className="light nounderline" to={'/@'+this.props.id}>
|
|
||||||
{this.getContent()}{this.state.name || this.props.id}
|
|
||||||
</Link>
|
|
||||||
</div>)
|
|
||||||
else return <div className="user-id">
|
|
||||||
<Icon name="ban" /> Unknown User
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Static pages
|
// Static pages
|
||||||
|
|
||||||
var Homepage = React.createClass({
|
var Homepage = React.createClass({
|
||||||
@ -226,165 +111,14 @@ var NotImplemented = React.createClass({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 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: <Icon name="ban" />,
|
|
||||||
description: err
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.setState({ name: res.name, description: res.description })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
linkToEditor: function(){
|
|
||||||
if(this.props.params.userid === boards.id){
|
|
||||||
return <div>
|
|
||||||
<h6>This is your profile</h6>
|
|
||||||
<hr/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
},
|
|
||||||
render: function(){
|
|
||||||
return (<div className="profile">
|
|
||||||
{this.linkToEditor()}
|
|
||||||
<h1>{this.state.name}</h1>
|
|
||||||
<Markdown source={this.state.description} skipHtml={true} />
|
|
||||||
<hr/>
|
|
||||||
<h5 className="light">@{this.props.params.userid}</h5>
|
|
||||||
{this.state.boards.map(n => {
|
|
||||||
return <h6 className="light" key={this.props.params.userid+'/'+n.name}>
|
|
||||||
<Link to={'/@'+this.props.params.userid+'/'+n.name}># {n.name}</Link>
|
|
||||||
</h6>
|
|
||||||
})}
|
|
||||||
</div>)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
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 (<div className="board">
|
|
||||||
<h2>{this.state.name}</h2>
|
|
||||||
<Markdown source={this.state.description} skipHtml={true} />
|
|
||||||
<h5><UserID id={this.props.params.userid} /></h5>
|
|
||||||
<PostList board={this.props.params.boardname} admin={this.props.params.userid}/>
|
|
||||||
</div>)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var Users = React.createClass({
|
|
||||||
getInitialState: function(){
|
|
||||||
return { users: boards.getUsers() }
|
|
||||||
},
|
|
||||||
componentDidMount: function(){
|
|
||||||
boards.searchUsers().on('user',(id) => {
|
|
||||||
if(id === undefined) console.log('found undefined user???')
|
|
||||||
if(this.isMounted() && this.state.users.indexOf(id) < 0)
|
|
||||||
this.setState({ users: this.state.users.concat(id) })
|
|
||||||
})
|
|
||||||
},
|
|
||||||
render: function(){
|
|
||||||
return <div>
|
|
||||||
<h1><Icon name="users" /> Users</h1>
|
|
||||||
<p>Found <b>{this.state.users.length}</b> users</p>
|
|
||||||
<ul>
|
|
||||||
{this.state.users.map(user => {
|
|
||||||
return <UserID key={user} id={user} />
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
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 (
|
|
||||||
<div className="settings">
|
|
||||||
<h2><Icon name="cog"/> Settings</h2>
|
|
||||||
<h5>This page is still a little rough, but it works. Reload the page after saving to apply changes.</h5>
|
|
||||||
<p>Use this page to customize the application's behavior. For now, you can change how it connects to IPFS.</p>
|
|
||||||
<p>All settings are saved in your browser.</p>
|
|
||||||
<div className="row">
|
|
||||||
<div className="six columns">
|
|
||||||
<label htmlFor="nodeAddress">IPFS Node</label>
|
|
||||||
<input className="u-full-width" type="text" id="nodeAddress" value={this.state.addr} onChange={this.onChange} placeholder="localhost" />
|
|
||||||
</div>
|
|
||||||
<div className="six columns">
|
|
||||||
<label htmlFor="nodePort">API Port</label>
|
|
||||||
<input className="u-full-width" type="text" id="nodePort" value={this.state.port} onChange={this.onChange} placeholder="5001" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="buttons">
|
|
||||||
<button className="button button-primary" onClick={this.save}>Save</button>
|
|
||||||
<button className="button not-first" onClick={this.setDefaults}>Defaults</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Start
|
// Start
|
||||||
|
|
||||||
|
var Users = require('users.jsx')(boards)
|
||||||
|
var Settings = require('settings.jsx')(boards)
|
||||||
|
var Profile = require('profile.jsx')(boards)
|
||||||
|
var Board = require('board.jsx')(boards)
|
||||||
|
var Icon = require('icon.jsx')
|
||||||
|
|
||||||
boards.init(err => {
|
boards.init(err => {
|
||||||
if(err){
|
if(err){
|
||||||
console.log('FATAL: IPFS NODE NOT AVAILABLE')
|
console.log('FATAL: IPFS NODE NOT AVAILABLE')
|
||||||
|
30
webapp/components/board.jsx
Normal file
30
webapp/components/board.jsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var Markdown = require('markdown.jsx')
|
||||||
|
var Link = require('react-router').Link
|
||||||
|
var Icon = require('icon.jsx')
|
||||||
|
|
||||||
|
module.exports = function(boards){
|
||||||
|
var UserID = require('userID.jsx')(boards)
|
||||||
|
var PostList = require('postlist.jsx')(boards)
|
||||||
|
return 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 (<div className="board">
|
||||||
|
<h2>{this.state.name}</h2>
|
||||||
|
<Markdown source={this.state.description} skipHtml={true} />
|
||||||
|
<h5><UserID id={this.props.params.userid} /></h5>
|
||||||
|
<PostList board={this.props.params.boardname} admin={this.props.params.userid}/>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
10
webapp/components/icon.jsx
Normal file
10
webapp/components/icon.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
var React = require('react')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
class: function(){
|
||||||
|
return 'fa fa-'+this.props.name+' '+this.props.className
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
return ( <i className={this.class()}></i> )
|
||||||
|
}
|
||||||
|
})
|
13
webapp/components/markdown.jsx
Normal file
13
webapp/components/markdown.jsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var MarkdownLib = require('react-markdown')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
renderIfApplicable: function(){
|
||||||
|
if(this.props.source)
|
||||||
|
return <MarkdownLib source={this.props.source} skipHtml={true} />
|
||||||
|
return <p>...</p>
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
return this.renderIfApplicable()
|
||||||
|
}
|
||||||
|
})
|
30
webapp/components/post.jsx
Normal file
30
webapp/components/post.jsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var moment = require('moment')
|
||||||
|
var Markdown = require('markdown.jsx')
|
||||||
|
var Icon = require('icon.jsx')
|
||||||
|
|
||||||
|
module.exports = function(boards){
|
||||||
|
var UserID = require('userID.jsx')(boards)
|
||||||
|
return React.createClass({
|
||||||
|
getDate: function(){
|
||||||
|
if(this.props.post.date){
|
||||||
|
return moment.unix(this.props.post.date).fromNow()
|
||||||
|
} else {
|
||||||
|
return 'Unknown Date'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
return <div key={this.props.post.title} className="post">
|
||||||
|
<div className="content">
|
||||||
|
<h5>{this.props.post.title}</h5><hr/>
|
||||||
|
<Markdown source={this.props.post.text} skipHtml={true} /><hr/>
|
||||||
|
<div className="icons">
|
||||||
|
<UserID id={this.props.post.op}></UserID>
|
||||||
|
<Icon name="clock-o" className="not-first"/> {this.getDate()}
|
||||||
|
<Icon name="comments" className="not-first" /> Comments
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
42
webapp/components/postlist.jsx
Normal file
42
webapp/components/postlist.jsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var moment = require('moment')
|
||||||
|
var sortedIndex = require('lodash.sortedindex')
|
||||||
|
|
||||||
|
module.exports = function(boards){
|
||||||
|
var Post = require('post.jsx')(boards)
|
||||||
|
return 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 (
|
||||||
|
<div className="postList">
|
||||||
|
{this.state.posts.map(post => {
|
||||||
|
return <Post key={post.title+post.text} post={post} />
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
54
webapp/components/profile.jsx
Normal file
54
webapp/components/profile.jsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var Markdown = require('markdown.jsx')
|
||||||
|
var Link = require('react-router').Link
|
||||||
|
var Icon = require('icon.jsx')
|
||||||
|
|
||||||
|
module.exports = function(boards){
|
||||||
|
return 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: <Icon name="ban" />,
|
||||||
|
description: err
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setState({ name: res.name, description: res.description })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
linkToEditor: function(){
|
||||||
|
if(this.props.params.userid === boards.id){
|
||||||
|
return <div>
|
||||||
|
<h6>This is your profile</h6>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
return (<div className="profile">
|
||||||
|
{this.linkToEditor()}
|
||||||
|
<h1>{this.state.name}</h1>
|
||||||
|
<Markdown source={this.state.description} skipHtml={true} />
|
||||||
|
<hr/>
|
||||||
|
<h5 className="light">@{this.props.params.userid}</h5>
|
||||||
|
{this.state.boards.map(n => {
|
||||||
|
return <h6 className="light" key={this.props.params.userid+'/'+n.name}>
|
||||||
|
<Link to={'/@'+this.props.params.userid+'/'+n.name}># {n.name}</Link>
|
||||||
|
</h6>
|
||||||
|
})}
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
66
webapp/components/settings.jsx
Normal file
66
webapp/components/settings.jsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var Icon = require('icon.jsx')
|
||||||
|
|
||||||
|
module.exports = function(boards){
|
||||||
|
return 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 (
|
||||||
|
<div className="settings">
|
||||||
|
<h2><Icon name="cog"/> Settings</h2>
|
||||||
|
<h5>This page is still a little rough, but it works. Reload the page after saving to apply changes.</h5>
|
||||||
|
<p>Use this page to customize the application's behavior. For now, you can change how it connects to IPFS.</p>
|
||||||
|
<p>All settings are saved in your browser.</p>
|
||||||
|
<div className="row">
|
||||||
|
<div className="six columns">
|
||||||
|
<label htmlFor="nodeAddress">IPFS Node</label>
|
||||||
|
<input className="u-full-width" type="text" id="nodeAddress" value={this.state.addr} onChange={this.onChange} placeholder="localhost" />
|
||||||
|
</div>
|
||||||
|
<div className="six columns">
|
||||||
|
<label htmlFor="nodePort">API Port</label>
|
||||||
|
<input className="u-full-width" type="text" id="nodePort" value={this.state.port} onChange={this.onChange} placeholder="5001" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="buttons">
|
||||||
|
<button className="button button-primary" onClick={this.save}>Save</button>
|
||||||
|
<button className="button not-first" onClick={this.setDefaults}>Defaults</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
37
webapp/components/userID.jsx
Normal file
37
webapp/components/userID.jsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var Icon = require('icon.jsx')
|
||||||
|
var Link = require('react-router').Link
|
||||||
|
|
||||||
|
module.exports = function(boards){
|
||||||
|
return 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 || 'Unknown Name' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getContent: function(){
|
||||||
|
if(this.state.name){
|
||||||
|
return (<Icon name="user" />)
|
||||||
|
} else {
|
||||||
|
return '@'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
if(this.props.id)
|
||||||
|
return (<div className="user-id">
|
||||||
|
<Link className="light nounderline" to={'/@'+this.props.id}>
|
||||||
|
{this.getContent()}{this.state.name || this.props.id}
|
||||||
|
</Link>
|
||||||
|
</div>)
|
||||||
|
else return <div className="user-id">
|
||||||
|
<Icon name="ban" /> Unknown User
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
29
webapp/components/users.jsx
Normal file
29
webapp/components/users.jsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var Icon = require('icon.jsx')
|
||||||
|
|
||||||
|
module.exports = function(boards){
|
||||||
|
var UserID = require('userID.jsx')(boards)
|
||||||
|
return React.createClass({
|
||||||
|
getInitialState: function(){
|
||||||
|
return { users: boards.getUsers() }
|
||||||
|
},
|
||||||
|
componentDidMount: function(){
|
||||||
|
boards.searchUsers().on('user',(id) => {
|
||||||
|
if(id === undefined) console.log('found undefined user???')
|
||||||
|
if(this.isMounted() && this.state.users.indexOf(id) < 0)
|
||||||
|
this.setState({ users: this.state.users.concat(id) })
|
||||||
|
})
|
||||||
|
},
|
||||||
|
render: function(){
|
||||||
|
return <div>
|
||||||
|
<h1><Icon name="users" /> Users</h1>
|
||||||
|
<p>Found <b>{this.state.users.length}</b> users</p>
|
||||||
|
<ul>
|
||||||
|
{this.state.users.map(user => {
|
||||||
|
return <UserID key={user} id={user} />
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -13,7 +13,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
modulesDirectories: [
|
modulesDirectories: [
|
||||||
'node_modules', './webapp/', 'lib',
|
'node_modules', './webapp/', 'lib', './webapp/components/',
|
||||||
'node_modules/font-awesome/css', 'node_modules/font-awesome/fonts'
|
'node_modules/font-awesome/css', 'node_modules/font-awesome/fonts'
|
||||||
],
|
],
|
||||||
alias: {
|
alias: {
|
||||||
|
Loading…
Reference in New Issue
Block a user