1
0
mirror of https://github.com/fazo96/ipfs-boards synced 2025-01-09 12:19:49 +01:00

added board editing form and fixed metadata retrieval

This commit is contained in:
Enrico Fasoli 2018-02-09 01:20:53 +01:00
parent 718a99b225
commit db03079b55
No known key found for this signature in database
GPG Key ID: 1238873C5F27DB4D
12 changed files with 128 additions and 25 deletions

View File

@ -1,15 +1,16 @@
export const ADD_POST = 'ADD_POST' export const ADD_POST = 'ADD_POST'
export const UPDATE_BOARD_METADATA = 'UPDATE_BOARD_METADATA'
export const OPEN_BOARD = 'OPEN_BOARD' export const OPEN_BOARD = 'OPEN_BOARD'
export const OPENED_BOARD = 'OPENED_BOARD' export const OPENED_BOARD = 'OPENED_BOARD'
export const UPDATE_BOARD = 'UPDATE_BOARD' export const UPDATE_BOARD = 'UPDATE_BOARD'
export const BOARD_ERROR = 'BOARD_ERROR'
export const ORBITDB_WRITE = 'ORBITDB_WRITE' export const ORBITDB_WRITE = 'ORBITDB_WRITE'
export const ORBITDB_REPLICATE = 'ORBITDB_REPLICATE' export const ORBITDB_REPLICATE = 'ORBITDB_REPLICATE'
export const ORBITDB_REPLICATE_PROGRESS = 'ORBITDB_REPLICATE_PROGRESS' export const ORBITDB_REPLICATE_PROGRESS = 'ORBITDB_REPLICATE_PROGRESS'
export const ORBITDB_REPLICATED = 'ORBITDB_REPLICATED' export const ORBITDB_REPLICATED = 'ORBITDB_REPLICATED'
export const ERROR = 'ERROR'

View File

@ -1,7 +1,7 @@
import { import {
OPEN_BOARD, OPEN_BOARD,
OPENED_BOARD, OPENED_BOARD,
BOARD_ERROR UPDATE_BOARD_METADATA
} from './actionTypes' } from './actionTypes'
export function openBoard(board) { export function openBoard(board) {
@ -18,9 +18,10 @@ export function createdBoard(board) {
} }
} }
export function boardError(error) { export function updateBoardMetadata(address, metadata) {
return { return {
type: BOARD_ERROR, type: UPDATE_BOARD_METADATA,
error address,
metadata
} }
} }

View File

@ -90,7 +90,7 @@ export default function Board({ address, posts, metadata, replicating, stats, re
<Button as={Link} to={'/'}> <Button as={Link} to={'/'}>
<Icon name='left arrow'/> Boards <Icon name='left arrow'/> Boards
</Button> </Button>
<Button disabled={!writeable}> <Button disabled={!writeable} as={Link} to={shortenAddress(address)+'/edit'}>
<Icon name='pencil'/> Edit <Icon name='pencil'/> Edit
</Button> </Button>
<Button disabled={!writeable} as={Link} to={shortenAddress(address)+'/p/new'}> <Button disabled={!writeable} as={Link} to={shortenAddress(address)+'/p/new'}>

View File

@ -0,0 +1,49 @@
import React, { Component } from 'react'
import { Icon, Container, Card, Form, Button } from 'semantic-ui-react'
export default class BoardEditorForm extends Component {
constructor(props){
super(props)
this.state = {
title: props.title || ''
}
}
render() {
const { title } = this.state
const { address, updateBoardMetadata } = this.props
return <Container>
<Card fluid centered style={{marginTop:'5em',maxWidth:'40em'}}>
<Card.Content>
<Card.Header>Edit Board</Card.Header>
<Card.Meta>
Boards is an experimental peer to peer application.<br/>
All content you publish will be public and may be lost or
changed at any time.<br/>
Please do not use this version of Boards
for anything other than testing purposes
</Card.Meta>
</Card.Content>
<Card.Content>
<Form>
<Form.Field>
<label>Title</label>
<input
value={title}
onChange={this.updateTitle.bind(this)}
/>
</Form.Field>
<Button fluid onClick={() => updateBoardMetadata(address, this.state)}>
<Icon name="save"/> Save
</Button>
</Form>
</Card.Content>
</Card>
</Container>
}
updateTitle(event) {
const title = event.target.value
this.setState({ title })
}
}

View File

@ -1,7 +1,7 @@
import React from 'react' 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 BoardEditor from '../containers/Board' import BoardEditor from '../containers/BoardEditor'
import PostEditor from '../containers/PostEditor' import PostEditor from '../containers/PostEditor'
import WithStats from '../containers/WithStats' import WithStats from '../containers/WithStats'

View File

@ -7,7 +7,7 @@ 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'}}>
<Icon name="cube" color="blue" circular verticalAlign="middle" floated="right"/> <Icon name="cube" color="blue" circular/>
<Header.Content> <Header.Content>
<Header.Content>IPFS Boards</Header.Content> <Header.Content>IPFS Boards</Header.Content>
<Header.Subheader>Experimental Build</Header.Subheader> <Header.Subheader>Experimental Build</Header.Subheader>

View File

@ -3,11 +3,11 @@ import { 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'
export default function BoardsItem({ address, title, name }) { export default function BoardsItem({ address, metadata, name }) {
return <Card fluid> return <Card fluid>
<Card.Content> <Card.Content>
<Card.Header> <Card.Header>
{ title || 'Unnamed board' } { metadata.title || 'Unnamed board' }
</Card.Header> </Card.Header>
<Card.Meta>Board</Card.Meta> <Card.Meta>Board</Card.Meta>
</Card.Content> </Card.Content>

View File

@ -0,0 +1,36 @@
import React from 'react'
import { connect } from 'react-redux'
import BoardEditorForm from '../components/BoardEditorForm'
import { updateBoardMetadata } from '../actions/board'
import { getBoardAddress } from '../utils/orbitdb'
function BoardEditor({ boards, boardEditor, match, updateBoardMetadata }) {
const { hash, name } = match.params
const address = getBoardAddress(hash, name)
const board = boards[address]
return <BoardEditorForm
board={board}
address={address}
updateBoardMetadata={updateBoardMetadata}
{...boardEditor}
/>
}
function mapStateToProps(state){
return {
boards: state.boards.boards,
boardEditor: state.boardEditor
}
}
function mapDispatchToProps(dispatch) {
return {
updateBoardMetadata: (address, metadata) => dispatch(updateBoardMetadata(address, metadata))
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(BoardEditor)

View File

@ -12,7 +12,7 @@ export default function(WrappedComponent) {
pubKey: '?', pubKey: '?',
dbs: {} dbs: {}
}, },
interval: null timeout: null
} }
} }
@ -23,10 +23,9 @@ export default function(WrappedComponent) {
} }
refreshDelayed() { refreshDelayed() {
const timeout = setTimeout(() => { this.timeout = setTimeout(() => {
this.refresh() this.refresh()
}, 2000) }, 2000)
this.setState({ timeout })
} }
componentDidMount() { componentDidMount() {
@ -34,7 +33,7 @@ export default function(WrappedComponent) {
} }
componentWillUnmount() { componentWillUnmount() {
if (this.state.interval) clearInterval(this.state.interval) if (this.timeout) clearTimeout(this.timeout)
} }
render() { render() {

View File

@ -1,8 +1,8 @@
import { put, call, fork, take } from 'redux-saga/effects' import { put, call, fork, take, apply } 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 { createdBoard, boardError } from '../actions/board' import { createdBoard } from '../actions/board'
import { shortenAddress } from '../utils/orbitdb' import { shortenAddress } from '../utils/orbitdb'
import { UPDATE_BOARD } from '../actions/actionTypes' import { UPDATE_BOARD } from '../actions/actionTypes'
@ -16,25 +16,33 @@ export function* updateBoard({ address }){
type: UPDATE_BOARD, type: UPDATE_BOARD,
address, address,
posts: db.posts, posts: db.posts,
metadata: db.metadata, metadata: Object.assign({}, db._index._index.metadata) // TODO: fix in lib and use db.metadata
syncRequestsReceived: db._stats.syncRequestsReceived,
opLogLength: db._oplog.length
}) })
} }
export function* updateBoardMetadata({ address, metadata }){
const db = window.dbs[address]
if (db) {
yield apply(db, db.updateMetadata, [metadata])
yield goToBoard({ board: { address } });
} else {
yield put({ type: 'ERROR', error: address + ' not found' })
}
}
export function* openBoard({ board }) { export function* openBoard({ board }) {
let db let db
try { try {
const metadata = board.title ? { title: board.title } : null const metadata = board.title ? { title: board.title } : null
db = yield call(open, board.address, metadata) db = yield call(open, board.address, metadata)
} catch (error) { } catch (error) {
yield put(boardError(error)) yield put({ type: 'ERROR', error })
} }
if (db) { if (db) {
const address = db.address.toString() const address = db.address.toString()
const dbInfo = { address } const dbInfo = { address }
dbInfo.posts = db.posts dbInfo.posts = db.posts
dbInfo.metadata = db.metadata dbInfo.metadata = Object.assign({}, db._index._index.metadata) // TODO: fix in lib and use db.metadata
dbInfo.name = db.dbname dbInfo.name = db.dbname
try { try {
const channel = yield call(createDbEventChannel, db) const channel = yield call(createDbEventChannel, db)

View File

@ -1,12 +1,15 @@
import { takeEvery } from 'redux-saga/effects' import { takeEvery } from 'redux-saga/effects'
import { OPEN_BOARD, OPENED_BOARD, ADD_POST, ORBITDB_REPLICATED, ORBITDB_WRITE } from '../actions/actionTypes' import { OPEN_BOARD, OPENED_BOARD, ADD_POST, ORBITDB_REPLICATED, ORBITDB_WRITE, UPDATE_BOARD_METADATA } from '../actions/actionTypes'
import { openBoard, updateBoard, goToBoard } from './boards' import { openBoard, updateBoard, goToBoard, updateBoardMetadata } from './boards'
import { addPost } from './posts' import { addPost } from './posts'
export default function* saga(){ export default function* saga(){
yield takeEvery(OPEN_BOARD, openBoard) yield takeEvery(OPEN_BOARD, openBoard)
yield takeEvery(OPENED_BOARD, goToBoard) yield takeEvery(OPENED_BOARD, goToBoard)
yield takeEvery(ADD_POST, addPost) yield takeEvery(ADD_POST, addPost)
yield takeEvery(UPDATE_BOARD_METADATA, updateBoardMetadata)
yield takeEvery(ORBITDB_WRITE, updateBoard) yield takeEvery(ORBITDB_WRITE, updateBoard)
yield takeEvery(ORBITDB_REPLICATED, updateBoard) yield takeEvery(ORBITDB_REPLICATED, updateBoard)
} }

View File

@ -18,12 +18,16 @@ export async function getStats() {
const dbs = {} const dbs = {}
const stats = {} const stats = {}
if (ipfs) { if (ipfs) {
stats.ipfsLoaded = true
const peers = await ipfs.swarm.peers() const peers = await ipfs.swarm.peers()
const id = await ipfs.id() const id = await ipfs.id()
stats.peers = peers.map(p => p.peer.id._idB58String) stats.peers = peers.map(p => p.peer.id._idB58String)
stats.id = id.id stats.id = id.id
} else {
stats.ipfsLoaded = false
} }
if (orbitDb) { if (orbitDb) {
stats.orbitDbLoaded = true
stats.pubKey = await orbitDb.key.getPublic('hex') stats.pubKey = await orbitDb.key.getPublic('hex')
Object.values(window.dbs || {}).forEach(db => { Object.values(window.dbs || {}).forEach(db => {
let writeable = db.access.write.indexOf('*') >= 0 || db.access.write.indexOf(stats.pubKey) >= 0 let writeable = db.access.write.indexOf('*') >= 0 || db.access.write.indexOf(stats.pubKey) >= 0
@ -43,6 +47,8 @@ export async function getStats() {
} }
dbs[db.address] = dbInfo dbs[db.address] = dbInfo
}) })
} else {
stats.orbitDbLoaded = false
} }
stats.dbs = dbs stats.dbs = dbs
return stats return stats