mirror of
https://github.com/fazo96/ipfs-boards
synced 2025-01-09 12:19:49 +01:00
implemented persistence with boards opened before
This commit is contained in:
parent
73eaff3b87
commit
e4b0a16cf0
@ -4,6 +4,7 @@ export const UPDATE_BOARD_METADATA = 'UPDATE_BOARD_METADATA'
|
||||
|
||||
export const OPEN_BOARD = 'OPEN_BOARD'
|
||||
export const OPENED_BOARD = 'OPENED_BOARD'
|
||||
export const CLOSE_BOARD = 'CLOSE_BOARD'
|
||||
|
||||
export const UPDATE_BOARD = 'UPDATE_BOARD'
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {
|
||||
OPEN_BOARD,
|
||||
CLOSE_BOARD,
|
||||
OPENED_BOARD,
|
||||
UPDATE_BOARD_METADATA
|
||||
} from './actionTypes'
|
||||
@ -25,3 +26,10 @@ export function updateBoardMetadata(address, metadata) {
|
||||
metadata
|
||||
}
|
||||
}
|
||||
|
||||
export function closeBoard(address) {
|
||||
return {
|
||||
type: CLOSE_BOARD,
|
||||
address
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ export default class BoardEditorForm extends Component {
|
||||
onChange={this.updateTitle.bind(this)}
|
||||
/>
|
||||
</Form.Field>
|
||||
<Form.Group fluid widths="equal">
|
||||
<Form.Group widths="equal">
|
||||
<Form.Field>
|
||||
<label>Website</label>
|
||||
<input
|
||||
|
@ -3,7 +3,7 @@ import { List, Icon, Segment, Divider, Grid, Header, Button, Card } from 'semant
|
||||
import { Link } from 'react-router-dom'
|
||||
import BoardsItem from './BoardsItem'
|
||||
|
||||
export default function Boards({ stats, boards, createBoard }) {
|
||||
export default function Boards({ stats, boards, createBoard, closeBoard }) {
|
||||
return <Grid container divided colums={2}>
|
||||
<Grid.Column width={8}>
|
||||
<Header size='large' style={{marginTop:'.5em'}}>
|
||||
@ -65,7 +65,7 @@ export default function Boards({ stats, boards, createBoard }) {
|
||||
</Grid.Column>
|
||||
<Grid.Column width={8} style={{paddingTop:'3em'}}>
|
||||
<Card.Group className="centered">
|
||||
{Object.values(boards).map(board => <BoardsItem key={board.address} {...board} />)}
|
||||
{Object.values(boards).map(board => <BoardsItem key={board.address} closeBoard={closeBoard} {...board} />)}
|
||||
{Object.keys(boards).length === 0 ? <Segment>No boards opened</Segment> : null}
|
||||
</Card.Group>
|
||||
</Grid.Column>
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import { List, Button, Card } from 'semantic-ui-react'
|
||||
import { Icon, List, Button, Card } from 'semantic-ui-react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { shortenAddress } from '../utils/orbitdb'
|
||||
|
||||
export default function BoardsItem({ address, metadata, name }) {
|
||||
export default function BoardsItem({ address, metadata, name, closeBoard }) {
|
||||
return <Card fluid>
|
||||
<Card.Content>
|
||||
<Card.Header>
|
||||
@ -29,8 +29,15 @@ export default function BoardsItem({ address, metadata, name }) {
|
||||
</List.Item>
|
||||
</List>
|
||||
</Card.Content>
|
||||
<Card.Content extra>
|
||||
<Button as={Link} to={shortenAddress(address)} basic fluid>View</Button>
|
||||
<Card.Content>
|
||||
<div className="ui two buttons">
|
||||
<Button onClick={() => closeBoard(address)} basic>
|
||||
<Icon name="close"/> Close
|
||||
</Button>
|
||||
<Button as={Link} to={shortenAddress(address)} basic>
|
||||
<Icon name="list"/> View
|
||||
</Button>
|
||||
</div>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
}
|
@ -43,7 +43,7 @@ export default class OpenBoardForm extends Component {
|
||||
<Button as={Link} to={'/'}>
|
||||
<Icon name="arrow left"/> Back
|
||||
</Button>
|
||||
<Button type="submit" onClick={() => openBoard({ address })}>
|
||||
<Button type="submit" onClick={() => openBoard({ address, redirect: true })}>
|
||||
<Icon name="plus"/> Open
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -3,11 +3,16 @@ import { connect } from 'react-redux'
|
||||
import { push } from 'react-router-redux'
|
||||
import BoardsComponent from '../components/Boards'
|
||||
import WithStats from './WithStats'
|
||||
import { closeBoard } from '../actions/board'
|
||||
|
||||
const WrappedComponent = WithStats(BoardsComponent)
|
||||
|
||||
function Boards({ boards, createBoard }) {
|
||||
return <WrappedComponent boards={boards} createBoard={createBoard} />
|
||||
function Boards({ boards, createBoard, closeBoard }) {
|
||||
return <WrappedComponent
|
||||
boards={boards}
|
||||
createBoard={createBoard}
|
||||
closeBoard={closeBoard}
|
||||
/>
|
||||
}
|
||||
|
||||
function mapStateToProps(state){
|
||||
@ -18,7 +23,8 @@ function mapStateToProps(state){
|
||||
|
||||
function mapDispatchToProps(dispatch){
|
||||
return {
|
||||
createBoard: () => dispatch(push('/b/new'))
|
||||
createBoard: () => dispatch(push('/b/new')),
|
||||
closeBoard: address => dispatch(closeBoard(address)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ function mapStateToProps(state){
|
||||
|
||||
function mapDispatchToProps(dispatch){
|
||||
return {
|
||||
openBoard: address => dispatch(openBoard({ address }))
|
||||
openBoard: address => dispatch(openBoard({ address, redirect: false }))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {
|
||||
OPENED_BOARD,
|
||||
CLOSE_BOARD,
|
||||
UPDATE_BOARD,
|
||||
ORBITDB_REPLICATE_PROGRESS,
|
||||
ORBITDB_REPLICATED,
|
||||
@ -18,12 +19,18 @@ function updateBoard(existingBoards, address, value) {
|
||||
})
|
||||
}
|
||||
|
||||
function deleteBoard(existingBoards, address) {
|
||||
const boards = Object.assign({}, existingBoards)
|
||||
delete boards[address]
|
||||
return boards
|
||||
}
|
||||
|
||||
export default function BoardsReducer(state = getInitialState(), action) {
|
||||
let address
|
||||
switch (action.type) {
|
||||
case OPENED_BOARD:
|
||||
address = action.board.address
|
||||
return Object.assign({}, state, { boards: updateBoard(state.boards, address, action.board) })
|
||||
return Object.assign({}, state, { boards: updateBoard(state.boards, address, Object.assign({}, action.board, { open: true })) })
|
||||
case UPDATE_BOARD:
|
||||
address = action.address
|
||||
let { posts, metadata } = action
|
||||
@ -45,6 +52,11 @@ export default function BoardsReducer(state = getInitialState(), action) {
|
||||
replicating: false,
|
||||
lastReplicated: action.time
|
||||
})})
|
||||
case CLOSE_BOARD:
|
||||
address = action.address
|
||||
return Object.assign({}, state, {
|
||||
boards: deleteBoard(state.boards, address)
|
||||
})
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -3,11 +3,14 @@ import { eventChannel } from 'redux-saga'
|
||||
import { push } from 'react-router-redux'
|
||||
import { open, connectDb } from '../orbitdb'
|
||||
import { createdBoard } from '../actions/board'
|
||||
import { shortenAddress } from '../utils/orbitdb'
|
||||
import { shortenAddress, closeBoard as closeOrbitDBBoard } from '../utils/orbitdb'
|
||||
import { UPDATE_BOARD } from '../actions/actionTypes'
|
||||
import { saveSaga } from './persistence'
|
||||
|
||||
export function* goToBoard({ board }){
|
||||
if (board.redirect) {
|
||||
yield put(push(shortenAddress(board.address)))
|
||||
}
|
||||
}
|
||||
|
||||
export function* updateBoard({ address }){
|
||||
@ -20,6 +23,11 @@ export function* updateBoard({ address }){
|
||||
})
|
||||
}
|
||||
|
||||
export function* closeBoard({ address }){
|
||||
yield call(closeOrbitDBBoard, address)
|
||||
yield saveSaga()
|
||||
}
|
||||
|
||||
export function* updateBoardMetadata({ address, metadata }){
|
||||
const db = window.dbs[address]
|
||||
if (db) {
|
||||
@ -47,7 +55,7 @@ export function* openBoard({ board }) {
|
||||
try {
|
||||
const channel = yield call(createDbEventChannel, db)
|
||||
yield fork(watchDb, channel)
|
||||
yield put(createdBoard(Object.assign({}, board, dbInfo)))
|
||||
yield put(createdBoard(Object.assign({ redirect: !!board.redirect }, board, dbInfo)))
|
||||
} catch (error) {
|
||||
yield put({ type: 'ERROR', error })
|
||||
}
|
||||
|
@ -1,15 +1,29 @@
|
||||
import { takeEvery } from 'redux-saga/effects'
|
||||
import { OPEN_BOARD, OPENED_BOARD, ADD_POST, ORBITDB_REPLICATED, ORBITDB_WRITE, UPDATE_BOARD_METADATA } from '../actions/actionTypes'
|
||||
import { openBoard, updateBoard, goToBoard, updateBoardMetadata } from './boards'
|
||||
import { takeEvery, put, call } from 'redux-saga/effects'
|
||||
import {
|
||||
OPEN_BOARD,
|
||||
OPENED_BOARD,
|
||||
CLOSE_BOARD,
|
||||
ADD_POST,
|
||||
ORBITDB_REPLICATED,
|
||||
ORBITDB_WRITE,
|
||||
UPDATE_BOARD_METADATA
|
||||
} from '../actions/actionTypes'
|
||||
import { openBoard, updateBoard, goToBoard, updateBoardMetadata, closeBoard } from './boards'
|
||||
import { openBoard as openBoardAction } from '../actions/board'
|
||||
import { addPost } from './posts'
|
||||
import { openPreviousBoards, saveSaga } from './persistence'
|
||||
|
||||
export default function* saga(){
|
||||
yield takeEvery(OPEN_BOARD, openBoard)
|
||||
yield takeEvery(OPENED_BOARD, goToBoard)
|
||||
yield takeEvery(OPENED_BOARD, saveSaga)
|
||||
yield takeEvery(CLOSE_BOARD, closeBoard)
|
||||
|
||||
yield takeEvery(ADD_POST, addPost)
|
||||
yield takeEvery(UPDATE_BOARD_METADATA, updateBoardMetadata)
|
||||
|
||||
yield takeEvery(ORBITDB_WRITE, updateBoard)
|
||||
yield takeEvery(ORBITDB_REPLICATED, updateBoard)
|
||||
|
||||
yield openPreviousBoards()
|
||||
}
|
16
src/sagas/persistence.js
Normal file
16
src/sagas/persistence.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { call, put } from 'redux-saga/effects'
|
||||
import { openBoard } from '../actions/board'
|
||||
import { save, load } from '../utils/persistence'
|
||||
|
||||
export function* openPreviousBoards() {
|
||||
const data = yield call(load)
|
||||
if (Array.isArray(data.addresses)) {
|
||||
for (const address of data.addresses) {
|
||||
yield put(openBoard({ address, redirect: false }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function* saveSaga() {
|
||||
yield call(save)
|
||||
}
|
@ -17,7 +17,7 @@ export async function getStats() {
|
||||
const orbitDb = window.orbitDb
|
||||
const dbs = {}
|
||||
const stats = {}
|
||||
if (ipfs) {
|
||||
if (ipfs && ipfs.isOnline()) {
|
||||
stats.ipfsLoaded = true
|
||||
const peers = await ipfs.swarm.peers()
|
||||
const id = await ipfs.id()
|
||||
@ -26,7 +26,7 @@ export async function getStats() {
|
||||
} else {
|
||||
stats.ipfsLoaded = false
|
||||
}
|
||||
if (orbitDb) {
|
||||
if (stats.ipfsLoaded && orbitDb) {
|
||||
stats.orbitDbLoaded = true
|
||||
stats.pubKey = await orbitDb.key.getPublic('hex')
|
||||
Object.values(window.dbs || {}).forEach(db => {
|
||||
|
@ -6,3 +6,9 @@ export function getBoardAddress(hash, name) {
|
||||
export function shortenAddress(address) {
|
||||
return address.replace(/^\/orbitdb/, '/b')
|
||||
}
|
||||
|
||||
export function closeBoard(address) {
|
||||
const db = window.dbs[address]
|
||||
delete window.dbs[address]
|
||||
if (db && db.close) db.close()
|
||||
}
|
16
src/utils/persistence.js
Normal file
16
src/utils/persistence.js
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
export function save(){
|
||||
const obj = {
|
||||
addresses: Object.keys(window.dbs || {})
|
||||
}
|
||||
localStorage.setItem('ipfs-boards-v0', JSON.stringify(obj))
|
||||
}
|
||||
|
||||
export function load(){
|
||||
const str = localStorage.getItem('ipfs-boards-v0')
|
||||
try {
|
||||
return JSON.parse(str) || {};
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user