mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-03-12 21:48:39 +01:00
profile editor implemented, very rough but works
This commit is contained in:
parent
604a48fa53
commit
c81dd42bf8
@ -84,15 +84,57 @@ function BoardsAPI (ipfs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoardsAPI.prototype.createProfile = function (profile) {
|
BoardsAPI.prototype.createProfile = function (profile, done) {
|
||||||
console.log('creating profile')
|
console.log('Generating profile:', profile)
|
||||||
this.ipfs.add(new Buffer(JSON.stringify(profile)), (err, res) => {
|
try {
|
||||||
console.log('added profile to IPFS:', err, res.Hash)
|
var profile_str = JSON.stringify(profile)
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error, invalid profile:', e)
|
||||||
|
return done(e)
|
||||||
|
}
|
||||||
|
asyncjs.waterfall([
|
||||||
|
// Create required directories
|
||||||
|
cb => this.ipfs.files.mkdir('/ipfs-boards-profile/boards', { p: true }, cb),
|
||||||
|
(e, cb) => this.ipfs.files.mkdir('/ipfs-boards-profile/comments', { p: true }, cb),
|
||||||
|
(e, cb) => this.ipfs.files.mkdir('/ipfs-boards-profile/posts', { p: true }, cb),
|
||||||
|
(e, cb) => {
|
||||||
|
// Remove old profile files if present
|
||||||
|
console.log('Removing file...')
|
||||||
|
var path = '/ipfs-boards-profile/ipfs-boards-version.txt'
|
||||||
|
this.ipfs.files.rm(path, { r: true }, res => {
|
||||||
|
console.log('Removing file...')
|
||||||
|
var path = '/ipfs-boards-profile/profile.json'
|
||||||
|
this.ipfs.files.rm(path, { r: true }, res => cb())
|
||||||
|
})
|
||||||
|
},
|
||||||
|
cb => {
|
||||||
|
// Add profile version file
|
||||||
|
var path = '/ipfs-boards-profile/ipfs-boards-version.txt'
|
||||||
|
var version_hash = '/ipfs/' + this.version_hash
|
||||||
|
this.ipfs.files.cp([version_hash, path], cb)
|
||||||
|
},
|
||||||
|
(e, cb) => {
|
||||||
|
// Serialize profile and add to IPFS
|
||||||
|
this.ipfs.add(new Buffer(profile_str), cb)
|
||||||
|
},
|
||||||
|
(res, cb) => {
|
||||||
|
// Move profile into mfs
|
||||||
|
console.log('added profile to IPFS:', res.Hash)
|
||||||
var profilepath = '/ipfs/' + res.Hash
|
var profilepath = '/ipfs/' + res.Hash
|
||||||
this.ipfs.files.mv([profilepath, '/ipns/local/profile.json'], (err, res) => {
|
this.ipfs.files.cp([profilepath, '/ipfs-boards-profile/profile.json'], cb)
|
||||||
console.log('mv', err, res)
|
},
|
||||||
})
|
(e, cb) => this.ipfs.files.stat('/', cb),
|
||||||
})
|
(res, cb) => {
|
||||||
|
var profile_hash = res.Hash
|
||||||
|
console.log('Publishing profile...')
|
||||||
|
this.ipfs.name.publish(profile_hash, cb)
|
||||||
|
// TODO: cb is probably never called here! Figure out why!
|
||||||
|
},
|
||||||
|
(e, cb) => {
|
||||||
|
console.log('Done')
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
}
|
}
|
||||||
|
|
||||||
BoardsAPI.prototype.backupCache = function () {
|
BoardsAPI.prototype.backupCache = function () {
|
||||||
@ -112,6 +154,7 @@ BoardsAPI.prototype.resolveIPNS = function (n, handler) {
|
|||||||
if (err) {
|
if (err) {
|
||||||
// Communicate error
|
// Communicate error
|
||||||
this.ee.emit('error', err)
|
this.ee.emit('error', err)
|
||||||
|
if (handler && handler.apply) handler(undefined, err)
|
||||||
} else {
|
} else {
|
||||||
var url = r.Path
|
var url = r.Path
|
||||||
if (url === undefined) {
|
if (url === undefined) {
|
||||||
@ -527,7 +570,7 @@ BoardsAPI.prototype.init = function (done) {
|
|||||||
this.id = res.ID
|
this.id = res.ID
|
||||||
this.resolveIPNS(res.ID)
|
this.resolveIPNS(res.ID)
|
||||||
console.log('Version is', this.version)
|
console.log('Version is', this.version)
|
||||||
this.ipfs.add(new Buffer('ipfs:boards:version:' + this.version), {n: true}, (err2, r) => {
|
this.ipfs.add(new Buffer(this.version), (err2, r) => {
|
||||||
if (err2) {
|
if (err2) {
|
||||||
this.ee.emit('error', err2)
|
this.ee.emit('error', err2)
|
||||||
console.log('Error while calculating version hash:', err2)
|
console.log('Error while calculating version hash:', err2)
|
||||||
@ -544,7 +587,7 @@ BoardsAPI.prototype.init = function (done) {
|
|||||||
console.log('Error while getting ipfs version:', err)
|
console.log('Error while getting ipfs version:', err)
|
||||||
if (done && done.apply) done(err)
|
if (done && done.apply) done(err)
|
||||||
} else {
|
} else {
|
||||||
this.ipfs_version = res.Version
|
this.ipfs_version = res.Version.split('-')[0]
|
||||||
console.log('IPFS Version is', res.Version)
|
console.log('IPFS Version is', res.Version)
|
||||||
if (semver.satisfies(this.ipfs_version, '~0.4.0')) {
|
if (semver.satisfies(this.ipfs_version, '~0.4.0')) {
|
||||||
console.log('IPFS version is supported')
|
console.log('IPFS version is supported')
|
||||||
|
@ -25,6 +25,7 @@ var Profile = require('profile.jsx')(boards)
|
|||||||
var Board = require('board.jsx')(boards)
|
var Board = require('board.jsx')(boards)
|
||||||
var PostPage = require('postpage.jsx')(boards)
|
var PostPage = require('postpage.jsx')(boards)
|
||||||
var CommentPage = require('commentpage.jsx')(boards)
|
var CommentPage = require('commentpage.jsx')(boards)
|
||||||
|
var ProfileEditor = require('profile-editor.jsx')(boards)
|
||||||
|
|
||||||
// Define Main Components
|
// Define Main Components
|
||||||
|
|
||||||
@ -91,6 +92,7 @@ ReactDOM.render(
|
|||||||
</Route>
|
</Route>
|
||||||
<Route path="/post/:posthash" component={PostPage} />
|
<Route path="/post/:posthash" component={PostPage} />
|
||||||
<Route path="/board/:boardname" component={Board} />
|
<Route path="/board/:boardname" component={Board} />
|
||||||
|
<Route path="/edit/profile" component={ProfileEditor} />
|
||||||
<Route path="/users" component={Users} />
|
<Route path="/users" component={Users} />
|
||||||
<Route path="/settings" component={Settings} />
|
<Route path="/settings" component={Settings} />
|
||||||
<Route path="*" component={NotFound} />
|
<Route path="*" component={NotFound} />
|
||||||
|
@ -57,7 +57,7 @@ module.exports = React.createClass({
|
|||||||
<h4 className="light">Sorry, but at the moment an external application is needed to try the Prototype</h4>
|
<h4 className="light">Sorry, but at the moment an external application is needed to try the Prototype</h4>
|
||||||
<hr/>
|
<hr/>
|
||||||
<h5>Error Message</h5>
|
<h5>Error Message</h5>
|
||||||
<p>{this.state.error.Message || this.state.error || 'connection to go-ipfs failed'}</p>
|
<p>{this.state.error || 'connection to go-ipfs failed'}</p>
|
||||||
<hr/>
|
<hr/>
|
||||||
<p>You don't have an IPFS node running at <code>{opt.addr}:{opt.port}</code> or it is not reachable.
|
<p>You don't have an IPFS node running at <code>{opt.addr}:{opt.port}</code> or it is not reachable.
|
||||||
The IPFS Boards prototype requires a full IPFS node. Please start one by following the
|
The IPFS Boards prototype requires a full IPFS node. Please start one by following the
|
||||||
|
94
webapp/pages/profile-editor.jsx
Normal file
94
webapp/pages/profile-editor.jsx
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var GetIPFS = require('getipfs.jsx')
|
||||||
|
var Icon = require('icon.jsx')
|
||||||
|
|
||||||
|
module.exports = function (boardsAPI) {
|
||||||
|
return React.createClass({
|
||||||
|
getInitialState () {
|
||||||
|
return { loading: true }
|
||||||
|
},
|
||||||
|
componentDidMount () {
|
||||||
|
boardsAPI.use(boards => {
|
||||||
|
boards.init()
|
||||||
|
boards.getEventEmitter().on('init', err => {
|
||||||
|
if (!err && this.isMounted()) {
|
||||||
|
this.init(boards)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (this.isMounted() && boards.isInit) {
|
||||||
|
this.init(boards)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getProfile (boards) {
|
||||||
|
boards.getProfile(boards.getMyID(), (err, p) => {
|
||||||
|
if (!this.isMounted()) return
|
||||||
|
else if (err) this.setState({ loading: false })
|
||||||
|
else if (this.state.loading) {
|
||||||
|
// State isn't set to p directly to avoid XSS.
|
||||||
|
// There is no knowing what's gonna be in a profile
|
||||||
|
// Should also convert to string and check length etc.
|
||||||
|
this.setState({ p: p.name, description: p.description, loading: false })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
init (boards) {
|
||||||
|
if (this.state.init) return
|
||||||
|
this.setState({ api: boards })
|
||||||
|
this.getProfile(boards)
|
||||||
|
},
|
||||||
|
handleChange (event) {
|
||||||
|
if (event.target.id === 'name') {
|
||||||
|
this.setState({ name: event.target.value })
|
||||||
|
} else {
|
||||||
|
this.setState({ description: event.target.value })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
skip () {
|
||||||
|
this.setState({ loading: false })
|
||||||
|
},
|
||||||
|
save () {
|
||||||
|
var boards = this.state.api
|
||||||
|
var profile = {
|
||||||
|
name: this.state.name,
|
||||||
|
description: this.state.description
|
||||||
|
}
|
||||||
|
boards.createProfile(profile, err => {
|
||||||
|
console.log('CREATE:', err)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
if (this.state.api) {
|
||||||
|
if (this.state.loading) {
|
||||||
|
return <div>
|
||||||
|
<div className="text-center">
|
||||||
|
<Icon className="center-block fa-spin fa-3x light" name="refresh" />
|
||||||
|
<h4 className="top-half-em">Fetching your current profile...</h4>
|
||||||
|
<button className="button button-primary center-block" onClick={this.skip}>Skip</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div className="editor">
|
||||||
|
<h2><Icon name="user" className="light" /> Edit Profile</h2>
|
||||||
|
<p>This App uses IPFS to store your profile. When you are offline,
|
||||||
|
other users or servers that viewed your profile will serve it to
|
||||||
|
others.</p>
|
||||||
|
<div className="center-block thin">
|
||||||
|
<label htmlFor="name">Name</label>
|
||||||
|
<input className="u-full-width" type="text" id="name" value={this.state.name} onChange={this.handleChange} placeholder="Who are you on the interwebs?" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="desc">Caption</label>
|
||||||
|
<textarea className="u-full-width" id="desc" value={this.state.description} onChange={this.handleChange} placeholder="Say something about yourself." />
|
||||||
|
</div>
|
||||||
|
<div className="buttons">
|
||||||
|
<button className="button button-primary" onClick={this.save}>Publish</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else return <GetIPFS api={this.state.api} />
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -69,10 +69,10 @@ module.exports = function (boardsAPI) {
|
|||||||
if (uid === this.state.id) {
|
if (uid === this.state.id) {
|
||||||
return <div className="your-profile">
|
return <div className="your-profile">
|
||||||
<h6>This is your profile</h6>
|
<h6>This is your profile</h6>
|
||||||
{this.state.error ? <div>
|
<div className="iconbar">
|
||||||
<b>Oops</b>. Looks like your profile is not valid
|
<Link className="nounderline" to="/edit/profile"><Icon name="edit" className="fa-2x light"/></Link>
|
||||||
|
</div>
|
||||||
<button className="new-profile button button-primary" onClick={this.newProfile}>New Profile</button>
|
<button className="new-profile button button-primary" onClick={this.newProfile}>New Profile</button>
|
||||||
</div> : <div></div>}
|
|
||||||
<hr/>
|
<hr/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,10 @@ a {
|
|||||||
color: black
|
color: black
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-half-em {
|
||||||
|
margin-top: .5em
|
||||||
|
}
|
||||||
|
|
||||||
.center-block {
|
.center-block {
|
||||||
margin:auto;
|
margin:auto;
|
||||||
display:block;
|
display:block;
|
||||||
|
Loading…
Reference in New Issue
Block a user