mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-01-09 12:19:49 +01:00
huge usability improvements
This commit is contained in:
parent
81a553f5a2
commit
65678a1521
@ -5,6 +5,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ipfs": "^0.27.7",
|
"ipfs": "^0.27.7",
|
||||||
|
"moment": "^2.20.1",
|
||||||
"orbit-db": "^0.19.4",
|
"orbit-db": "^0.19.4",
|
||||||
"orbit-db-discussion-board": "https://github.com/fazo96/orbit-db-discussion-board.git",
|
"orbit-db-discussion-board": "https://github.com/fazo96/orbit-db-discussion-board.git",
|
||||||
"react": "^16.2.0",
|
"react": "^16.2.0",
|
||||||
|
@ -1,12 +1,23 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Post from './Post'
|
import Post from './Post'
|
||||||
import { Divider, Icon, Grid, Segment, Header, List, Button, Card } from 'semantic-ui-react'
|
import { Divider, Icon, Grid, Header, List, Button, Card } from 'semantic-ui-react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { shortenAddress } from '../utils/orbitdb';
|
import { shortenAddress } from '../utils/orbitdb';
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
export default function Board({ address, posts, metadata, replicating }) {
|
export default function Board({ address, posts, metadata, replicating, stats, replicationInfo, lastReplicated }) {
|
||||||
const { email, website, title } = metadata || {}
|
const { email, website, title } = metadata || {}
|
||||||
const url = window.location.href
|
const peerCount = (stats.peers || []).length
|
||||||
|
const online = peerCount > 0
|
||||||
|
const writeable = stats.access ? (stats.access.writeable ? 'Yes' : 'No') : '?'
|
||||||
|
let replicationMessage = lastReplicated ? ('Last Activity at ' + moment(lastReplicated).format('H:mm')) : 'No Activity'
|
||||||
|
if (replicating) {
|
||||||
|
if (replicationInfo && replicationInfo.max !== undefined) {
|
||||||
|
replicationMessage = 'Progress: ' + (replicationInfo.progress || 0) + '/' + replicationInfo.max
|
||||||
|
} else {
|
||||||
|
replicationMessage = 'Initializing Transfer'
|
||||||
|
}
|
||||||
|
}
|
||||||
return <Grid container divided colums={2}>
|
return <Grid container divided colums={2}>
|
||||||
<Grid.Column width={8}>
|
<Grid.Column width={8}>
|
||||||
<Header size='large' style={{marginTop:'.5em'}}>
|
<Header size='large' style={{marginTop:'.5em'}}>
|
||||||
@ -18,19 +29,41 @@ export default function Board({ address, posts, metadata, replicating }) {
|
|||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='linkify' size="large" verticalAlign="middle"/>
|
<List.Icon name='linkify' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header>Board Address</List.Header>
|
<List.Header>Address</List.Header>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<a href={url}>{address}</a>
|
{address}
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='users' size="large" verticalAlign="middle"/>
|
<List.Icon name='disk outline' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header>Users</List.Header>
|
<List.Header>Size</List.Header>
|
||||||
<List.Content>?</List.Content>
|
<List.Content>{stats.opLogLength || 0} Entries</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name={online ? 'heart' : 'heartbeat'} size="large" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>{online ? 'Online' : 'Offline'}</List.Header>
|
||||||
|
<List.Content>{online ? peerCount + ' Connections' : 'No Connections'}</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon color={replicating ? 'green' : null} name='feed' size="large" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>{replicating ? 'Downloading' : 'Download'}</List.Header>
|
||||||
|
<List.Content>{replicationMessage}</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name='edit' size="large" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Write Access</List.Header>
|
||||||
|
<List.Content>{writeable}</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<Divider/>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='file text outline' size="large" verticalAlign="middle"/>
|
<List.Icon name='file text outline' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
@ -38,13 +71,6 @@ export default function Board({ address, posts, metadata, replicating }) {
|
|||||||
<List.Content>{Object.values(posts || {}).length}</List.Content>
|
<List.Content>{Object.values(posts || {}).length}</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
<List.Item>
|
|
||||||
<List.Icon color={replicating ? 'green' : null} name='wifi' size="large" verticalAlign="middle"/>
|
|
||||||
<List.Content>
|
|
||||||
<List.Header>Replication</List.Header>
|
|
||||||
<List.Content>{replicating ? 'Receiving Content...' : 'Idle'}</List.Content>
|
|
||||||
</List.Content>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='globe' size="large" verticalAlign="middle"/>
|
<List.Icon name='globe' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
@ -61,13 +87,13 @@ export default function Board({ address, posts, metadata, replicating }) {
|
|||||||
</List.Item>
|
</List.Item>
|
||||||
</List>
|
</List>
|
||||||
<div className='ui three buttons basic'>
|
<div className='ui three buttons basic'>
|
||||||
<Button>
|
<Button as={Link} to={'/'}>
|
||||||
<Icon name='left arrow'/> Boards
|
<Icon name='left arrow'/> Boards
|
||||||
</Button>
|
</Button>
|
||||||
<Button>
|
<Button disabled={!writeable}>
|
||||||
<Icon name='pencil'/> Edit
|
<Icon name='pencil'/> Edit
|
||||||
</Button>
|
</Button>
|
||||||
<Button as={Link} to={shortenAddress(address)+'/p/new'}>
|
<Button disabled={!writeable} as={Link} to={shortenAddress(address)+'/p/new'}>
|
||||||
<Icon name='plus'/> New Post
|
<Icon name='plus'/> New Post
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { Redirect } from 'react-router-dom'
|
|
||||||
import { Container, Card, Form, Button } from 'semantic-ui-react'
|
import { Container, Card, Form, Button } from 'semantic-ui-react'
|
||||||
import { shortenAddress } from '../utils/orbitdb'
|
|
||||||
|
|
||||||
export default class BoardForm extends Component {
|
export default class BoardForm extends Component {
|
||||||
constructor(props){
|
constructor(props){
|
||||||
|
@ -2,11 +2,12 @@ import React from 'react'
|
|||||||
import { Switch, Route } from 'react-router-dom'
|
import { Switch, Route } from 'react-router-dom'
|
||||||
import Board from '../containers/Board'
|
import Board from '../containers/Board'
|
||||||
import PostEditor from '../containers/PostEditor'
|
import PostEditor from '../containers/PostEditor'
|
||||||
|
import WithStats from '../containers/WithStats'
|
||||||
|
|
||||||
function BoardPage({ match, address, posts, metadata }) {
|
function BoardPage({ match, address, posts, metadata }) {
|
||||||
return <Switch>
|
return <Switch>
|
||||||
<Route path={match.path+'p/new'} component={PostEditor} />
|
<Route path={match.path+'p/new'} component={PostEditor} />
|
||||||
<Route path={match.path} component={Board} />
|
<Route path={match.path} component={WithStats(Board)} />
|
||||||
</Switch>
|
</Switch>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { List, Icon, Segment, Divider, Grid, Header, Button, Card } from 'semant
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import BoardsItem from './BoardsItem'
|
import BoardsItem from './BoardsItem'
|
||||||
|
|
||||||
export default function Boards({ boards, createBoard }) {
|
export default function Boards({ stats, boards, createBoard }) {
|
||||||
return <Grid container divided colums={2}>
|
return <Grid container divided colums={2}>
|
||||||
<Grid.Column width={8}>
|
<Grid.Column width={8}>
|
||||||
<Header size='large' style={{marginTop:'.5em'}}>
|
<Header size='large' style={{marginTop:'.5em'}}>
|
||||||
@ -13,43 +13,43 @@ export default function Boards({ boards, createBoard }) {
|
|||||||
<Divider />
|
<Divider />
|
||||||
<List relaxed>
|
<List relaxed>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='file text outline' size="large" verticalAlign="middle"/>
|
<List.Icon name='leaf' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header>Boards</List.Header>
|
<List.Header>Seeding</List.Header>
|
||||||
<List.Content>{Object.keys(boards).length}</List.Content>
|
<List.Content>{Object.keys(boards).length} Boards</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='wifi' size="large" verticalAlign="middle"/>
|
<List.Icon name='wifi' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header>Connected Peers</List.Header>
|
<List.Header>Connected Peers</List.Header>
|
||||||
<List.Content>?</List.Content>
|
<List.Content>{stats.peers.length}</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='disk outline' size="large" verticalAlign="middle"/>
|
<List.Icon name='disk outline' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header>Used Space</List.Header>
|
<List.Header>Used Space</List.Header>
|
||||||
<List.Content>?</List.Content>
|
<List.Content>Not Supported Yet</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='user' size="large" verticalAlign="middle"/>
|
<List.Icon name='user circle' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header>IPFS ID</List.Header>
|
<List.Header>IPFS ID</List.Header>
|
||||||
<List.Content>?</List.Content>
|
<List.Content>{stats.id}</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Icon name='key' size="large" verticalAlign="middle"/>
|
<List.Icon name='key' size="large" verticalAlign="middle"/>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header>OrbitDB Public Key</List.Header>
|
<List.Header>OrbitDB Public Key</List.Header>
|
||||||
<List.Content>?</List.Content>
|
<List.Content style={{wordBreak:'break-all'}}>{stats.pubKey}</List.Content>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
</List>
|
</List>
|
||||||
<div className="ui two buttons">
|
<div className="ui two buttons">
|
||||||
<Button as='a' href="https://github.com/fazo96/ipfs-boards">
|
<Button as='a' href="https://github.com/fazo96/ipfs-boards" target="__blank" >
|
||||||
<Icon name="github"/> GitHub
|
<Icon name="github"/> GitHub
|
||||||
</Button>
|
</Button>
|
||||||
<Button as={Link} to={'/b/new'}>
|
<Button as={Link} to={'/b/new'}>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Card, Icon } from 'semantic-ui-react'
|
import { List, Card } from 'semantic-ui-react'
|
||||||
|
|
||||||
export default function Post({ title, multihash}) {
|
export default function Post({ title, multihash, pubKey }) {
|
||||||
return <Card fluid>
|
return <Card fluid>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Card.Header>
|
<Card.Header>
|
||||||
@ -10,10 +10,31 @@ export default function Post({ title, multihash}) {
|
|||||||
<Card.Meta>Post</Card.Meta>
|
<Card.Meta>Post</Card.Meta>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
<Card.Content style={{wordBreak:'break-all'}}>
|
<Card.Content style={{wordBreak:'break-all'}}>
|
||||||
<Icon name="chain"/> <a href={'//ipfs.io/ipfs/'+multihash}>View</a>
|
<List>
|
||||||
</Card.Content>
|
<List.Item>
|
||||||
<Card.Content extra>
|
<List.Icon name="key" verticalAlign="middle"/>
|
||||||
<Icon name="comments"/> Comments not supported yet
|
<List.Content>
|
||||||
|
<List.Header>Signed By</List.Header>
|
||||||
|
<List.Content>{pubKey || 'Unknown'}</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name="comments" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Comments</List.Header>
|
||||||
|
<List.Content>Not Supported Yet</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<List.Icon name="chain" verticalAlign="middle"/>
|
||||||
|
<List.Content>
|
||||||
|
<List.Header>Content</List.Header>
|
||||||
|
<List.Content>
|
||||||
|
<a href={'//ipfs.io/ipfs/'+multihash}>{multihash}</a>
|
||||||
|
</List.Content>
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
</List>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card>
|
</Card>
|
||||||
}
|
}
|
@ -3,9 +3,11 @@ import { connect } from 'react-redux'
|
|||||||
import BoardComponent from '../components/Board'
|
import BoardComponent from '../components/Board'
|
||||||
import { getBoardAddress } from '../utils/orbitdb'
|
import { getBoardAddress } from '../utils/orbitdb'
|
||||||
|
|
||||||
function Board({ location, match, boards }) {
|
function Board({ stats, location, match, boards }) {
|
||||||
const { hash, name } = match.params
|
const { hash, name } = match.params
|
||||||
return <BoardComponent {...boards[getBoardAddress(hash, name)]} />
|
const address = getBoardAddress(hash, name)
|
||||||
|
const boardStats = stats.dbs[address] || {}
|
||||||
|
return <BoardComponent stats={boardStats} {...boards[address]} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state){
|
||||||
|
@ -2,9 +2,12 @@ import React from 'react'
|
|||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { push } from 'react-router-redux'
|
import { push } from 'react-router-redux'
|
||||||
import BoardsComponent from '../components/Boards'
|
import BoardsComponent from '../components/Boards'
|
||||||
|
import WithStats from './WithStats'
|
||||||
|
|
||||||
|
const WrappedComponent = WithStats(BoardsComponent)
|
||||||
|
|
||||||
function Boards({ boards, createBoard }) {
|
function Boards({ boards, createBoard }) {
|
||||||
return <BoardsComponent boards={boards} createBoard={createBoard} />
|
return <WrappedComponent boards={boards} createBoard={createBoard} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state){
|
function mapStateToProps(state){
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { Loader, Dimmer } from 'semantic-ui-react'
|
import { Dimmer } from 'semantic-ui-react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { openBoard } from '../actions/board'
|
import { openBoard } from '../actions/board'
|
||||||
import { getBoardAddress } from '../utils/orbitdb'
|
import { getBoardAddress } from '../utils/orbitdb'
|
||||||
|
44
src/containers/WithStats.js
Normal file
44
src/containers/WithStats.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
import { getStats } from '../utils/ipfs'
|
||||||
|
|
||||||
|
export default function(WrappedComponent) {
|
||||||
|
return class extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
stats: {
|
||||||
|
id: '?',
|
||||||
|
peers: [],
|
||||||
|
pubKey: '?',
|
||||||
|
dbs: {}
|
||||||
|
},
|
||||||
|
interval: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async refresh(loop = true) {
|
||||||
|
const newStats = await getStats()
|
||||||
|
const stats = Object.assign({}, this.state.stats, newStats)
|
||||||
|
this.setState({ stats }, loop ? this.refreshDelayed.bind(this) : undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshDelayed() {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
this.refresh()
|
||||||
|
}, 2000)
|
||||||
|
this.setState({ timeout })
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.state.interval) clearInterval(this.state.interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <WrappedComponent stats={this.state.stats} {...this.props} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/index.js
10
src/index.js
@ -7,6 +7,7 @@ import App from './components/App'
|
|||||||
import registerServiceWorker from './registerServiceWorker'
|
import registerServiceWorker from './registerServiceWorker'
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import { ConnectedRouter } from 'react-router-redux'
|
import { ConnectedRouter } from 'react-router-redux'
|
||||||
|
import { start } from './orbitdb'
|
||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ render(
|
|||||||
|
|
||||||
if (module.hot) {
|
if (module.hot) {
|
||||||
module.hot.accept('./components/App', () => {
|
module.hot.accept('./components/App', () => {
|
||||||
const NewApp = require('./components/App').default;
|
const NewApp = require('./components/App').default
|
||||||
render(
|
render(
|
||||||
<AppContainer>
|
<AppContainer>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
@ -33,8 +34,9 @@ if (module.hot) {
|
|||||||
</Provider>
|
</Provider>
|
||||||
</AppContainer>,
|
</AppContainer>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
registerServiceWorker();
|
registerServiceWorker()
|
||||||
|
start(store.dispatch)
|
@ -2,7 +2,6 @@ import IPFS from 'ipfs'
|
|||||||
import OrbitDB from 'orbit-db'
|
import OrbitDB from 'orbit-db'
|
||||||
import BoardStore from 'orbit-db-discussion-board'
|
import BoardStore from 'orbit-db-discussion-board'
|
||||||
import multihashes from 'multihashes'
|
import multihashes from 'multihashes'
|
||||||
import { getBoardIdFromAddress } from '../utils/orbitdb'
|
|
||||||
|
|
||||||
export function isValidID(id) {
|
export function isValidID(id) {
|
||||||
try {
|
try {
|
||||||
@ -13,7 +12,7 @@ export function isValidID(id) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function open(address, metadata) {
|
export async function start() {
|
||||||
if (!window.ipfs) {
|
if (!window.ipfs) {
|
||||||
window.ipfs = new IPFS({
|
window.ipfs = new IPFS({
|
||||||
repo: 'ipfs-v6-boards-v0',
|
repo: 'ipfs-v6-boards-v0',
|
||||||
@ -38,23 +37,23 @@ export async function open(address, metadata) {
|
|||||||
OrbitDB.addDatabaseType(BoardStore.type, BoardStore)
|
OrbitDB.addDatabaseType(BoardStore.type, BoardStore)
|
||||||
window.orbitDb = new OrbitDB(window.ipfs)
|
window.orbitDb = new OrbitDB(window.ipfs)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function open(address, metadata) {
|
||||||
|
await start()
|
||||||
const options = {
|
const options = {
|
||||||
type: BoardStore.type,
|
type: BoardStore.type,
|
||||||
create: true,
|
create: true,
|
||||||
write: ['*']
|
write: ['*']
|
||||||
}
|
}
|
||||||
try {
|
const db = await window.orbitDb.open(address, options)
|
||||||
const db = await window.orbitDb.open(address, options)
|
await db.load()
|
||||||
await db.load()
|
if (metadata) {
|
||||||
if (metadata) {
|
await db.updateMetadata(metadata)
|
||||||
await db.updateMetadata(metadata)
|
|
||||||
}
|
|
||||||
if (!window.dbs) window.dbs = {}
|
|
||||||
window.dbs[db.address.toString()] = db
|
|
||||||
return db
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
}
|
}
|
||||||
|
if (!window.dbs) window.dbs = {}
|
||||||
|
window.dbs[db.address.toString()] = db
|
||||||
|
return db
|
||||||
}
|
}
|
||||||
|
|
||||||
export function connectDb(db, dispatch) {
|
export function connectDb(db, dispatch) {
|
||||||
@ -83,10 +82,7 @@ export function connectDb(db, dispatch) {
|
|||||||
progress,
|
progress,
|
||||||
have,
|
have,
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
replicationInfo: {
|
replicationInfo: Object.assign({}, db._replicationInfo)
|
||||||
progress: db._replicationInfo.progress,
|
|
||||||
max: db._replicationInfo.max
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
db.events.on('replicate', address => {
|
db.events.on('replicate', address => {
|
||||||
|
@ -5,7 +5,6 @@ import {
|
|||||||
ORBITDB_REPLICATED,
|
ORBITDB_REPLICATED,
|
||||||
ORBITDB_REPLICATE
|
ORBITDB_REPLICATE
|
||||||
} from '../actions/actionTypes'
|
} from '../actions/actionTypes'
|
||||||
import { getBoardIdFromAddress } from '../utils/orbitdb'
|
|
||||||
|
|
||||||
function getInitialState() {
|
function getInitialState() {
|
||||||
return {
|
return {
|
||||||
@ -43,7 +42,8 @@ export default function BoardsReducer(state = getInitialState(), action) {
|
|||||||
case ORBITDB_REPLICATED:
|
case ORBITDB_REPLICATED:
|
||||||
address = action.address
|
address = action.address
|
||||||
return Object.assign({}, state, { boards: updateBoard(state.boards, address, {
|
return Object.assign({}, state, { boards: updateBoard(state.boards, address, {
|
||||||
replicating: false
|
replicating: false,
|
||||||
|
lastReplicated: action.time
|
||||||
})})
|
})})
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
@ -2,8 +2,8 @@ import { put, call, fork, take } from 'redux-saga/effects'
|
|||||||
import { eventChannel } from 'redux-saga'
|
import { eventChannel } from 'redux-saga'
|
||||||
import { push } from 'react-router-redux'
|
import { push } from 'react-router-redux'
|
||||||
import { open, connectDb } from '../orbitdb'
|
import { open, connectDb } from '../orbitdb'
|
||||||
import { creatingBoard, createdBoard, boardError } from '../actions/board'
|
import { createdBoard, boardError } from '../actions/board'
|
||||||
import { getBoardIdFromAddress, shortenAddress } from '../utils/orbitdb'
|
import { shortenAddress } from '../utils/orbitdb'
|
||||||
import { UPDATE_BOARD } from '../actions/actionTypes'
|
import { UPDATE_BOARD } from '../actions/actionTypes'
|
||||||
|
|
||||||
export function* goToBoard({ board }){
|
export function* goToBoard({ board }){
|
||||||
@ -35,9 +35,13 @@ export function* openBoard({ board }) {
|
|||||||
const dbInfo = { address }
|
const dbInfo = { address }
|
||||||
dbInfo.posts = db.posts
|
dbInfo.posts = db.posts
|
||||||
dbInfo.metadata = db.metadata
|
dbInfo.metadata = db.metadata
|
||||||
const channel = yield call(createDbEventChannel, db)
|
try {
|
||||||
yield fork(watchDb, channel)
|
const channel = yield call(createDbEventChannel, db)
|
||||||
yield put(createdBoard(Object.assign({}, board, dbInfo)))
|
yield fork(watchDb, channel)
|
||||||
|
yield put(createdBoard(Object.assign({}, board, dbInfo)))
|
||||||
|
} catch (error) {
|
||||||
|
yield put({ type: 'ERROR', error })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,4 +5,45 @@ export async function ipfsPut(content) {
|
|||||||
}
|
}
|
||||||
const response = await window.ipfs.files.add(obj)
|
const response = await window.ipfs.files.add(obj)
|
||||||
return response[0].hash
|
return response[0].hash
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function readText(multihash) {
|
||||||
|
const buffer = await window.ipfs.object.get(multihash)
|
||||||
|
return buffer.toString('utf-8')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStats() {
|
||||||
|
const ipfs = window.ipfs;
|
||||||
|
const orbitDb = window.orbitDb
|
||||||
|
const dbs = {}
|
||||||
|
const stats = {}
|
||||||
|
if (ipfs) {
|
||||||
|
const peers = await ipfs.swarm.peers()
|
||||||
|
const id = await ipfs.id()
|
||||||
|
stats.peers = peers.map(p => p.peer.id._idB58String)
|
||||||
|
stats.id = id.id
|
||||||
|
}
|
||||||
|
if (orbitDb) {
|
||||||
|
stats.pubKey = await orbitDb.key.getPublic('hex')
|
||||||
|
Object.values(window.dbs || {}).forEach(db => {
|
||||||
|
let writeable = db.access.write.indexOf('*') >= 0 || db.access.write.indexOf(stats.pubKey) >= 0
|
||||||
|
const dbInfo = {
|
||||||
|
opLogLength: db._oplog.length,
|
||||||
|
access: {
|
||||||
|
admin: db.access.admin,
|
||||||
|
read: db.access.read,
|
||||||
|
write: db.access.write,
|
||||||
|
writeable
|
||||||
|
},
|
||||||
|
peers: []
|
||||||
|
}
|
||||||
|
const subscription = orbitDb._pubsub._subscriptions
|
||||||
|
if (subscription && subscription.room) {
|
||||||
|
dbInfo.peers = subscription.room._peers
|
||||||
|
}
|
||||||
|
dbs[db.address] = dbInfo
|
||||||
|
})
|
||||||
|
}
|
||||||
|
stats.dbs = dbs
|
||||||
|
return stats
|
||||||
}
|
}
|
@ -5862,6 +5862,10 @@ mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@~0.5.0, mkdi
|
|||||||
dependencies:
|
dependencies:
|
||||||
minimist "0.0.8"
|
minimist "0.0.8"
|
||||||
|
|
||||||
|
moment@^2.20.1:
|
||||||
|
version "2.20.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd"
|
||||||
|
|
||||||
moving-average@^1.0.0:
|
moving-average@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/moving-average/-/moving-average-1.0.0.tgz#b1247ba8dd2d7927c619f1eac8036cf933d65adc"
|
resolved "https://registry.yarnpkg.com/moving-average/-/moving-average-1.0.0.tgz#b1247ba8dd2d7927c619f1eac8036cf933d65adc"
|
||||||
|
Loading…
Reference in New Issue
Block a user