diff --git a/src/actions/actionTypes.js b/src/actions/actionTypes.js index eb42ca8..88a9ab1 100644 --- a/src/actions/actionTypes.js +++ b/src/actions/actionTypes.js @@ -1,9 +1,8 @@ export const ADD_POST = 'ADD_POST' -export const CREATE_BOARD = 'CREATE_BOARD' -export const CREATING_BOARD = 'CREATING_BOARD' -export const CREATED_BOARD = 'CREATED_BOARD' +export const OPEN_BOARD = 'OPEN_BOARD' +export const OPENED_BOARD = 'OPENED_BOARD' export const UPDATE_BOARD = 'UPDATE_BOARD' diff --git a/src/actions/board.js b/src/actions/board.js index 2ca6f14..3b0f484 100644 --- a/src/actions/board.js +++ b/src/actions/board.js @@ -1,27 +1,19 @@ import { - CREATE_BOARD, - CREATING_BOARD, - CREATED_BOARD, + OPEN_BOARD, + OPENED_BOARD, BOARD_ERROR } from './actionTypes' -export function createBoard(board) { +export function openBoard(board) { return { - type: CREATE_BOARD, - board - } -} - -export function creatingBoard(board) { - return { - type: CREATING_BOARD, + type: OPEN_BOARD, board } } export function createdBoard(board) { return { - type: CREATED_BOARD, + type: OPENED_BOARD, board } } diff --git a/src/actions/post.js b/src/actions/post.js index 8cf3f70..380c2bf 100644 --- a/src/actions/post.js +++ b/src/actions/post.js @@ -1,9 +1,9 @@ import { ADD_POST } from './actionTypes' -export function addPost(boardId, post) { +export function addPost(address, post) { return { type: ADD_POST, post, - boardId + address } } \ No newline at end of file diff --git a/src/components/App.js b/src/components/App.js index 0b75765..5104225 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,9 +1,9 @@ import React, { Component } from 'react'; import { Switch, Route, withRouter } from 'react-router-dom' import Boards from '../containers/Boards' -import PostEditor from '../containers/PostEditor' import BoardEditor from '../containers/BoardEditor' -import Board from '../containers/Board' +import WithBoard from '../containers/WithBoard' +import BoardPage from '../components/BoardPage' import 'semantic-ui-css/semantic.css' class App extends Component { @@ -11,8 +11,7 @@ class App extends Component { return ( - - + ) diff --git a/src/components/Board.js b/src/components/Board.js index 02b5aa8..58e0550 100644 --- a/src/components/Board.js +++ b/src/components/Board.js @@ -2,13 +2,14 @@ import React from 'react' import Post from './Post' import { Segment, Button } from 'semantic-ui-react' import { Link } from 'react-router-dom' +import { shortenAddress } from '../utils/orbitdb'; -export default function Board({ id, posts }) { +export default function Board({ address, posts }) { return
- {id} - + {address} + - +
} \ No newline at end of file diff --git a/src/components/BoardForm.js b/src/components/BoardForm.js index 93daa18..4b16885 100644 --- a/src/components/BoardForm.js +++ b/src/components/BoardForm.js @@ -5,29 +5,30 @@ export default class BoardForm extends Component { constructor(props){ super(props) this.state = { - title: props.title || '' + address: props.address || '' } } - updateTitle(event) { - this.setState({ title: event.target.value }) + updateAddress(event) { + const address = event.target.value + this.setState({ address }) } render() { - const { title, content } = this.state + const { address } = this.state const { onSave, creating } = this.props return
- + {creating ? 'Creating the board...' : ''} diff --git a/src/components/BoardPage.js b/src/components/BoardPage.js new file mode 100644 index 0000000..5cdb210 --- /dev/null +++ b/src/components/BoardPage.js @@ -0,0 +1,13 @@ +import React from 'react' +import { Switch, Route } from 'react-router-dom' +import Board from '../containers/Board' +import PostEditor from '../containers/PostEditor' + +function BoardPage({ match, address, posts, metadata }) { + return + + + +} + +export default BoardPage \ No newline at end of file diff --git a/src/components/Boards.js b/src/components/Boards.js index 56cb125..ab5b50d 100644 --- a/src/components/Boards.js +++ b/src/components/Boards.js @@ -1,11 +1,12 @@ import React from 'react' -import { List } from 'semantic-ui-react' +import { Button, Card } from 'semantic-ui-react' import BoardsItem from './BoardsItem' -import { Button } from 'semantic-ui-react' export default function Boards({ boards, createBoard }) { - return - {Object.values(boards).map(board => )} + return
+ + {Object.values(boards).map(board => )} + - +
} \ No newline at end of file diff --git a/src/components/BoardsItem.js b/src/components/BoardsItem.js index cb57f6a..2553a79 100644 --- a/src/components/BoardsItem.js +++ b/src/components/BoardsItem.js @@ -1,13 +1,23 @@ import React from 'react' -import { List } from 'semantic-ui-react' +import { Button, Card } from 'semantic-ui-react' import { Link } from 'react-router-dom' +import { shortenAddress } from '../utils/orbitdb' -export default function BoardsItem({ id, title }) { - return - - - {title} - Experimental - - +export default function BoardsItem({ address, title }) { + return + + + { title || 'Untitled board' } + + + Board + + + {address} + + + + + + } \ No newline at end of file diff --git a/src/containers/Board.js b/src/containers/Board.js index 361a795..43fdac6 100644 --- a/src/containers/Board.js +++ b/src/containers/Board.js @@ -1,28 +1,11 @@ -import React, { Component } from 'react' +import React from 'react' import { connect } from 'react-redux' -import { push } from 'react-router-redux' import BoardComponent from '../components/Board' -import { createBoard } from '../actions/board' +import { getBoardAddress } from '../utils/orbitdb' -class Board extends Component { - - componentDidMount() { - const { boards, match } = this.props - if (!boards[match.params.boardId]) { - this.props.openBoard(match.params.boardId) - } - } - - render() { - const { boards, match } = this.props - const id = match.params.boardId - const board = boards[id] - if (board) { - return - } else { - return
Opening this board...
- } - } +function Board({ location, match, boards }) { + const { hash, name } = match.params + return } function mapStateToProps(state){ @@ -31,13 +14,6 @@ function mapStateToProps(state){ } } -function mapDispatchToProps(dispatch){ - return { - openBoard: id => dispatch(createBoard(id)) - } -} - export default connect( - mapStateToProps, - mapDispatchToProps + mapStateToProps )(Board) diff --git a/src/containers/BoardEditor.js b/src/containers/BoardEditor.js index 846b44c..793aa73 100644 --- a/src/containers/BoardEditor.js +++ b/src/containers/BoardEditor.js @@ -1,10 +1,10 @@ import React from 'react' import { connect } from 'react-redux' import BoardForm from '../components/BoardForm' -import { createBoard } from '../actions/board' +import { openBoard } from '../actions/board' -function BoardEditor({ board, createBoard }) { - return +function BoardEditor({ board, openBoard }) { + return } function mapStateToProps(state){ @@ -15,7 +15,7 @@ function mapStateToProps(state){ function mapDispatchToProps(dispatch) { return { - createBoard: board => dispatch(createBoard(board)) + openBoard: board => dispatch(openBoard(board)) } } diff --git a/src/containers/PostEditor.js b/src/containers/PostEditor.js index 03cca4f..bfb979c 100644 --- a/src/containers/PostEditor.js +++ b/src/containers/PostEditor.js @@ -2,12 +2,13 @@ import React, { Component } from 'react' import { connect } from 'react-redux' import PostForm from '../components/PostForm' import { addPost } from '../actions/post' +import { getBoardAddress } from '../utils/orbitdb'; class PostEditor extends Component { render() { const { post, addPost, match } = this.props - const { boardId } = match.params - return addPost(boardId, p)} /> + const address = getBoardAddress(match.params.hash, match.params.name) + return addPost(address, p)} /> } } @@ -19,7 +20,7 @@ function mapStateToProps(state){ function mapDispatchToProps(dispatch) { return { - addPost: (boardId, post) => dispatch(addPost(boardId, post)) + addPost: (address, post) => dispatch(addPost(address, post)) } } diff --git a/src/containers/WithBoard.js b/src/containers/WithBoard.js new file mode 100644 index 0000000..36a73a7 --- /dev/null +++ b/src/containers/WithBoard.js @@ -0,0 +1,53 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' +import { openBoard } from '../actions/board' +import { getBoardAddress } from '../utils/orbitdb' + +function mapStateToProps(state){ + return { + boards: state.boards.boards + } +} + +function mapDispatchToProps(dispatch){ + return { + openBoard: address => dispatch(openBoard({ address })) + } +} + +export default function WithBoard(WrappedComponent) { + class ToExport extends Component { + + componentDidMount() { + const { boards, match } = this.props + const address = getBoardAddress(match.params.hash, match.params.name) + if (!boards[address]) { + this.props.openBoard(address) + } + } + + componentWillReceiveProps({ match, boards }) { + const address = getBoardAddress(match.params.hash, match.params.name) + if (!boards[address]) { + this.props.openBoard(address) + } + } + + render() { + const { boards, match } = this.props + const address = getBoardAddress(match.params.hash, match.params.name) + const board = boards[address] + if (board) { + return + } else { + return
Opening this board...
+ } + } + } + + return connect( + mapStateToProps, + mapDispatchToProps + )(ToExport) + +} \ No newline at end of file diff --git a/src/orbitdb/index.js b/src/orbitdb/index.js index 78f2480..e57363c 100644 --- a/src/orbitdb/index.js +++ b/src/orbitdb/index.js @@ -11,7 +11,7 @@ export function isValidID(id) { return false } -export async function open(id, metadata, options = {}) { +export async function open(address, metadata) { if (!window.ipfs) { const IPFS = await import('ipfs') window.ipfs = new IPFS({ @@ -38,24 +38,18 @@ export async function open(id, metadata, options = {}) { OrbitDB.addDatabaseType(BoardStore.type, BoardStore) window.orbitDb = new OrbitDB(window.ipfs) } - const defaultOptions = { - create: id === undefined, - type: BoardStore.type - } - let address - if (!id) { - address = 'board-v0' - } else if (!isValidID(id)) { - throw new Error('invalid address') + const options = { + type: BoardStore.type, + create: true } try { - const db = await window.orbitDb.open(address, Object.assign(defaultOptions, options)) + const db = await window.orbitDb.open(address, options) await db.load() - if (metadata && defaultOptions.create) { + if (metadata) { await db.updateMetadata(metadata) } if (!window.dbs) window.dbs = {} - window.dbs[getBoardIdFromAddress(db.address.toString())] = db + window.dbs[db.address.toString()] = db return db } catch (error) { console.log(error) @@ -66,7 +60,7 @@ export function connectDb(db, dispatch) { db.events.on('write', (dbname, hash, entry) => { dispatch({ type: 'ORBITDB_WRITE', - id: getBoardIdFromAddress(db.address.toString()), + address: db.address.toString(), hash, entry }) @@ -74,13 +68,13 @@ export function connectDb(db, dispatch) { db.events.on('replicated', address => { dispatch({ type: 'ORBITDB_REPLICATED', - id: getBoardIdFromAddress(db.address.toString()) + address: db.address.toString() }) }) db.events.on('replicate.progress', (address, hash, entry, progress, have) => { dispatch({ type: 'ORBITDB_REPLICATE_PROGRESS', - id: getBoardIdFromAddress(db.address.toString()), + address: db.address.toString(), hash, entry, progress, @@ -90,25 +84,25 @@ export function connectDb(db, dispatch) { db.events.on('replicate', address => { dispatch({ type: 'ORBITDB_REPLICATE', - id: getBoardIdFromAddress(db.address.toString()) + address: db.address.toString() }) }) db.events.on('close', address => { dispatch({ type: 'ORBITDB_CLOSE', - id: getBoardIdFromAddress(db.address.toString()) + address: db.address.toString() }) }) db.events.on('load', address => { dispatch({ type: 'ORBITDB_LOAD', - id: getBoardIdFromAddress(db.address.toString()) + address: db.address.toString() }) }) db.events.on('load.progress', (address, hash, entry, progress, total) => { dispatch({ type: 'ORBITDB_LOAD_PROGRESS', - id: getBoardIdFromAddress(db.address.toString()), + address: db.address.toString(), hash, entry, progress, diff --git a/src/reducers/boardEditor.js b/src/reducers/boardEditor.js index 5b0e041..2f9267c 100644 --- a/src/reducers/boardEditor.js +++ b/src/reducers/boardEditor.js @@ -1,13 +1,12 @@ import { - CREATE_BOARD, - CREATING_BOARD, - CREATED_BOARD + OPEN_BOARD, + OPENED_BOARD } from '../actions/actionTypes' function getInitialState() { return { board: { - title: '' + name: '' }, creating: false } @@ -15,12 +14,10 @@ function getInitialState() { export default function BoardEditorReducer(state = getInitialState(), action) { switch (action.type) { - case CREATE_BOARD: - return Object.assign({}, state, { board: action.board, creating: false }) - case CREATING_BOARD: - return Object.assign({}, state, { creating: true }) - case CREATED_BOARD: - return Object.assign({}, state, { creating: false }) + case OPEN_BOARD: + return Object.assign({}, state, { board: action.board, opening: true }) + case OPENED_BOARD: + return Object.assign({}, state, { opening: false, board: action.board }) default: return state } diff --git a/src/reducers/boards.js b/src/reducers/boards.js index 5a5c872..35d6261 100644 --- a/src/reducers/boards.js +++ b/src/reducers/boards.js @@ -1,4 +1,4 @@ -import { CREATED_BOARD, UPDATE_BOARD } from '../actions/actionTypes' +import { OPENED_BOARD, UPDATE_BOARD } from '../actions/actionTypes' import { getBoardIdFromAddress } from '../utils/orbitdb' function getInitialState() { @@ -8,22 +8,17 @@ function getInitialState() { } export default function BoardsReducer(state = getInitialState(), action) { - let id, newBoards + let address, newBoards switch (action.type) { - case CREATED_BOARD: - id = getBoardIdFromAddress(action.board.address) - const board = { - id, - posts: {} - } - newBoards = Object.assign({}, state.boards, { [id]: board }) + case OPENED_BOARD: + address = action.board.address + newBoards = Object.assign({}, state.boards, { [address]: action.board }) return Object.assign({}, state, { boards: newBoards }) case UPDATE_BOARD: - id = action.boardId - let { posts } = action - console.log(state, action) + address = action.address + let { posts, metadata } = action newBoards = Object.assign({}, state.boards, { - [id]: Object.assign({}, state.boards[id], { posts }) + [address]: Object.assign({}, state.boards[address], { posts, metadata }) }) return Object.assign({}, state, { boards: newBoards }) default: diff --git a/src/sagas/boards.js b/src/sagas/boards.js index e778c13..513ca87 100644 --- a/src/sagas/boards.js +++ b/src/sagas/boards.js @@ -6,36 +6,32 @@ import { creatingBoard, createdBoard, boardError } from '../actions/board' import { getBoardIdFromAddress } from '../utils/orbitdb' import { UPDATE_BOARD } from '../actions/actionTypes' -export function* updateBoard({ id }){ - const db = window.dbs[id] +export function* updateBoard({ address }){ + const db = window.dbs[address] yield put({ type: UPDATE_BOARD, - boardId: id, + address, posts: db.posts, metadata: db.metadata }) } -export function* createBoard({ board }) { - yield put(creatingBoard(board)) +export function* openBoard({ board }) { let db try { - db = yield call(open, board.id, { - title: board.title - }) + const metadata = board.title ? { title: board.title } : null + db = yield call(open, board.address, metadata) } catch (error) { yield put(boardError(error)) } if (db) { const address = db.address.toString() - const dbInfo = { - id: getBoardIdFromAddress(address), - address - } + const dbInfo = { address } + dbInfo.posts = db.posts + dbInfo.metadata = db.metadata const channel = yield call(createDbEventChannel, db) yield fork(watchDb, channel) yield put(createdBoard(Object.assign({}, board, dbInfo))) - yield put(push('/b/' + dbInfo.id + '/')) } } diff --git a/src/sagas/index.js b/src/sagas/index.js index 4e42f00..399bb6f 100644 --- a/src/sagas/index.js +++ b/src/sagas/index.js @@ -1,10 +1,10 @@ import { takeEvery } from 'redux-saga/effects' -import { CREATE_BOARD, ADD_POST, ORBITDB_REPLICATED, ORBITDB_WRITE } from '../actions/actionTypes' -import { createBoard, updateBoard } from './boards' +import { OPEN_BOARD, ADD_POST, ORBITDB_REPLICATED, ORBITDB_WRITE } from '../actions/actionTypes' +import { openBoard, updateBoard } from './boards' import { addPost } from './posts' export default function* saga(){ - yield takeEvery(CREATE_BOARD, createBoard) + yield takeEvery(OPEN_BOARD, openBoard) yield takeEvery(ADD_POST, addPost) yield takeEvery(ORBITDB_WRITE, updateBoard) yield takeEvery(ORBITDB_REPLICATED, updateBoard) diff --git a/src/sagas/posts.js b/src/sagas/posts.js index 25f57a5..e79d78e 100644 --- a/src/sagas/posts.js +++ b/src/sagas/posts.js @@ -1,8 +1,8 @@ -import { put, apply, call } from 'redux-saga/effects' +import { apply, call } from 'redux-saga/effects' import { ipfsPut } from '../utils/ipfs' -export function* addPost({ boardId, post }) { - const db = window.dbs[boardId] +export function* addPost({ address, post }) { + const db = window.dbs[address] const { title, content } = post const multihash = yield call(ipfsPut, content) yield apply(db, db.addPost, [title, multihash]) diff --git a/src/utils/orbitdb.js b/src/utils/orbitdb.js index cfe070a..31181cf 100644 --- a/src/utils/orbitdb.js +++ b/src/utils/orbitdb.js @@ -1,6 +1,8 @@ -export function getBoardIdFromAddress(address) { - const match = /\/orbitdb\/(.+)\//.exec(address) - if (match[1]) return match[1] - return undefined +export function getBoardAddress(hash, name) { + return '/orbitdb/' + hash + '/' + name +} + +export function shortenAddress(address) { + return address.replace(/^\/orbitdb/, '/b') } \ No newline at end of file