mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-01-10 12:24:20 +01:00
added board editing form and fixed metadata retrieval
This commit is contained in:
parent
718a99b225
commit
db03079b55
@ -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'
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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'}>
|
||||||
|
49
src/components/BoardEditorForm.js
Normal file
49
src/components/BoardEditorForm.js
Normal 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 })
|
||||||
|
}
|
||||||
|
}
|
@ -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'
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
36
src/containers/BoardEditor.js
Normal file
36
src/containers/BoardEditor.js
Normal 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)
|
@ -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() {
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user